From d58288da6de565882c9045cae8afa731578c2222 Mon Sep 17 00:00:00 2001
From: LevelX2 <ludwig.hirth@online.de>
Date: Tue, 20 Oct 2015 17:16:13 +0200
Subject: [PATCH] Some changes to RedirectionEffect class. Fixed that Harm's
 Way and Shaman en-Kor prevented the damage instead of only redirecting the
 damage.

---
 .../src/mage/sets/fatereforged/WildSlash.java |   8 +-
 .../src/mage/sets/magic2010/HarmsWay.java     | 101 +++++--------
 .../src/mage/sets/stronghold/NomadsEnKor.java |   2 +-
 .../src/mage/sets/stronghold/ShamanEnKor.java | 139 +++++-------------
 .../HarmsWayRedirectDamageTest.java           |  53 ++++++-
 .../replacement/redirect/ShamenEnKorTest.java |  94 ++++++++++++
 .../abilities/effects/RedirectionEffect.java  |  75 +++++++---
 7 files changed, 272 insertions(+), 200 deletions(-)
 rename Mage.Tests/src/test/java/org/mage/test/cards/replacement/{prevent => redirect}/HarmsWayRedirectDamageTest.java (57%)
 create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/ShamenEnKorTest.java

diff --git a/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java b/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java
index 054006c589..b2e5a66527 100644
--- a/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java
+++ b/Mage.Sets/src/mage/sets/fatereforged/WildSlash.java
@@ -29,7 +29,6 @@ package mage.sets.fatereforged;
 
 import java.util.UUID;
 import mage.abilities.Ability;
-import mage.abilities.common.SimpleStaticAbility;
 import mage.abilities.condition.LockedInCondition;
 import mage.abilities.condition.common.FerociousCondition;
 import mage.abilities.decorator.ConditionalContinuousRuleModifyingEffect;
@@ -41,7 +40,6 @@ import mage.constants.CardType;
 import mage.constants.Duration;
 import mage.constants.Outcome;
 import mage.constants.Rarity;
-import mage.constants.Zone;
 import mage.game.Game;
 import mage.game.events.GameEvent;
 import mage.target.common.TargetCreatureOrPlayer;
@@ -60,12 +58,12 @@ public class WildSlash extends CardImpl {
         ContinuousRuleModifyingEffect effect = new DamageCantBePreventedEffect();
         effect.setText("<i>Ferocious</i> &mdash; If you control a creature with power 4 or greater, damage can't be prevented this turn.<br>");
         this.getSpellAbility().addEffect(new ConditionalContinuousRuleModifyingEffect(effect,
-                        new LockedInCondition(FerociousCondition.getInstance())));
-        
+                new LockedInCondition(FerociousCondition.getInstance())));
+
         // Wild Slash deals 2 damage to target creature or player.
         this.getSpellAbility().addEffect(new DamageTargetEffect(2));
         this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());
-        
+
     }
 
     public WildSlash(final WildSlash card) {
diff --git a/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java b/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java
index 12a58405a4..11cf5c7c68 100644
--- a/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java
+++ b/Mage.Sets/src/mage/sets/magic2010/HarmsWay.java
@@ -30,8 +30,7 @@ package mage.sets.magic2010;
 import java.util.UUID;
 import mage.MageObject;
 import mage.abilities.Ability;
-import mage.abilities.effects.PreventionEffectData;
-import mage.abilities.effects.PreventionEffectImpl;
+import mage.abilities.effects.RedirectionEffect;
 import mage.cards.CardImpl;
 import mage.constants.CardType;
 import mage.constants.Duration;
@@ -69,91 +68,65 @@ public class HarmsWay extends CardImpl {
     }
 }
 
