Merge pull request #138 from Northmoc/snc_ab_ql

Arcane Bombardment - quality of life
This commit is contained in:
Northmoc
2022-04-26 08:34:19 -04:00
committed by GitHub
14 changed files with 61 additions and 6 deletions

View File

@@ -823,6 +823,7 @@ public abstract class GameState {
String id = rememberedEnts.getValue(); String id = rememberedEnts.getValue();
Card exiledWith = idToCard.get(Integer.parseInt(id)); Card exiledWith = idToCard.get(Integer.parseInt(id));
exiledWith.addExiledCard(c);
c.setExiledWith(exiledWith); c.setExiledWith(exiledWith);
c.setExiledBy(exiledWith.getController()); c.setExiledBy(exiledWith.getController());
} }

View File

@@ -192,6 +192,7 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
if (host == null) { if (host == null) {
host = sa.getHostCard(); host = sa.getHostCard();
} }
host.addExiledCard(movedCard);
movedCard.setExiledWith(host); movedCard.setExiledWith(host);
movedCard.setExiledBy(host.getController()); movedCard.setExiledBy(host.getController());
} }

View File

@@ -719,6 +719,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (host == null) { if (host == null) {
host = sa.getHostCard(); host = sa.getHostCard();
} }
host.addExiledCard(gameCard);
gameCard.setExiledWith(host); gameCard.setExiledWith(host);
gameCard.setExiledBy(host.getController()); gameCard.setExiledBy(host.getController());
} }
@@ -745,6 +746,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (destination.equals(ZoneType.Exile) && !movedCard.isToken()) { if (destination.equals(ZoneType.Exile) && !movedCard.isToken()) {
movedCard.setExiledWith(host); movedCard.setExiledWith(host);
if (host != null) { if (host != null) {
host.addExiledCard(movedCard);
movedCard.setExiledBy(host.getController()); movedCard.setExiledBy(host.getController());
} }
} }
@@ -1350,6 +1352,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (host == null) { if (host == null) {
host = sa.getHostCard(); host = sa.getHostCard();
} }
host.addExiledCard(movedCard);
movedCard.setExiledWith(host); movedCard.setExiledWith(host);
movedCard.setExiledBy(host.getController()); movedCard.setExiledBy(host.getController());
} }
@@ -1541,6 +1544,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
host = srcSA.getHostCard(); host = srcSA.getHostCard();
} }
movedCard = game.getAction().exile(tgtHost, srcSA, params); movedCard = game.getAction().exile(tgtHost, srcSA, params);
host.addExiledCard(movedCard);
movedCard.setExiledWith(host); movedCard.setExiledWith(host);
movedCard.setExiledBy(host.getController()); movedCard.setExiledBy(host.getController());
} else if (srcSA.getParam("Destination").equals("TopOfLibrary")) { } else if (srcSA.getParam("Destination").equals("TopOfLibrary")) {

View File

@@ -420,6 +420,7 @@ public class DigEffect extends SpellAbilityEffect {
if (sa.hasParam("ExileWithCounter")) { if (sa.hasParam("ExileWithCounter")) {
c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")), 1, player, counterTable); c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")), 1, player, counterTable);
} }
effectHost.addExiledCard(c);
c.setExiledWith(effectHost); c.setExiledWith(effectHost);
c.setExiledBy(effectHost.getController()); c.setExiledBy(effectHost.getController());
} }
@@ -492,6 +493,7 @@ public class DigEffect extends SpellAbilityEffect {
if (sa.hasParam("ExileWithCounter")) { if (sa.hasParam("ExileWithCounter")) {
c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")), 1, player, counterTable); c.addCounter(CounterType.getType(sa.getParam("ExileWithCounter")), 1, player, counterTable);
} }
effectHost.addExiledCard(c);
c.setExiledWith(effectHost); c.setExiledWith(effectHost);
c.setExiledBy(effectHost.getController()); c.setExiledBy(effectHost.getController());
if (remZone2) { if (remZone2) {

View File

@@ -68,6 +68,7 @@ public class MillEffect extends SpellAbilityEffect {
host = sa.getHostCard(); host = sa.getHostCard();
} }
for (final Card c : milled) { for (final Card c : milled) {
host.addExiledCard(c);
c.setExiledWith(host); c.setExiledWith(host);
if (facedown) { if (facedown) {
c.turnFaceDown(true); c.turnFaceDown(true);

View File

@@ -109,7 +109,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private final Table<Long, Long, List<String>> hiddenExtrinsicKeywords = TreeBasedTable.create(); private final Table<Long, Long, List<String>> hiddenExtrinsicKeywords = TreeBasedTable.create();
// cards attached or otherwise linked to this card // cards attached or otherwise linked to this card
private CardCollection hauntedBy, devouredCards, exploitedCards, delvedCards, convokedCards, imprintedCards, encodedCards; private CardCollection hauntedBy, devouredCards, exploitedCards, delvedCards, convokedCards, imprintedCards,
exiledCards, encodedCards;
private CardCollection gainControlTargets, chosenCards; private CardCollection gainControlTargets, chosenCards;
private CardCollection mergedCards; private CardCollection mergedCards;
private Map<Long, CardCollection> mustBlockCards = Maps.newHashMap(); private Map<Long, CardCollection> mustBlockCards = Maps.newHashMap();
@@ -1079,6 +1080,31 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
imprintedCards = view.clearCards(imprintedCards, TrackableProperty.ImprintedCards); imprintedCards = view.clearCards(imprintedCards, TrackableProperty.ImprintedCards);
} }
public final CardCollectionView getExiledCards() {
return CardCollection.getView(exiledCards);
}
public final boolean hasExiledCard() {
return FCollection.hasElements(exiledCards);
}
public final boolean hasExiledCard(Card c) {
return FCollection.hasElement(exiledCards, c);
}
public final void addExiledCard(final Card c) {
exiledCards = view.addCard(exiledCards, c, TrackableProperty.ExiledCards);
}
public final void addExiledCards(final Iterable<Card> cards) {
exiledCards = view.addCards(exiledCards, cards, TrackableProperty.ExiledCards);
}
public final void removeExiledCard(final Card c) {
exiledCards = view.removeCard(exiledCards, c, TrackableProperty.ExiledCards);
}
public final void removeExiledCards(final Iterable<Card> cards) {
exiledCards = view.removeCards(exiledCards, cards, TrackableProperty.ExiledCards);
}
public final void clearExiledCards() {
exiledCards = view.clearCards(exiledCards, TrackableProperty.ExiledCards);
}
public final CardCollectionView getEncodedCards() { public final CardCollectionView getEncodedCards() {
return CardCollection.getView(encodedCards); return CardCollection.getView(encodedCards);
} }
@@ -1668,6 +1694,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return; return;
} }
exiledWith.removeExiledCard(this);
exiledWith.removeUntilLeavesBattlefield(this); exiledWith.removeUntilLeavesBattlefield(this);
exiledWith = null; exiledWith = null;

View File

@@ -647,6 +647,10 @@ public class CardView extends GameEntityView {
return get(TrackableProperty.ImprintedCards); return get(TrackableProperty.ImprintedCards);
} }
public FCollectionView<CardView> getExiledCards() {
return get(TrackableProperty.ExiledCards);
}
public FCollectionView<CardView> getHauntedBy() { public FCollectionView<CardView> getHauntedBy() {
return get(TrackableProperty.HauntedBy); return get(TrackableProperty.HauntedBy);
} }

View File

@@ -232,8 +232,10 @@ public class CostAdjustment {
} else if (!test) { } else if (!test) {
sa.getHostCard().addDelved(c); sa.getHostCard().addDelved(c);
final Card d = game.getAction().exile(c, null); final Card d = game.getAction().exile(c, null);
d.setExiledWith(sa.getHostCard()); final Card host = sa.getHostCard();
d.setExiledBy(sa.getHostCard().getController()); host.addExiledCard(d);
d.setExiledWith(host);
d.setExiledBy(host.getController());
table.put(ZoneType.Graveyard, d.getZone().getZoneType(), d); table.put(ZoneType.Graveyard, d.getZone().getZoneType(), d);
} }
} }

