Fix crash after removing target when copying divided spell (#8714)

Co-authored-by: tool4EvEr <tool4EvEr@>
This commit is contained in:
tool4ever
2025-09-15 14:27:21 +02:00
committed by GitHub
parent 10d359e7d7
commit 79fd4a3f8d
10 changed files with 27 additions and 35 deletions

View File

@@ -298,13 +298,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
boolean activateForCost = ComputerUtil.activateForCost(sa, ai);
if (sa.hasParam("Origin")) {
try {
origin = ZoneType.listValueOf(sa.getParam("Origin"));
} catch (IllegalArgumentException ex) {
// This happens when Origin is something like
// "Graveyard,Library" (Doomsday)
return new AiAbilityDecision(0, AiPlayDecision.CantPlayAi);
}
}
final String destination = sa.getParam("Destination");

View File

@@ -928,7 +928,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
List<ZoneType> origin = Lists.newArrayList();
if (sa.hasParam("Origin")) {
origin = ZoneType.listValueOf(sa.getParam("Origin"));
origin.addAll(ZoneType.listValueOf(sa.getParam("Origin")));
}
ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));

View File

@@ -9,6 +9,7 @@ import forge.game.GameEntityCounterTable;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CounterType;
@@ -20,7 +21,6 @@ import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
import forge.util.Localizer;
import forge.util.collect.FCollection;
public class TimeTravelEffect extends SpellAbilityEffect {
@@ -41,10 +41,8 @@ public class TimeTravelEffect extends SpellAbilityEffect {
final CounterType counterType = CounterEnumType.TIME;
for (int i = 0; i < num; i++) {
FCollection<Card> list = new FCollection<>();
// card you own that is suspended
list.addAll(CardLists.filter(activator.getCardsIn(ZoneType.Exile), CardPredicates.hasSuspend()));
CardCollection list = CardLists.filter(activator.getCardsIn(ZoneType.Exile), CardPredicates.hasSuspend());
// permanent you control with time counter
list.addAll(CardLists.filter(activator.getCardsIn(ZoneType.Battlefield), CardPredicates.hasCounter(counterType)));

View File

@@ -1120,13 +1120,14 @@ public class Player extends GameEntity implements Comparable<Player> {
getGame().fireEvent(new GameEventSurveil(this, numToTop, numToGrave));
}
surveilThisTurn++;
final Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(this);
runParams.put(AbilityKey.FirstTime, surveilThisTurn == 1);
runParams.put(AbilityKey.FirstTime, surveilThisTurn == 0);
if (params != null) {
runParams.putAll(params);
}
getGame().getTriggerHandler().runTrigger(TriggerType.Surveil, runParams, false);
surveilThisTurn++;
}
public int getSurveilThisTurn() {

View File

@@ -1,7 +1,6 @@
Name:Footsteps of the Goryo
ManaCost:2 B
Types:Sorcery Arcane
A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature in your graveyard | GainControl$ True | SubAbility$ DBPump | AILogic$ BeforeCombat | SpellDescription$ Return target creature card from your graveyard to the battlefield. Sacrifice that creature at the beginning of the next end step.
SVar:DBPump:DB$ Pump | Defined$ Targeted | AtEOT$ Sacrifice
A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature in your graveyard | GainControl$ True | AtEOT$ Sacrifice | AILogic$ BeforeCombat | SpellDescription$ Return target creature card from your graveyard to the battlefield. Sacrifice that creature at the beginning of the next end step.
AI:RemoveDeck:Random
Oracle:Return target creature card from your graveyard to the battlefield. Sacrifice that creature at the beginning of the next end step.

View File

@@ -1,11 +1,9 @@
Name:Push the Limit
ManaCost:5 R R
Types:Sorcery
A:SP$ ChangeZoneAll | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Mount.YouOwn,Vehicle.YouOwn | RememberChanged$ True | SubAbility$ DBPump | SpellDescription$ Return all Mount and Vehicle cards from your graveyard to the battlefield. Sacrifice them at the beginning of the next end step. Vehicles you control become artifact creatures until end of turn. Creatures you control gain haste until end of turn.
SVar:DBPump:DB$ Pump | Defined$ Remembered | AtEOT$ Sacrifice | SubAbility$ DBAnimateAll
A:SP$ ChangeZoneAll | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Mount.YouOwn,Vehicle.YouOwn | AtEOT$ Sacrifice | SubAbility$ DBAnimateAll | SpellDescription$ Return all Mount and Vehicle cards from your graveyard to the battlefield. Sacrifice them at the beginning of the next end step. Vehicles you control become artifact creatures until end of turn. Creatures you control gain haste until end of turn.
SVar:DBAnimateAll:DB$ AnimateAll | Types$ Artifact,Creature | ValidCards$ Vehicle.YouCtrl | SubAbility$ DBPumpAll
SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.YouCtrl | KW$ Haste | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.YouCtrl | KW$ Haste
SVar:PlayMain1:TRUE
DeckHas:Ability$Graveyard
DeckHints:Ability$Discard|Sacrifice

View File

@@ -2,8 +2,7 @@ Name:Wake the Dead
ManaCost:X B B
Types:Instant
Text:Cast this spell only during combat on an opponent's turn.
A:SP$ ChangeZone | TargetMin$ X | TargetMax$ X | OpponentTurn$ True | ActivationPhases$ BeginCombat->EndCombat | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select X target creatures in your graveyard | GainControl$ True | SubAbility$ DBPump | StackDescription$ Return X target creature cards [{c:Targeted}] from your graveyard to the battlefield. Sacrifice those creatures at the beginning of the next end step. | SpellDescription$ Return X target creature cards from your graveyard to the battlefield. Sacrifice those creatures at the beginning of the next end step.
SVar:DBPump:DB$ Pump | Defined$ Targeted | AtEOT$ Sacrifice
A:SP$ ChangeZone | TargetMin$ X | TargetMax$ X | OpponentTurn$ True | ActivationPhases$ BeginCombat->EndCombat | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.YouOwn | TgtPrompt$ Select X target creatures in your graveyard | GainControl$ True | AtEOT$ Sacrifice | StackDescription$ Return X target creature cards [{c:Targeted}] from your graveyard to the battlefield. Sacrifice those creatures at the beginning of the next end step. | SpellDescription$ Return X target creature cards from your graveyard to the battlefield. Sacrifice those creatures at the beginning of the next end step.
SVar:X:Count$xPaid
AI:RemoveDeck:All
DeckHas:Ability$Graveyard|Sacrifice

View File

@@ -408,15 +408,18 @@ public final class InputSelectTargets extends InputSyncronizedBase {
}
private void removeTarget(final GameEntity ge) {
if (divisionValues != null) {
divisionValues.add(sa.getDividedValue(ge));
}
targets.remove(ge);
sa.getTargets().remove(ge);
if (ge instanceof Card) {
getController().getGui().setUsedToPay(CardView.get((Card) ge), false);
if (ge instanceof Card c) {
getController().getGui().setUsedToPay(CardView.get(c), false);
// try to get last selected card
lastTarget = Iterables.getLast(IterableUtil.filter(targets, Card.class), null);
}
else if (ge instanceof Player) {
getController().getGui().setHighlighted(PlayerView.get((Player) ge), false);
else if (ge instanceof Player p) {
getController().getGui().setHighlighted(PlayerView.get(p), false);
}
this.showMessage();