-class HarmsWayPreventDamageTargetEffect extends PreventionEffectImpl {
-    
-    private final TargetSource target;
-    
+class HarmsWayPreventDamageTargetEffect extends RedirectionEffect {
+
+    private final TargetSource damageSource;
+
     public HarmsWayPreventDamageTargetEffect() {
-        super(Duration.EndOfTurn, 2, false, true);
+        super(Duration.EndOfTurn, 2, true);
         staticText = "The next 2 damage that a source of your choice would deal to you and/or permanents you control this turn is dealt to target creature or player instead";
-        this.target = new TargetSource();
+        this.damageSource = new TargetSource();
     }
 
     public HarmsWayPreventDamageTargetEffect(final HarmsWayPreventDamageTargetEffect effect) {
         super(effect);
-        this.target = effect.target.copy();
+        this.damageSource = effect.damageSource.copy();
     }
 
     @Override
     public HarmsWayPreventDamageTargetEffect copy() {
         return new HarmsWayPreventDamageTargetEffect(this);
     }
-    
+
     @Override
     public void init(Ability source, Game game) {
-        this.target.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
+        this.damageSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game);
         super.init(source, game);
     }
 
     @Override
-    public boolean replaceEvent(GameEvent event, Ability source, Game game) {
-        PreventionEffectData preventionData = preventDamageAction(event, source, game);
-        // deal damage now
-        if (preventionData.getPreventedDamage() > 0) {
-            UUID redirectTo = source.getFirstTarget();
-            Permanent permanent = game.getPermanent(redirectTo);
-            if (permanent != null) {
-                game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " to " + permanent.getLogName() + " instead");
-                // keep the original source id as it is redirecting
-                permanent.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true);
-                discard();
-            }
-            Player player = game.getPlayer(redirectTo);
-            if (player != null) {
-                game.informPlayers("Dealing " + preventionData.getPreventedDamage() + " to " + player.getLogName() + " instead");
-                // keep the original source id as it is redirecting
-                player.damage(preventionData.getPreventedDamage(), event.getSourceId(), game, false, true);
-                discard();
+    public boolean applies(GameEvent event, Ability source, Game game) {
+        // check source
+        MageObject object = game.getObject(event.getSourceId());
+        if (object == null) {
+            game.informPlayers("Couldn't find source of damage");
+            return false;
+        }
+
+        if (!object.getId().equals(damageSource.getFirstTarget())
+                && (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(damageSource.getFirstTarget()))) {
+            return false;
+        }
+        this.redirectTarget = source.getTargets().get(0);
+
+        // check target
+        //   check permanent first
+        Permanent permanent = game.getPermanent(event.getTargetId());
+        if (permanent != null) {
+            if (permanent.getControllerId().equals(source.getControllerId())) {
+                // it's your permanent
+                return true;
             }
         }
-        return false;
-    }
-
-    @Override
-    public boolean applies(GameEvent event, Ability source, Game game) {
-        if (super.applies(event, source, game)) {
-            // check source
-            MageObject object = game.getObject(event.getSourceId());
-            if (object == null) {
-                game.informPlayers("Couldn't find source of damage");
-                return false;
-            }
-
-            if (!object.getId().equals(target.getFirstTarget())
-                    && (!(object instanceof Spell) || !((Spell) object).getSourceId().equals(target.getFirstTarget()))) {
-                return false;
-            }
-
-            // check target
-            //   check permanent first
-            Permanent permanent = game.getPermanent(event.getTargetId());
-            if (permanent != null) {
-                if (permanent.getControllerId().equals(source.getControllerId())) {
-                    // it's your permanent
-                    return true;
-                }
-            }
-            //   check player
-            Player player = game.getPlayer(event.getTargetId());
-            if (player != null) {
-                if (player.getId().equals(source.getControllerId())) {
-                    // it is you
-                    return true;
-                }
+        //   check player
+        Player player = game.getPlayer(event.getTargetId());
+        if (player != null) {
+            if (player.getId().equals(source.getControllerId())) {
+                // it is you
+                return true;
             }
         }
         return false;
     }
 
 }
-
diff --git a/Mage.Sets/src/mage/sets/stronghold/NomadsEnKor.java b/Mage.Sets/src/mage/sets/stronghold/NomadsEnKor.java
index 2c2bf9a230..c1dbfdd8b8 100644
--- a/Mage.Sets/src/mage/sets/stronghold/NomadsEnKor.java
+++ b/Mage.Sets/src/mage/sets/stronghold/NomadsEnKor.java
@@ -55,7 +55,7 @@ public class NomadsEnKor extends CardImpl {
         this.toughness = new MageInt(1);
 
         // {0}: The next 1 damage that would be dealt to Nomads en-Kor this turn is dealt to target creature you control instead.
-        Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorPreventionEffect(), new GenericManaCost(0));
+        Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorRedirectFromItselfEffect(), new GenericManaCost(0));
         ability.addTarget(new TargetControlledCreaturePermanent());
         this.addAbility(ability);
     }
diff --git a/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java b/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java
index 97c5d5349e..0bac73f71d 100644
--- a/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java
+++ b/Mage.Sets/src/mage/sets/stronghold/ShamanEnKor.java
@@ -29,14 +29,12 @@ package mage.sets.stronghold;
 
 import java.util.UUID;
 import mage.MageInt;
-import mage.MageObject;
+import mage.MageObjectReference;
 import mage.abilities.Ability;
 import mage.abilities.common.SimpleActivatedAbility;
 import mage.abilities.costs.mana.GenericManaCost;
 import mage.abilities.costs.mana.ManaCostsImpl;
-import mage.abilities.effects.PreventionEffectData;
-import mage.abilities.effects.PreventionEffectImpl;
-import mage.abilities.effects.ReplacementEffectImpl;
+import mage.abilities.effects.RedirectionEffect;
 import mage.cards.CardImpl;
 import mage.constants.CardType;
 import mage.constants.Duration;
@@ -44,11 +42,10 @@ import mage.constants.Outcome;
 import mage.constants.Rarity;
 import mage.constants.Zone;
 import mage.game.Game;
-import mage.game.events.DamageEvent;
 import mage.game.events.GameEvent;
 import mage.game.events.GameEvent.EventType;
-import mage.game.permanent.Permanent;
 import mage.players.Player;
+import mage.target.TargetPermanent;
 import mage.target.TargetSource;
 import mage.target.common.TargetControlledCreaturePermanent;
 import mage.target.common.TargetCreaturePermanent;
@@ -70,12 +67,12 @@ public class ShamanEnKor extends CardImpl {
         this.toughness = new MageInt(2);
 
         // {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
-        Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorPreventionEffect(), new GenericManaCost(0));
+        Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorRedirectFromItselfEffect(), new GenericManaCost(0));
         ability.addTarget(new TargetControlledCreaturePermanent());
         this.addAbility(ability);
