diff --git a/Mage.Sets/src/mage/cards/s/StormOfSouls.java b/Mage.Sets/src/mage/cards/s/StormOfSouls.java
new file mode 100644
index 0000000000..c35281f0ce
--- /dev/null
+++ b/Mage.Sets/src/mage/cards/s/StormOfSouls.java
@@ -0,0 +1,143 @@
+package mage.cards.s;
+
+import mage.abilities.Ability;
+import mage.abilities.effects.ContinuousEffectImpl;
+import mage.abilities.effects.OneShotEffect;
+import mage.abilities.effects.common.ExileSpellEffect;
+import mage.abilities.keyword.FlyingAbility;
+import mage.cards.Card;
+import mage.cards.CardImpl;
+import mage.cards.CardSetInfo;
+import mage.constants.*;
+import mage.filter.StaticFilters;
+import mage.game.Game;
+import mage.game.permanent.Permanent;
+import mage.players.Player;
+import mage.target.targetpointer.FixedTargets;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * @author Alex-Vasile
+ */
+public class StormOfSouls extends CardImpl {
+    public StormOfSouls(UUID ownerId, CardSetInfo setInfo) {
+        super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}{W}");
+
+        // Return all creature cards from your graveyard to the battlefield.
+        // Each of them is a 1/1 Spirit with flying in addition to its other types.
+        this.getSpellAbility().addEffect(new StormOfSoulsReturnEffect());
+
+        // Exile Storm of Souls.
+        this.getSpellAbility().addEffect(new ExileSpellEffect().concatBy("<br>"));
+    }
+
+    private StormOfSouls(final StormOfSouls card) { super(card); }
+
+    @Override
+    public StormOfSouls copy() { return new StormOfSouls(this); }
+}
+
+class StormOfSoulsReturnEffect extends OneShotEffect {
+    public StormOfSoulsReturnEffect() {
+        super(Outcome.Benefit);
+        staticText = "Return all creature cards from your graveyard to the battlefield." +
+                "Each of them is a 1/1 Spirit with flying in addition to its other types.";
+    }
+
+    private StormOfSoulsReturnEffect(final StormOfSoulsReturnEffect effect) { super(effect); }
+
+    @Override
+    public StormOfSoulsReturnEffect copy() { return new StormOfSoulsReturnEffect(this); }
+
+    @Override
+    public boolean apply(Game game, Ability source) {
+        Player player = game.getPlayer(source.getControllerId());
+
+        if (player == null) { return false; }
+
+        Set<Card> creatureCardsToBeMovedFromGraveyard = player.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game);
+        if (creatureCardsToBeMovedFromGraveyard == null) { return false; }
+
+        if (creatureCardsToBeMovedFromGraveyard.isEmpty()) { return false; }
+
+        boolean anyCardsMoved = player.moveCards(creatureCardsToBeMovedFromGraveyard, Zone.BATTLEFIELD, source, game);
+        if (!anyCardsMoved) { return false; }
+
+        // Figure out which cards were successfuly moved so that they can be turned into 1/1 Spirits
+        Set<Card> creatureCardsMovedFromGraveyard = new LinkedHashSet<>();
+
+        for (Card card : creatureCardsToBeMovedFromGraveyard) {
+            if (game.getState().getZone(card.getId()) == Zone.BATTLEFIELD) {
+                creatureCardsMovedFromGraveyard.add(card);
+            }
+        }
+
+        // Change the creatures
+        ContinuousEffectImpl effect = new StormOfSoulsChangeCreatureEffect();
+        effect.setTargetPointer(new FixedTargets(creatureCardsMovedFromGraveyard, game));
+        game.addEffect(effect, source);
+
+        return true;
+    }
+}
+
+class StormOfSoulsChangeCreatureEffect extends ContinuousEffectImpl {
+
+    public StormOfSoulsChangeCreatureEffect() {
+        super(Duration.WhileOnBattlefield, Outcome.Benefit);
+    }
+
+    private StormOfSoulsChangeCreatureEffect(final StormOfSoulsChangeCreatureEffect effect) {
+        super(effect);
+    }
+
+    @Override
+    public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
+        Player player = game.getPlayer(source.getControllerId());
+        if (player == null) { return false; }
+
+        // Each of them is a 1/1 Spirit with flying in addition to its other types
+        for (UUID cardID : targetPointer.getTargets(game, source)) {
+            Permanent permanent = game.getPermanent(cardID);
+            if (permanent == null) { continue; }
+
+            switch (layer) {
+                case TypeChangingEffects_4:
+                    permanent.getSubtype().add(SubType.SPIRIT);
+                    break;
+                case AbilityAddingRemovingEffects_6:
+                    // Don't double add flying
+                    if (!permanent.getAbilities().contains(FlyingAbility.getInstance())) {
+                        // Add it index 0 so that it shows up at the top of the card's text.
+                        permanent.getAbilities().add(0, FlyingAbility.getInstance());
+                    }
+                    break;
+                case PTChangingEffects_7:
+                    if (sublayer == SubLayer.ModifyPT_7c) {
+                        permanent.getPower().setValue(1);
+                        permanent.getToughness().setValue(1);
+                    }
+                    break;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean apply(Game game, Ability source) { return false; }
+
+    @Override
+    public StormOfSoulsChangeCreatureEffect copy() {
+        return new StormOfSoulsChangeCreatureEffect(this);
+    }
+
+    @Override
+    public boolean hasLayer(Layer layer) {
+        return layer == Layer.TypeChangingEffects_4
+                || layer == Layer.AbilityAddingRemovingEffects_6
+                || layer == Layer.PTChangingEffects_7;
+    }
+}
diff --git a/Mage.Sets/src/mage/sets/CrimsonVowCommander.java b/Mage.Sets/src/mage/sets/CrimsonVowCommander.java
index d100f65d30..4a318af741 100644
--- a/Mage.Sets/src/mage/sets/CrimsonVowCommander.java
+++ b/Mage.Sets/src/mage/sets/CrimsonVowCommander.java
@@ -136,6 +136,8 @@ public final class CrimsonVowCommander extends ExpansionSet {
         cards.add(new SetCardInfo("Spectral Sailor", 114, Rarity.UNCOMMON, mage.cards.s.SpectralSailor.class));
         cards.add(new SetCardInfo("Spectral Shepherd", 98, Rarity.UNCOMMON, mage.cards.s.SpectralShepherd.class));
         cards.add(new SetCardInfo("Stensia Masquerade", 150, Rarity.UNCOMMON, mage.cards.s.StensiaMasquerade.class));
+        cards.add(new SetCardInfo("Storm of Souls", 9, Rarity.RARE, mage.cards.s.StormOfSouls.class, NON_FULL_USE_VARIOUS));
+        cards.add(new SetCardInfo("Storm of Souls", 47, Rarity.RARE, mage.cards.s.StormOfSouls.class, NON_FULL_USE_VARIOUS));
         cards.add(new SetCardInfo("Stromkirk Captain", 157, Rarity.UNCOMMON, mage.cards.s.StromkirkCaptain.class));
         cards.add(new SetCardInfo("Stromkirk Condemned", 137, Rarity.RARE, mage.cards.s.StromkirkCondemned.class));
         cards.add(new SetCardInfo("Stromkirk Occultist", 151, Rarity.RARE, mage.cards.s.StromkirkOccultist.class));