Merge branch 'lightning' into 'master'

Fix Lightning Storm retargeting

See merge request core-developers/forge!6054
This commit is contained in:
Hans Mackowiak
2022-01-19 08:05:59 +00:00
7 changed files with 18 additions and 9 deletions

View File

@@ -1325,7 +1325,10 @@ public class AbilityUtils {
} }
} }
else if (defined.equals("SourceFirstSpell")) { else if (defined.equals("SourceFirstSpell")) {
sas.add(card.getFirstSpellAbility()); SpellAbility spell = game.getStack().getSpellMatchingHost(card);
if (spell != null) {
sas.add(spell);
}
} }
else if (defined.startsWith("Triggered") && sa instanceof SpellAbility) { else if (defined.startsWith("Triggered") && sa instanceof SpellAbility) {
final SpellAbility root = ((SpellAbility)sa).getRootAbility(); final SpellAbility root = ((SpellAbility)sa).getRootAbility();
@@ -1362,8 +1365,7 @@ public class AbilityUtils {
if (instanceSA != null) { if (instanceSA != null) {
sas.add(instanceSA); sas.add(instanceSA);
} }
} } else {
else {
sas.add(targetSpell); sas.add(targetSpell);
} }
} }

View File

@@ -579,7 +579,7 @@ public abstract class SpellAbilityEffect {
PlayerCollection defendingPlayers = AbilityUtils.getDefinedPlayers(host, attacking, sa); PlayerCollection defendingPlayers = AbilityUtils.getDefinedPlayers(host, attacking, sa);
defs = new FCollection<>(); defs = new FCollection<>();
for (Player p : defendingPlayers) { for (Player p : defendingPlayers) {
defs.addAll(game.getCombat().getDefendersControlledBy(p)); defs.addAll(combat.getDefendersControlledBy(p));
} }
} else if ("True".equalsIgnoreCase(attacking)) { } else if ("True".equalsIgnoreCase(attacking)) {
defs = (FCollection<GameEntity>) combat.getDefenders(); defs = (FCollection<GameEntity>) combat.getDefenders();

View File

@@ -68,7 +68,6 @@ public class ReplaceToken extends ReplacementEffect {
sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected)); sa.setReplacingObject(AbilityKey.Player, runParams.get(AbilityKey.Affected));
} }
public int filterAmount(final TokenCreateTable table) { public int filterAmount(final TokenCreateTable table) {
return table.getFilterAmount(getParamOrDefault("ValidPlayer", null), getParamOrDefault("ValidToken", null), this); return table.getFilterAmount(getParamOrDefault("ValidPlayer", null), getParamOrDefault("ValidToken", null), this);
} }

View File

@@ -2102,7 +2102,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
public boolean isCumulativeupkeep() { public boolean isCumulativeupkeep() {
return cumulativeupkeep; return cumulativeupkeep;
} }
public void setCumulativeupkeep(boolean cumulativeupkeep0) { public void setCumulativeupkeep(boolean cumulativeupkeep0) {
cumulativeupkeep = cumulativeupkeep0; cumulativeupkeep = cumulativeupkeep0;
} }

View File

@@ -81,8 +81,8 @@ public class StaticAbilityPanharmonicon {
} }
} else if (trigMode.equals(TriggerType.ChangesZoneAll)) { } else if (trigMode.equals(TriggerType.ChangesZoneAll)) {
// Check if the cards have a trigger at all // Check if the cards have a trigger at all
final String origin = stAb.hasParam("Origin") ? stAb.getParam("Origin") : null; final String origin = stAb.getParamOrDefault("Origin", null);
final String destination = stAb.hasParam("Destination") ? stAb.getParam("Destination") : null; final String destination = stAb.getParamOrDefault("Destination", null);
final CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards); final CardZoneTable table = (CardZoneTable) runParams.get(AbilityKey.Cards);
if (table.filterCards(origin == null ? null : ImmutableList.of(ZoneType.smartValueOf(origin)), ZoneType.smartValueOf(destination), stAb.getParam("ValidCause"), card, stAb).isEmpty()) { if (table.filterCards(origin == null ? null : ImmutableList.of(ZoneType.smartValueOf(origin)), ZoneType.smartValueOf(destination), stAb.getParam("ValidCause"), card, stAb).isEmpty()) {

View File

@@ -766,6 +766,15 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
return null; return null;
} }
public final SpellAbility getSpellMatchingHost(final Card host) {
for (final SpellAbilityStackInstance si : stack) {
if (si.isSpell() && host.equals(si.getSpellAbility(false).getHostCard())) {
return si.getSpellAbility(false);
}
}
return null;
}
public final boolean hasSimultaneousStackEntries() { public final boolean hasSimultaneousStackEntries() {
return !simultaneousStackEntryList.isEmpty(); return !simultaneousStackEntryList.isEmpty();
} }

View File

@@ -3,7 +3,7 @@ ManaCost:3
Types:Artifact Types:Artifact
A:AB$ DigUntil | Cost$ 4 T | ValidTgts$ Opponent | Valid$ Instant,Sorcery | ValidDescription$ instant or sorcery | FoundDestination$ Exile | RevealedDestination$ Exile | RememberFound$ True | RememberRevealed$ True | IsCurse$ True | SubAbility$ DBPlay | SpellDescription$ Target opponent exiles cards from the top of their library until they exile an instant or sorcery card. You may cast that card without paying its mana cost. Then put the exiled cards that weren't cast this way on the bottom of that library in a random order. A:AB$ DigUntil | Cost$ 4 T | ValidTgts$ Opponent | Valid$ Instant,Sorcery | ValidDescription$ instant or sorcery | FoundDestination$ Exile | RevealedDestination$ Exile | RememberFound$ True | RememberRevealed$ True | IsCurse$ True | SubAbility$ DBPlay | SpellDescription$ Target opponent exiles cards from the top of their library until they exile an instant or sorcery card. You may cast that card without paying its mana cost. Then put the exiled cards that weren't cast this way on the bottom of that library in a random order.
SVar:DBPlay:DB$ Play | Defined$ Remembered | ValidZone$ Exile | Valid$ Instant.IsRemembered,Sorcery.IsRemembered | ValidSA$ Spell | WithoutManaCost$ True | RememberObjects$ Remembered | Optional$ True | ForgetTargetRemembered$ True | SubAbility$ DBRestRandomOrder SVar:DBPlay:DB$ Play | Defined$ Remembered | ValidZone$ Exile | Valid$ Instant.IsRemembered,Sorcery.IsRemembered | ValidSA$ Spell | WithoutManaCost$ True | RememberObjects$ Remembered | Optional$ True | ForgetTargetRemembered$ True | SubAbility$ DBRestRandomOrder
SVar:DBRestRandomOrder:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Library | Destination$ Library | LibraryPosition$ -1 | RandomOrder$ True | SubAbility$ DBCleanup SVar:DBRestRandomOrder:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Exile | Destination$ Library | LibraryPosition$ -1 | RandomOrder$ True | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:Picture:http://www.wizards.com/global/images/magic/general/chaos_wand.jpg SVar:Picture:http://www.wizards.com/global/images/magic/general/chaos_wand.jpg
Oracle:{4}, {T}: Target opponent exiles cards from the top of their library until they exile an instant or sorcery card. You may cast that card without paying its mana cost. Then put the exiled cards that weren't cast this way on the bottom of that library in a random order. Oracle:{4}, {T}: Target opponent exiles cards from the top of their library until they exile an instant or sorcery card. You may cast that card without paying its mana cost. Then put the exiled cards that weren't cast this way on the bottom of that library in a random order.