Repository: magefree/mage (Java)

Issue:
Battle at the Helvault Saga Chapter 1 does not exile despite a selection of valid targets
Current behavior:
The Saga [[Battle at the Helvault]] has the same rules text for Chapter I and Chapter II. While Chapter II exiles all targeted creatures, Chapter I does not. I've made sure to select all desired creatures when they light up but despite the Saga resolving they won't get exiled.
Only after my Draw Step when the lore counter is increased to two and after selecting a new set of creatures those last 3 will be exiled.
Chapter III resolves successfully every time.

Expected behavior:
The saga exiles 3 creatures when it enters the battlefield and when the lore counter is increased to 2.

Steps to reproduce:
1. Launch the XMage-Server in Testmode.
2. Create a 4 player Match.
3. Use the provided cheat-setup below.
4. On your turn play Battle at the Helvault
5. Select 1 creature for each player.
6. Confirm your selection and let the spell resolve.

Cheat-Setup:
```
[Helvault Test]
battlefield:Computer:Kitesail Corsair:2
battlefield:Computer2:Grizzly Bears:4
battlefield:Computer3:Storm Crow:3
battlefield:Human:Spyglass Siren:2
battlefield:Human:CLU-Plains:6
hand:Human:Battle at the Helvault:1
```


Discussion: **[Battle at the Helvault](https://cards.scryfall.io/normal/front/0/d/0de0eaeb-9b62-427d-9873-d84de1740ddc.jpg?1692232653)** - [(Gatherer)](https://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=625084&printed=false) [(Scryfall)](https://scryfall.com/card/cmm/719/battle-at-the-helvault?utm_source=api) [(EDHREC)](https://edhrec.com/route/?cc=Battle+at+the+Helvault)
> {4}{W}{W}
> Enchantment — Saga
> (As this Saga enters and after your draw step, add a lore counter. Sacrifice after III.)
> I, II — For each player, exile up to one target non-Saga, nonland permanent that player controls until Battle at the Helvault leaves the battlefield.
III — Create Avacyn, a legendary 8/8 white Angel creature token with flying, vigilance, and indestructible.
This sounds related to #11619

Edit: and also #11442



Fix (patch):
diff --git a/Mage.Sets/src/mage/cards/g/GenesisOfTheDaleks.java b/Mage.Sets/src/mage/cards/g/GenesisOfTheDaleks.java
index daef4301cea9..6807307ac586 100644
--- a/Mage.Sets/src/mage/cards/g/GenesisOfTheDaleks.java
+++ b/Mage.Sets/src/mage/cards/g/GenesisOfTheDaleks.java
@@ -2,8 +2,7 @@
 
 import mage.abilities.Ability;
 import mage.abilities.common.SagaAbility;
-import mage.abilities.dynamicvalue.DynamicValue;
-import mage.abilities.effects.Effect;
+import mage.abilities.dynamicvalue.common.CountersSourceCount;
 import mage.abilities.effects.OneShotEffect;
 import mage.abilities.effects.common.CreateTokenEffect;
 import mage.abilities.effects.common.DestroyAllEffect;
@@ -19,7 +18,6 @@
 import mage.game.Game;
 import mage.game.events.GameEvent;
 import mage.game.events.ZoneChangeEvent;
-import mage.game.permanent.Permanent;
 import mage.game.permanent.token.DalekToken;
 import mage.players.Player;
 import mage.target.common.TargetOpponent;
@@ -44,7 +42,7 @@ public GenesisOfTheDaleks(UUID ownerId, CardSetInfo setInfo) {
         // I, II, III -- Create a 3/3 black Dalek artifact creature token with menace for each lore counter on Genesis of the Daleks.
         sagaAbility.addChapterEffect(
                 this, SagaChapter.CHAPTER_I, SagaChapter.CHAPTER_III,
-                new CreateTokenEffect(new DalekToken(), GenesisOfTheDaleksValue.instance)
+                new CreateTokenEffect(new DalekToken(), new CountersSourceCount(CounterType.LORE))
         );
 
         // IV -- Target opponent faces a villainous choice -- Destroy all Dalek creatures and each of your opponents loses life equal to the total power of Daleks that died this turn, or destroy all non-Dalek creatures.
@@ -65,41 +63,6 @@ public GenesisOfTheDaleks copy() {
     }
 }
 
-enum GenesisOfTheDaleksValue implements DynamicValue {
-    instance;
-
-    @Override
-    public int calculate(Game game, Ability sourceAbility, Effect effect) {
-        Permanent permanent = sourceAbility.getSourcePermanentOrLKI(game);
-        if (permanent != null) {
-            return permanent
-                    .getCounters(game)
-                    .getCount(CounterType.LORE);
-        }
-        return Optional
-                .ofNullable(sourceAbility)
-                .map(Ability::getSourceId)
-                .map(game::getPermanentOrLKIBattlefield)
-                .map(p -> p.getCounters(game).getCount(CounterType.LORE))
-                .orElse(0);
-    }
-
-    @Override
-    public GenesisOfTheDaleksValue copy() {
-        return this;
-    }
-
-    @Override
-    public String getMessage() {
-        return "lore counter on {this}";
-    }
-
-    @Override
-    public String toString() {
-        return "1";
-    }
-}
-
 class GenesisOfTheDaleksEffect extends OneShotEffect {
 
     private static final FaceVillainousChoice choice = new FaceVillainousChoice(
diff --git a/Mage.Sets/src/mage/cards/l/LongListOfTheEnts.java b/Mage.Sets/src/mage/cards/l/LongListOfTheEnts.java
index 95abf6d63d5e..0bb6414a7a71 100644
--- a/Mage.Sets/src/mage/cards/l/LongListOfTheEnts.java
+++ b/Mage.Sets/src/mage/cards/l/LongListOfTheEnts.java
@@ -53,8 +53,8 @@ public LongListOfTheEnts copy() {
         return new LongListOfTheEnts(this);
     }
 
-    static String getKey(Game game, Ability source, int offset) {
-        return "EntList_" + source.getSourceId() + "_" + (offset + CardUtil.getActualSourceObjectZoneChangeCounter(game, source));
+    static String getKey(Game game, Ability source) {
+        return "EntList_" + source.getSourceId() + "_" + CardUtil.getActualSourceObjectZoneChangeCounter(game, source);
     }
 
 }
@@ -67,7 +67,7 @@ public String getText(Game game, Ability ability) {
         if (ability.getSourcePermanentIfItStillExists(game) == null) {
             return null;
         }
-        Set<SubType> subTypes = (Set<SubType>) game.getState().getValue(LongListOfTheEnts.getKey(game, ability, 0));
+        Set<SubType> subTypes = (Set<SubType>) game.getState().getValue(LongListOfTheEnts.getKey(game, ability));
         if (subTypes == null || subTypes.isEmpty()) {
             return "No creature types have been noted yet.";
         }
@@ -109,14 +109,11 @@ public boolean apply(Game game, Ability source) {
             return false;
         }
 
-        Object existingEntList = game.getState().getValue(LongListOfTheEnts.getKey(game, source, 0));
-        int offset;
+        Object existingEntList = game.getState().getValue(LongListOfTheEnts.getKey(game, source));
         Set<SubType> newEntList;
         if (existingEntList == null) {
-            offset = 1; // zcc is off-by-one due to still entering battlefield
             newEntList = new LinkedHashSet<>();
         } else {
-            offset = 0;
             newEntList = new LinkedHashSet<>((Set<SubType>) existingEntList);
         }
         Set<String> chosenTypes = newEntList
@@ -132,7 +129,7 @@ public boolean apply(Game game, Ability source) {
         SubType subType = SubType.byDescription(choice.getChoiceKey());
         game.informPlayers(player.getLogName() + " notes the creature type " + subType);
         newEntList.add(subType);
-        game.getState().setValue(LongListOfTheEnts.getKey(game, source, offset), newEntList);
+        game.getState().setValue(LongListOfTheEnts.getKey(game, source), newEntList);
         FilterSpell filter = new FilterCreatureSpell("a creature spell of that type");
         filter.add(subType.getPredicate());
         game.addDelayedTriggeredAbility(new AddCounterNextSpellDelayedTriggeredAbility(filter), source);
diff --git a/Mage.Sets/src/mage/cards/s/SummonEsperValigarmanda.java b/Mage.Sets/src/mage/cards/s/SummonEsperValigarmanda.java
index 3a2c1b4614ad..3fcc14c2c8ec 100644
--- a/Mage.Sets/src/mage/cards/s/SummonEsperValigarmanda.java
+++ b/Mage.Sets/src/mage/cards/s/SummonEsperValigarmanda.java
@@ -107,7 +107,7 @@ public boolean apply(Game game, Ability source) {
         return !cards.isEmpty()
                 && controller.moveCardsToExile(
                 cards.getCards(game), source, game, true,
-                CardUtil.getExileZoneId(game, source, 1),
+                CardUtil.getExileZoneId(game, source),
                 CardUtil.getSourceName(game, source)
         );
     }
diff --git a/Mage.Sets/src/mage/cards/t/TheAesirEscapeValhalla.java b/Mage.Sets/src/mage/cards/t/TheAesirEscapeValhalla.java
index 0095d30b9ae5..aed85868cd23 100644
--- a/Mage.Sets/src/mage/cards/t/TheAesirEscapeValhalla.java
+++ b/Mage.Sets/src/mage/cards/t/TheAesirEscapeValhalla.java
@@ -1,15 +1,13 @@
 package mage.cards.t;
 
-import java.util.UUID;
-
 import mage.MageObject;
 import mage.abilities.Ability;
 import mage.abilities.common.SagaAbility;
 import mage.abilities.effects.OneShotEffect;
 import mage.cards.Card;
-import mage.constants.*;
 import mage.cards.CardImpl;
 import mage.cards.CardSetInfo;
+import mage.constants.*;
 import mage.counters.CounterType;
 import mage.filter.StaticFilters;
 import mage.game.ExileZone;
@@ -20,6 +18,8 @@
 import mage.target.common.TargetControlledCreaturePermanent;
 import mage.util.CardUtil;
 
+import java.util.UUID;
+
 /**
  *
  * @author Grath
@@ -83,7 +83,7 @@ public boolean apply(Game game, Ability source) {
         controller.choose(outcome, target, source, game);
         Card card = game.getCard(target.getFirstTarget());
         if (card != null) {
-            UUID exileId = CardUtil.getExileZoneId(game, source, 1);
+            UUID exileId = CardUtil.getExileZoneId(game, source);
             MageObject sourceObject = source.getSourceObject(game);
             String exileName = sourceObject != null ? sourceObject.getName() : "";
             controller.moveCardsToExile(card, source, game, false, exileId, exileName);
diff --git a/Mage.Sets/src/mage/cards/t/TheCreationOfAvacyn.java b/Mage.Sets/src/mage/cards/t/TheCreationOfAvacyn.java
index 17b28d397541..b1cdb9ab4688 100644
--- a/Mage.Sets/src/mage/cards/t/TheCreationOfAvacyn.java
+++ b/Mage.Sets/src/mage/cards/t/TheCreationOfAvacyn.java
@@ -81,7 +81,7 @@ public boolean apply(Game game, Ability source) {
             if (card != null) {
                 // exile it face down
                 card.setFaceDown(true, game);
-                UUID exileId = CardUtil.getExileZoneId(game, source, 1);
+                UUID exileId = CardUtil.getExileZoneId(game, source);
                 MageObject sourceObject = source.getSourceObject(game);
                 String exileName = sourceObject != null ? sourceObject.getName() : "";
                 controller.moveCardsToExile(card, source, game, false, exileId, exileName);
diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java
index ad735b98e742..81c5e5e0d28a 100644
--- a/Mage/src/main/java/mage/abilities/AbilityImpl.java
+++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java
@@ -1710,15 +1710,14 @@ public void initSourceObjectZoneChangeCounter(Game game, boolean force) {
 
     private int getCurrentSourceObjectZoneChangeCounter(Game game){
         int zcc = game.getState().getZoneChangeCounter(getSourceId());
-        // TODO: Enable this, #13710
-        /*if (game.getPermanentEntering(getSourceId()) != null){
+        if (game.getPermanentEntering(getSourceId()) != null){
             // If the triggered ability triggered while the permanent is entering the battlefield
             // then add 1 zcc so that it triggers as if the permanent was already on the battlefield
             // So "Enters with counters" causes "Whenever counters are placed" to trigger with battlefield zcc
             // Particularly relevant for Sagas, which always involve both
             // Note that this does NOT apply to "As ~ ETB" effects, those still use the stack zcc
             zcc += 1;
-        }*/
+        }
         return zcc;
     }