-        
+
         // {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
-        ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorReplacementEffect(), new ManaCostsImpl("{1}{W}"));
+        ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ShamanEnKorRedirectFromTargetEffect(), new ManaCostsImpl("{1}{W}"));
         ability.addTarget(new TargetCreaturePermanent());
         this.addAbility(ability);
     }
@@ -90,129 +87,69 @@ public class ShamanEnKor extends CardImpl {
     }
 }
 
-class ShamanEnKorPreventionEffect extends PreventionEffectImpl {
-    
-    ShamanEnKorPreventionEffect() {
-        super(Duration.EndOfTurn, 1, false);
+class ShamanEnKorRedirectFromItselfEffect extends RedirectionEffect {
+
+    ShamanEnKorRedirectFromItselfEffect() {
+        super(Duration.EndOfTurn, 1, true);
         staticText = "The next 1 damage that would be dealt to {this} this turn is dealt to target creature you control instead.";
     }
-    
-    ShamanEnKorPreventionEffect(final ShamanEnKorPreventionEffect effect) {
+
+    ShamanEnKorRedirectFromItselfEffect(final ShamanEnKorRedirectFromItselfEffect effect) {
         super(effect);
     }
-    
+
     @Override
-    public ShamanEnKorPreventionEffect copy() {
-        return new ShamanEnKorPreventionEffect(this);
+    public ShamanEnKorRedirectFromItselfEffect copy() {
+        return new ShamanEnKorRedirectFromItselfEffect(this);
     }
-    
-    @Override
-    public boolean replaceEvent(GameEvent event, Ability source, Game game) {
-        PreventionEffectData preventionResult = preventDamageAction(event, source, game);
-        if (preventionResult.getPreventedDamage() > 0) {
-            Permanent redirectTo = game.getPermanent(getTargetPointer().getFirst(game, source));
-            if (redirectTo != null) {
-                game.informPlayers("Dealing " + preventionResult.getPreventedDamage() + " to " + redirectTo.getName() + " instead.");
-                DamageEvent damageEvent = (DamageEvent) event;
-                redirectTo.damage(preventionResult.getPreventedDamage(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
-            }
-        }
-        return false;
-    }
-    
+
     @Override
     public boolean applies(GameEvent event, Ability source, Game game) {
-        if (!this.used && super.applies(event, source, game)) {
-            if (event.getTargetId().equals(source.getSourceId())) {
-                return game.getPermanent(getTargetPointer().getFirst(game, source)) != null;
-            }
+        if (event.getTargetId().equals(source.getSourceId())) {
+            this.redirectTarget = source.getTargets().get(0);
+            return true;
         }
         return false;
     }
 }
 
-class ShamanEnKorReplacementEffect extends ReplacementEffectImpl {
-    
-    protected TargetSource targetSource;
+class ShamanEnKorRedirectFromTargetEffect extends RedirectionEffect {
 
-    ShamanEnKorReplacementEffect() {
-        super(Duration.EndOfTurn, Outcome.RedirectDamage);
+    protected MageObjectReference sourceObject;
+
+    ShamanEnKorRedirectFromTargetEffect() {
+        super(Duration.EndOfTurn, Integer.MAX_VALUE, true);
         staticText = "The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to {this} instead";
     }
 
-    ShamanEnKorReplacementEffect(final ShamanEnKorReplacementEffect effect) {
+    ShamanEnKorRedirectFromTargetEffect(final ShamanEnKorRedirectFromTargetEffect effect) {
         super(effect);
-        targetSource = effect.targetSource;
+        sourceObject = effect.sourceObject;
     }
 
     @Override
     public void init(Ability source, Game game) {
         Player player = game.getPlayer(source.getControllerId());
-        TargetSource target = new TargetSource();
-        target.setNotTarget(true);
         if (player != null) {
+            TargetSource target = new TargetSource();
             target.choose(Outcome.PreventDamage, player.getId(), source.getSourceId(), game);
-            this.targetSource = target;
+            this.sourceObject = new MageObjectReference(target.getFirstTarget(), game);
+        } else {
+            discard();
         }
     }
-    
+
     @Override
     public boolean checksEventType(GameEvent event, Game game) {
         return event.getType() == EventType.DAMAGE_CREATURE;
     }
-    
-    @Override
-    public boolean applies(GameEvent event, Ability source, Game game) {
-        if (!this.used) {
-            if (targetSource != null) {
-                if (event.getSourceId().equals(targetSource.getFirstTarget())) {
-                    // check source
-                    MageObject object = game.getObject(event.getSourceId());
-                    if (object == null) {
-                        game.informPlayers("Couldn't find source of damage");
-                        return false;
-                    }
-                    else {
-                        if (event.getTargetId().equals(source.getFirstTarget())) {
-                            Permanent permanent = game.getPermanent(source.getFirstTarget());
-                            if (permanent != null) {
-                                return true;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        return false;
-    }
 
     @Override
-    public boolean replaceEvent(GameEvent event, Ability source, Game game) {
-        DamageEvent damageEvent = (DamageEvent)event;
-        Permanent sourcePermanent = game.getPermanent(source.getSourceId());
-        if (sourcePermanent != null) {
-            // get name of old target
-            Permanent targetPermanent = game.getPermanent(event.getTargetId());
-            StringBuilder message = new StringBuilder();
-            message.append(sourcePermanent.getName()).append(": gets ");
-            message.append(damageEvent.getAmount()).append(" damage redirected from ");
-            if (targetPermanent != null) {
-                message.append(targetPermanent.getName());
-            }
-            else {
-                Player targetPlayer = game.getPlayer(event.getTargetId());
-                if (targetPlayer != null) {
-                    message.append(targetPlayer.getLogName());
-                }
-                else {
-                    message.append("unknown");
-                }
-            }
-            game.informPlayers(message.toString());
-            // redirect damage
-            this.used = true;
-            sourcePermanent.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
-            return true;
+    public boolean applies(GameEvent event, Ability source, Game game) {
+        if (sourceObject.equals(new MageObjectReference(event.getSourceId(), game))) {
+            redirectTarget = new TargetPermanent();
+            redirectTarget.add(source.getSourceId(), game);
+            return event.getTargetId().equals(getTargetPointer().getFirst(game, source));
         }
         return false;
     }
@@ -223,7 +160,7 @@ class ShamanEnKorReplacementEffect extends ReplacementEffectImpl {
     }
 
     @Override
-    public ShamanEnKorReplacementEffect copy() {
-        return new ShamanEnKorReplacementEffect(this);
+    public ShamanEnKorRedirectFromTargetEffect copy() {
+        return new ShamanEnKorRedirectFromTargetEffect(this);
     }
 }
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/HarmsWayRedirectDamageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/HarmsWayRedirectDamageTest.java
similarity index 57%
rename from Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/HarmsWayRedirectDamageTest.java
rename to Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/HarmsWayRedirectDamageTest.java
index f609e5ed8e..7f7508a5ab 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/HarmsWayRedirectDamageTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/HarmsWayRedirectDamageTest.java
@@ -1,4 +1,4 @@
-package org.mage.test.cards.replacement.prevent;
+package org.mage.test.cards.replacement.redirect;
 
 import mage.constants.PhaseStep;
 import mage.constants.Zone;
@@ -6,15 +6,17 @@ import org.junit.Test;
 import org.mage.test.serverside.base.CardTestPlayerBase;
 
 /**
- * Harm's Way:
- *   The next 2 damage that a source of your choice would deal to you and/or permanents you control this turn is dealt to target creature or player instead.
+ * Harm's Way: The next 2 damage that a source of your choice would deal to you
+ * and/or permanents you control this turn is dealt to target creature or player
+ * instead.
  *
  * @author noxx
  */
 public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
 
     /**
-     * Tests that 2 of 3 damage is redirected while 1 damage is still dealt to original target
+     * Tests that 2 of 3 damage is redirected while 1 damage is still dealt to
+     * original target
      */
     @Test
     public void testRedirectTwoDamage() {
@@ -51,7 +53,7 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
         attack(2, playerB, "Craw Wurm");
         castSpell(2, PhaseStep.DECLARE_BLOCKERS, playerA, "Harm's Way", playerB);
         setChoice(playerA, "Craw Wurm");
-        
+
         setStopAt(2, PhaseStep.END_TURN);
         execute();
 
@@ -79,8 +81,11 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
         addCard(Zone.BATTLEFIELD, playerB, "Magma Phoenix");
 
         castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harm's Way", playerB);
-        setChoice(playerA, "Magma Phoenix");        
-        /** When Magma Phoenix dies, Magma Phoenix deals 3 damage to each creature and each player **/
+        setChoice(playerA, "Magma Phoenix");
+        /**
+         * When Magma Phoenix dies, Magma Phoenix deals 3 damage to each
+         * creature and each player *
+         */
         castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Magma Phoenix");
 
         setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
@@ -91,4 +96,38 @@ public class HarmsWayRedirectDamageTest extends CardTestPlayerBase {
         assertLife(playerB, 15); // 3 damage from dying Phoenix directly and 2 redirected damage from playerA
     }
 
+    /**
+     * Tests that not preventable damage is redirected
+     */
+    @Test
+    public void testRedirectNotPreventableDamage() {
+        addCard(Zone.BATTLEFIELD, playerA, "Mountain");
+        // <i>Ferocious</i> If you control a creature with power 4 or greater, damage can't be prevented this turn.
+        // Wild Slash deals 2 damage to target creature or player.
+        addCard(Zone.HAND, playerA, "Wild Slash"); // {R}
+        addCard(Zone.BATTLEFIELD, playerA, "Serra Angel");
+        addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
+
+        // The next 2 damage that a source of your choice would deal to you and/or permanents
+        // you control this turn is dealt to target creature or player instead.
+        addCard(Zone.HAND, playerB, "Harm's Way"); // {W}
+        addCard(Zone.BATTLEFIELD, playerB, "Plains");
+        addCard(Zone.BATTLEFIELD, playerB, "Birds of Paradise");
+
+        // the 2 damage can't be prevented and have to be redirected to Silvercoat Lion of player A
+        castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Wild Slash", "Birds of Paradise");
+        castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Harm's Way", "Silvercoat Lion", "Wild Slash");
+        setChoice(playerB, "Wild Slash");
+
+        setStopAt(1, PhaseStep.BEGIN_COMBAT);
+        execute();
+
+        assertGraveyardCount(playerA, "Wild Slash", 1);
+        assertGraveyardCount(playerB, "Harm's Way", 1);
+        assertPermanentCount(playerB, "Birds of Paradise", 1);
+        assertGraveyardCount(playerA, "Silvercoat Lion", 1);
+        assertLife(playerA, 20);
+        assertLife(playerB, 20);
+    }
+
 }
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/ShamenEnKorTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/ShamenEnKorTest.java
new file mode 100644
index 0000000000..a8ffe681e7
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/ShamenEnKorTest.java
@@ -0,0 +1,94 @@
+/*
+ *  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 org.mage.test.cards.replacement.redirect;
+
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ *
+ * @author LevelX2
+ */
+public class ShamenEnKorTest extends CardTestPlayerBase {
+
+    /**
+     * Tests that 2 of 3 damage is redirected while 1 damage is still dealt to
+     * original target
+     */
+    @Test
+    public void testFirstAbilityNonCombatDamage() {
+        addCard(Zone.HAND, playerA, "Lightning Bolt");
+        addCard(Zone.BATTLEFIELD, playerA, "Mountain");
+
+        // {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
+        // {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
+        addCard(Zone.BATTLEFIELD, playerB, "Shaman en-Kor"); // 1/2
+        addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2
+
+        castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Shaman en-Kor");
+
+        activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{0}: The next 1 damage", "Silvercoat Lion", "Lightning Bolt");
+        activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{0}: The next 1 damage", "Silvercoat Lion", "Lightning Bolt");
+
+        setStopAt(1, PhaseStep.BEGIN_COMBAT);
+        execute();
+
+        assertGraveyardCount(playerA, "Lightning Bolt", 1);
+        assertPermanentCount(playerB, "Shaman en-Kor", 1);
+        assertGraveyardCount(playerB, "Silvercoat Lion", 1);
+
+    }
+
+    @Test
+    public void testSecondAbilityNonCombatDamage() {
+        addCard(Zone.HAND, playerA, "Lightning Bolt");
+        addCard(Zone.BATTLEFIELD, playerA, "Mountain");
+
+        // {0}: The next 1 damage that would be dealt to Shaman en-Kor this turn is dealt to target creature you control instead.
+        // {1}{W}: The next time a source of your choice would deal damage to target creature this turn, that damage is dealt to Shaman en-Kor instead.
+        addCard(Zone.BATTLEFIELD, playerB, "Shaman en-Kor"); // 1/2
+        addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
+        addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); // 2/2
+
+        castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
+
+        activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{W}: The next time", "Silvercoat Lion", "Lightning Bolt");
+        setChoice(playerB, "Lightning Bolt");
+
+        setStopAt(1, PhaseStep.BEGIN_COMBAT);
+        execute();
+
+        assertGraveyardCount(playerA, "Lightning Bolt", 1);
+        assertPermanentCount(playerB, "Silvercoat Lion", 1);
+        assertGraveyardCount(playerB, "Shaman en-Kor", 1);
+
+    }
+
+}
diff --git a/Mage/src/mage/abilities/effects/RedirectionEffect.java b/Mage/src/mage/abilities/effects/RedirectionEffect.java
index 6c339460ed..b30400e656 100644
--- a/Mage/src/mage/abilities/effects/RedirectionEffect.java
+++ b/Mage/src/mage/abilities/effects/RedirectionEffect.java
@@ -1,16 +1,16 @@
 /*
  *  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
@@ -20,14 +20,14 @@
  *  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;
 
+import mage.MageObject;
 import mage.abilities.Ability;
 import mage.constants.Duration;
 import mage.constants.EffectType;
@@ -46,36 +46,67 @@ import mage.target.Target;
 public abstract class RedirectionEffect extends ReplacementEffectImpl {
 
     protected Target redirectTarget;
+    protected int amountToRedirect;
+    protected boolean oneUsage;
 
     public RedirectionEffect(Duration duration) {
+        this(duration, Integer.MAX_VALUE, false);
+    }
+
+    public RedirectionEffect(Duration duration, int amountToRedirect, boolean oneUsage) {
         super(duration, Outcome.RedirectDamage);
         this.effectType = EffectType.REDIRECTION;
+        this.amountToRedirect = amountToRedirect;
+        this.oneUsage = oneUsage;
     }
 
     public RedirectionEffect(final RedirectionEffect effect) {
         super(effect);
         this.redirectTarget = effect.redirectTarget;
+        this.amountToRedirect = effect.amountToRedirect;
+        this.oneUsage = effect.oneUsage;
     }
 
     @Override
-    public boolean apply(Game game, Ability source) {
-        return true;
-    }
-
-    @Override
-    public boolean replaceEvent(GameEvent event, Ability source, Game game) {
-        DamageEvent damageEvent = (DamageEvent)event;
-        Permanent permanent = game.getPermanent(redirectTarget.getFirstTarget());
-        if (permanent != null) {
-            permanent.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
-            return true;
-        }
-        Player player = game.getPlayer(redirectTarget.getFirstTarget());
-        if (player != null) {
-            player.damage(damageEvent.getAmount(), event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
-            return true;
+    public boolean checksEventType(GameEvent event, Game game) {
+        switch (event.getType()) {
+            case DAMAGE_CREATURE:
+            case DAMAGE_PLAYER:
+            case DAMAGE_PLANESWALKER:
+                return true;
         }
         return false;
     }
 
+    @Override
+    public boolean replaceEvent(GameEvent event, Ability source, Game game) {
+        MageObject sourceObject = game.getObject(source.getSourceId());
+        DamageEvent damageEvent = (DamageEvent) event;
+        int restDamage = 0;
+        int damageToRedirect = event.getAmount();
+        if (damageEvent.getAmount() > amountToRedirect) {
+            restDamage = damageEvent.getAmount() - amountToRedirect;
+            damageToRedirect = amountToRedirect;
+        }
+        if (damageToRedirect > 0 && oneUsage) {
+            this.discard();
+        }
+        Permanent permanent = game.getPermanent(redirectTarget.getFirstTarget());
+        if (permanent != null) {
+            permanent.damage(damageToRedirect, event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
+            game.informPlayers(sourceObject.getLogName() + ": Redirected " + damageToRedirect + " damage to " + permanent.getLogName());
+        } else {
+            Player player = game.getPlayer(redirectTarget.getFirstTarget());
+            if (player != null) {
+                player.damage(damageToRedirect, event.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), event.getAppliedEffects());
+                game.informPlayers(sourceObject.getLogName() + ": Redirected " + damageToRedirect + " damage to " + player.getLogName());
+            }
+        }
+        if (restDamage > 0) {
+            damageEvent.setAmount(restDamage);
+            return false;
+        }
+        return true;
+    }
+
 }