View File

@@ -180,8 +180,10 @@ public class CostExile extends CostPartWithList {
@Override @Override
protected Card doPayment(SpellAbility ability, Card targetCard, final boolean effect) { protected Card doPayment(SpellAbility ability, Card targetCard, final boolean effect) {
final Game game = targetCard.getGame(); final Game game = targetCard.getGame();
final Card host = ability.getHostCard();
Card newCard = game.getAction().exile(targetCard, null); Card newCard = game.getAction().exile(targetCard, null);
newCard.setExiledWith(ability.getHostCard()); host.addExiledCard(newCard);
newCard.setExiledWith(host);
newCard.setExiledBy(ability.getActivatingPlayer()); newCard.setExiledBy(ability.getActivatingPlayer());
return newCard; return newCard;
} }

View File

@@ -87,6 +87,7 @@ public enum TrackableProperty {
NeedsTapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze), NeedsTapAnimation(TrackableTypes.BooleanType, FreezeMode.IgnoresFreeze),
ImprintedCards(TrackableTypes.CardViewCollectionType), ImprintedCards(TrackableTypes.CardViewCollectionType),
ExiledCards(TrackableTypes.CardViewCollectionType),
HauntedBy(TrackableTypes.CardViewCollectionType), HauntedBy(TrackableTypes.CardViewCollectionType),
Haunting(TrackableTypes.CardViewType), Haunting(TrackableTypes.CardViewType),
MustBlockCards(TrackableTypes.CardViewCollectionType), MustBlockCards(TrackableTypes.CardViewCollectionType),

View File

@@ -1,7 +1,7 @@
Name:Arcane Bombardment Name:Arcane Bombardment
ManaCost:4 R R ManaCost:4 R R
Types:Enchantment Types:Enchantment
T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | ActivatorThisTurnCast$ EQ1 | NoResolvingCheck$ True | Execute$ TrigExile | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast your first instant or sorcery spell each turn, exile an instant or sorcery card at random from your graveyard. Then copy each card exiled with CARDNAME. You may cast any number of the copies without paying their mana costs. T:Mode$ SpellCast | ValidCard$ Instant,Sorcery | ValidActivatingPlayer$ You | ActivatorThisTurnCast$ EQ1 | NoResolvingCheck$ True | Execute$ TrigExile | TriggerZones$ Battlefield | OrderDuplicates$ True | TriggerDescription$ Whenever you cast your first instant or sorcery spell each turn, exile an instant or sorcery card at random from your graveyard. Then copy each card exiled with CARDNAME. You may cast any number of the copies without paying their mana costs.
SVar:TrigExile:DB$ ChangeZone | DefinedPlayer$ You | Destination$ Exile | ChangeNum$ 1 | ChangeType$ Instant.YouOwn,Sorcery.YouOwn | AtRandom$ True | Origin$ Graveyard | Hidden$ True | Mandatory$ True | SubAbility$ DBCast SVar:TrigExile:DB$ ChangeZone | DefinedPlayer$ You | Destination$ Exile | ChangeNum$ 1 | ChangeType$ Instant.YouOwn,Sorcery.YouOwn | AtRandom$ True | Origin$ Graveyard | Hidden$ True | Mandatory$ True | SubAbility$ DBCast
SVar:DBCast:DB$ Play | Valid$ Card.ExiledWithSource | ValidSA$ Spell | ValidZone$ Exile | Amount$ All | CopyCard$ True | Optional$ True | WithoutManaCost$ True SVar:DBCast:DB$ Play | Valid$ Card.ExiledWithSource | ValidSA$ Spell | ValidZone$ Exile | Amount$ All | CopyCard$ True | Optional$ True | WithoutManaCost$ True
DeckNeeds:Type$Instant|Sorcery DeckNeeds:Type$Instant|Sorcery

View File

@@ -560,6 +560,15 @@ public class CardDetailUtil {
area.append(StringUtils.join(card.getImprintedCards(), ", ")); area.append(StringUtils.join(card.getImprintedCards(), ", "));
} }
// CardsExiledBy
if (card.getExiledCards() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Exiled: ");
area.append(StringUtils.join(card.getExiledCards(), ", "));
}
// Haunt // Haunt
if (card.getHauntedBy() != null) { if (card.getHauntedBy() != null) {
if (area.length() != 0) { if (area.length() != 0) {

View File

@@ -577,6 +577,7 @@ public class HumanPlay {
hostCard.addDelved(c); hostCard.addDelved(c);
final ZoneType o = c.getZone().getZoneType(); final ZoneType o = c.getZone().getZoneType();
final Card d = game.getAction().exile(c, null); final Card d = game.getAction().exile(c, null);
hostCard.addExiledCard(d);
d.setExiledWith(hostCard); d.setExiledWith(hostCard);
d.setExiledBy(hostCard.getController()); d.setExiledBy(hostCard.getController());
table.put(o, d.getZone().getZoneType(), d); table.put(o, d.getZone().getZoneType(), d);

View File

@@ -1842,7 +1842,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (!currentSa.isTrigger() && currentSa.usesTargeting()) { if (!currentSa.isTrigger() && currentSa.usesTargeting()) {
needPrompt = true; needPrompt = true;
} }
if (!needPrompt && !saStr.equals(firstStr)) { if (!needPrompt && !saStr.equals(firstStr) && !currentSa.hasParam("OrderDuplicates")) {
needPrompt = true; // prompt by default unless all abilities needPrompt = true; // prompt by default unless all abilities
// are the same // are the same
} }