From f0c852c54f0116c88fda45dc9005404ed7a4fead Mon Sep 17 00:00:00 2001 From: Tim Mocny Date: Mon, 25 Oct 2021 09:01:43 +0000 Subject: [PATCH] Blacker Lotus and Look at Me, I'm the DCI --- .../src/main/java/forge/ai/SpellApiToAi.java | 1 + .../src/main/java/forge/game/Match.java | 46 +++++++++++-------- .../main/java/forge/game/ability/ApiType.java | 1 + .../effects/RemoveFromMatchEffect.java | 37 +++++++++++++++ forge-gui/res/cardsfolder/b/blacker_lotus.txt | 6 +++ .../cardsfolder/l/look_at_me_im_the_dci.txt | 6 +++ 6 files changed, 79 insertions(+), 18 deletions(-) create mode 100644 forge-game/src/main/java/forge/game/ability/effects/RemoveFromMatchEffect.java create mode 100644 forge-gui/res/cardsfolder/b/blacker_lotus.txt create mode 100644 forge-gui/res/cardsfolder/l/look_at_me_im_the_dci.txt diff --git a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java index f0829816f72..e784c4d68a1 100644 --- a/forge-ai/src/main/java/forge/ai/SpellApiToAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellApiToAi.java @@ -140,6 +140,7 @@ public enum SpellApiToAi { .put(ApiType.RemoveCounterAll, CannotPlayAi.class) .put(ApiType.RemoveFromCombat, RemoveFromCombatAi.class) .put(ApiType.RemoveFromGame, AlwaysPlayAi.class) + .put(ApiType.RemoveFromMatch, AlwaysPlayAi.class) .put(ApiType.ReorderZone, AlwaysPlayAi.class) .put(ApiType.Repeat, RepeatAi.class) .put(ApiType.RepeatEach, RepeatEachAi.class) diff --git a/forge-game/src/main/java/forge/game/Match.java b/forge-game/src/main/java/forge/game/Match.java index 6177720f34f..beac2accbb4 100644 --- a/forge-game/src/main/java/forge/game/Match.java +++ b/forge-game/src/main/java/forge/game/Match.java @@ -1,24 +1,7 @@ package forge.game; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.HashMultimap; -import com.google.common.collect.HashMultiset; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multiset; +import com.google.common.collect.*; import com.google.common.eventbus.EventBus; - import forge.LobbyPlayer; import forge.deck.CardPool; import forge.deck.Deck; @@ -40,7 +23,11 @@ import forge.util.Localizer; import forge.util.MyRandom; import forge.util.collect.FCollectionView; +import java.util.*; +import java.util.Map.Entry; + public class Match { + private static List removedCards = Lists.newArrayList(); private final List players; private final GameRules rules; private final String title; @@ -198,6 +185,12 @@ public class Match { return myRemovedAnteCards; } + public static List getRemovedCards() { return removedCards; } + + public void removeCard(PaperCard c) { + removedCards.add(c); + } + private static void preparePlayerZone(Player player, final ZoneType zoneType, CardPool section, boolean canRandomFoil) { PlayerZone library = player.getZone(zoneType); List newLibrary = new ArrayList<>(); @@ -257,6 +250,23 @@ public class Match { } Deck toChange = psc.getDeck(); + if (!getRemovedCards().isEmpty()) { + CardPool main = new CardPool(); + main.addAll(toChange.get(DeckSection.Main)); + CardPool sideboard = new CardPool(); + sideboard.addAll(toChange.getOrCreate(DeckSection.Sideboard)); + for (PaperCard c : removedCards) { + if (main.contains(c)) { + main.remove(c, 1); + } else if (sideboard.contains(c)) { + sideboard.remove(c, 1); + } + } + toChange.getMain().clear(); + toChange.getMain().addAll(main); + toChange.get(DeckSection.Sideboard).clear(); + toChange.get(DeckSection.Sideboard).addAll(sideboard); + } List newMain = person.sideboard(toChange, rules.getGameType(), player.getName()); if (null != newMain) { CardPool allCards = new CardPool(); diff --git a/forge-game/src/main/java/forge/game/ability/ApiType.java b/forge-game/src/main/java/forge/game/ability/ApiType.java index 3aa8a5cda27..8808b208c2e 100644 --- a/forge-game/src/main/java/forge/game/ability/ApiType.java +++ b/forge-game/src/main/java/forge/game/ability/ApiType.java @@ -139,6 +139,7 @@ public enum ApiType { RemoveCounterAll (CountersRemoveAllEffect.class), RemoveFromCombat (RemoveFromCombatEffect.class), RemoveFromGame (RemoveFromGameEffect.class), + RemoveFromMatch (RemoveFromMatchEffect.class), ReorderZone (ReorderZoneEffect.class), Repeat (RepeatEffect.class), RepeatEach (RepeatEachEffect.class), diff --git a/forge-game/src/main/java/forge/game/ability/effects/RemoveFromMatchEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RemoveFromMatchEffect.java new file mode 100644 index 00000000000..f06bc534c39 --- /dev/null +++ b/forge-game/src/main/java/forge/game/ability/effects/RemoveFromMatchEffect.java @@ -0,0 +1,37 @@ +package forge.game.ability.effects; + +import forge.game.ability.AbilityUtils; +import forge.game.ability.SpellAbilityEffect; +import forge.game.card.Card; +import forge.game.card.CardCollection; +import forge.game.event.GameEventRandomLog; +import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; +import forge.item.PaperCard; + +public class RemoveFromMatchEffect extends SpellAbilityEffect { + @Override + public void resolve(SpellAbility sa) { + final Card host = sa.getHostCard(); + CardCollection toRemove; + + if (sa.hasParam("RemoveType")) { + CardCollection cards = (CardCollection) host.getOwner().getGame().getCardsInGame(); + if (sa.hasParam("IncludeSideboard")) { + CardCollection sideboard = (CardCollection) host.getGame().getCardsIn(ZoneType.Sideboard); + cards.addAll(sideboard); + } + toRemove = (CardCollection) AbilityUtils.filterListByType(cards, sa.getParam("RemoveType"), sa); + } else { + toRemove = getTargetCards(sa); + } + String logMessage = sa.getParamOrDefault("LogMessage", "Removed from match"); + String remove = toRemove.toString().replace("[","").replace("]",""); + host.getController().getGame().fireEvent(new GameEventRandomLog(logMessage + ": " + remove)); + for (final Card tgtC : toRemove) { + tgtC.getGame().getAction().ceaseToExist(tgtC, true); + PaperCard rem = (PaperCard) tgtC.getPaperCard(); + host.getGame().getMatch().removeCard(rem); + } + } +} \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/b/blacker_lotus.txt b/forge-gui/res/cardsfolder/b/blacker_lotus.txt new file mode 100644 index 00000000000..1dbe01751b9 --- /dev/null +++ b/forge-gui/res/cardsfolder/b/blacker_lotus.txt @@ -0,0 +1,6 @@ +Name:Blacker Lotus +ManaCost:0 +Types:Artifact +A:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 4 | AILogic$ BlackLotus | SubAbility$ DBTearUpAndRemove | SpellDescription$ Tear CARDNAME into pieces. Add four mana of any one color. Remove the pieces from the game. +SVar:DBTearUpAndRemove:DB$ RemoveFromMatch | Defined$ Self | LogMessage$ Torn to pieces and removed +Oracle:{T}: Tear Blacker Lotus into pieces. Add four mana of any one color. Remove the pieces from the game. diff --git a/forge-gui/res/cardsfolder/l/look_at_me_im_the_dci.txt b/forge-gui/res/cardsfolder/l/look_at_me_im_the_dci.txt new file mode 100644 index 00000000000..0f526ba3bc0 --- /dev/null +++ b/forge-gui/res/cardsfolder/l/look_at_me_im_the_dci.txt @@ -0,0 +1,6 @@ +Name:Look at Me, I'm the DCI +ManaCost:5 W W +Types:Sorcery +A:SP$ NameCard | Defined$ You | ValidCards$ Card.nonBasic | SelectPrompt$ Choose a card other than a basic land card to ban | SubAbility$ DBRemove | AILogic$ MostProminentInHumanDeck | StackDescription$ None | SpellDescription$ Ban a card other than a basic land card for the rest of the match. (All cards with that name in any zone or sideboard are removed from the match.) +SVar:DBRemove:DB$ RemoveFromMatch | RemoveType$ Card.NamedCard | IncludeSideboard$ True | StackDescription$ Ban a card other than a basic land card for the rest of the match. (All cards with that name in any zone or sideboard are removed from the match.) +Oracle:Ban a card other than a basic land card for the rest of the match. (All cards with that name in any zone or sideboard are removed from the match.)