From 1e5f9e93c63904682f55dc90230450cdbe07e39a Mon Sep 17 00:00:00 2001 From: swordshine Date: Sun, 9 Jun 2013 13:01:26 +0000 Subject: [PATCH] - Added Jester's Scepter and Void Maw --- .gitattributes | 3 + res/cardsfolder/j/jesters_scepter.txt | 15 ++ res/cardsfolder/v/void_maw.txt | 15 ++ src/main/java/forge/Card.java | 14 ++ src/main/java/forge/card/cost/Cost.java | 7 + .../card/cost/CostExiledMoveToGrave.java | 188 ++++++++++++++++++ 6 files changed, 242 insertions(+) create mode 100644 res/cardsfolder/j/jesters_scepter.txt create mode 100644 res/cardsfolder/v/void_maw.txt create mode 100644 src/main/java/forge/card/cost/CostExiledMoveToGrave.java diff --git a/.gitattributes b/.gitattributes index 43e461bf1ff..3fcdcea2928 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5570,6 +5570,7 @@ res/cardsfolder/j/jerrard_of_the_closed_fist.txt svneol=native#text/plain res/cardsfolder/j/jeska_warrior_adept.txt svneol=native#text/plain res/cardsfolder/j/jesters_cap.txt svneol=native#text/plain res/cardsfolder/j/jesters_mask.txt svneol=native#text/plain +res/cardsfolder/j/jesters_scepter.txt -text res/cardsfolder/j/jet_medallion.txt svneol=native#text/plain res/cardsfolder/j/jeweled_bird.txt -text res/cardsfolder/j/jeweled_spirit.txt svneol=native#text/plain @@ -12128,6 +12129,7 @@ res/cardsfolder/v/voice_of_truth.txt svneol=native#text/plain res/cardsfolder/v/voiceless_spirit.txt -text res/cardsfolder/v/voices_from_the_void.txt svneol=native#text/plain res/cardsfolder/v/void.txt -text svneol=unset#text/plain +res/cardsfolder/v/void_maw.txt -text res/cardsfolder/v/void_stalker.txt -text res/cardsfolder/v/voidmage_apprentice.txt -text svneol=unset#text/plain res/cardsfolder/v/voidmage_husher.txt svneol=native#text/plain @@ -14191,6 +14193,7 @@ src/main/java/forge/card/cost/CostDiscard.java -text src/main/java/forge/card/cost/CostDraw.java -text src/main/java/forge/card/cost/CostExile.java -text src/main/java/forge/card/cost/CostExileAndPay.java -text +src/main/java/forge/card/cost/CostExiledMoveToGrave.java -text src/main/java/forge/card/cost/CostGainLife.java -text src/main/java/forge/card/cost/CostMill.java -text src/main/java/forge/card/cost/CostPart.java -text diff --git a/res/cardsfolder/j/jesters_scepter.txt b/res/cardsfolder/j/jesters_scepter.txt new file mode 100644 index 00000000000..17743990fd0 --- /dev/null +++ b/res/cardsfolder/j/jesters_scepter.txt @@ -0,0 +1,15 @@ +Name:Jester's Scepter +ManaCost:3 +Types:Artifact +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile the top five cards of target player's library face down. +SVar:TrigExile:AB$ Mill | Cost$ 0 | ValidTgts$ Player | NumCards$ 5 | Destination$ Exile | ExileFaceDown$ True | RememberMilled$ True +S:Mode$ MayLookAt | Affected$ Card.IsRemembered | Player$ You | AffectedZone$ Exile | Description$ You may look at cards exiled with CARDNAME. +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ DBCleanup | Static$ True +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget +SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard +A:AB$ Counter | Cost$ 2 T ExiledMoveToGrave<1/Card.IsRemembered/card exiled with CARDNAME> | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SpellDescription$ Counter target spell if it has the same name as that card. +SVar:X:Targeted$Valid Card.sharesNameWith MovedToGrave +SVar:RemAIDeck:True +SVar:Picture:http://www.wizards.com/global/images/magic/general/jesters_scepter.jpg +Oracle:When Jester's Scepter enters the battlefield, exile the top five cards of target player's library face down. You may look at those cards for as long as they remain exiled.\n{2}, {T}, Put a card exiled with Jester's Scepter into its owner's graveyard: Counter target spell if it has the same name as that card. diff --git a/res/cardsfolder/v/void_maw.txt b/res/cardsfolder/v/void_maw.txt new file mode 100644 index 00000000000..eb734712256 --- /dev/null +++ b/res/cardsfolder/v/void_maw.txt @@ -0,0 +1,15 @@ +Name:Void Maw +ManaCost:4 B B +Types:Creature Horror +PT:4/5 +K:Trample +R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.Other | ReplaceWith$ Exile | Description$ If another creature would die, exile it instead. +SVar:Exile:AB$ ChangeZone | Cost$ 0 | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard | SubAbility$ DBRemember +SVar:DBRemember:DB$ Pump | RememberObjects$ ReplacedCard | ConditionDefined$ ReplacedCard | ConditionPresent$ Card.inZoneExile | ConditionCompare$ GE1 +T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget +SVar:DBForget:DB$ Pump | Defined$ TriggeredCard | ForgetObjects$ TriggeredCard +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Static$ True | ValidCard$ Card.Self | Execute$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +A:AB$ Pump | Cost$ ExiledMoveToGrave<1/Card.IsRemembered/card exiled with CARDNAME> | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ CARDNAME gets +2/+2 until end of turn. +SVar:Picture:http://www.wizards.com/global/images/magic/general/void_maw.jpg +Oracle:Trample\nIf another creature would die, exile it instead.\nPut a card exiled with Void Maw into its owner's graveyard: Void Maw gets +2/+2 until end of turn. diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index be0e06dab4f..063e61f4e5c 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -5796,6 +5796,20 @@ public class Card extends GameEntity implements Comparable { } } return false; + } else if (restriction.equals("MovedToGrave")) { + for (final SpellAbility sa : source.getCharacteristics().getSpellAbility()) { + final SpellAbility root = sa.getRootAbility(); + if (root != null && (root.getPaidList("MovedToGrave") != null) + && !root.getPaidList("MovedToGrave").isEmpty()) { + List list = root.getPaidList("MovedToGrave"); + for (Card card : list) { + if (this.getName().equals(card.getName())) { + return true; + } + } + } + } + return false; } else if (restriction.equals("NonToken")) { final List list = CardLists.filter(getGame().getCardsIn(ZoneType.Battlefield), Presets.NON_TOKEN); diff --git a/src/main/java/forge/card/cost/Cost.java b/src/main/java/forge/card/cost/Cost.java index 5620df36e57..1931017d091 100644 --- a/src/main/java/forge/card/cost/Cost.java +++ b/src/main/java/forge/card/cost/Cost.java @@ -313,6 +313,13 @@ public class Cost { final String description = splitStr.length > 2 ? splitStr[2] : null; return new CostReveal(splitStr[0], splitStr[1], description); } + + if (parse.startsWith("ExiledMoveToGrave<")) { + final String[] splitStr = abCostParse(parse, 3); + final String description = splitStr.length > 2 ? splitStr[2] : null; + return new CostExiledMoveToGrave(splitStr[0], splitStr[1], description); + } + if (parse.startsWith("DrawYou<")) { final String[] splitStr = abCostParse(parse, 1); return new CostDraw(splitStr[0], "You"); diff --git a/src/main/java/forge/card/cost/CostExiledMoveToGrave.java b/src/main/java/forge/card/cost/CostExiledMoveToGrave.java new file mode 100644 index 00000000000..867bdfbb82b --- /dev/null +++ b/src/main/java/forge/card/cost/CostExiledMoveToGrave.java @@ -0,0 +1,188 @@ +/* + * Forge: Play Magic: the Gathering. + * Copyright (C) 2011 Forge Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package forge.card.cost; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import forge.Card; +import forge.CardLists; +import forge.card.ability.AbilityUtils; +import forge.card.spellability.SpellAbility; +import forge.game.Game; +import forge.game.player.Player; +import forge.game.zone.ZoneType; +import forge.gui.GuiChoose; + +/** + * This is for the "ExiledMoveToGrave" Cost. + */ +public class CostExiledMoveToGrave extends CostPartWithList { + // ExiledMoveToGrave + + /** + * Instantiates a new cost CostExiledMoveToGrave. + * + * @param amount + * the amount + * @param type + * the type + * @param description + * the description + */ + public CostExiledMoveToGrave(final String amount, final String type, final String description) { + super(amount, type, description); + } + + /* + * (non-Javadoc) + * + * @see forge.card.cost.CostPart#toString() + */ + @Override + public final String toString() { + final StringBuilder sb = new StringBuilder(); + final Integer i = this.convertAmount(); + sb.append("Put "); + + final String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription(); + sb.append(Cost.convertAmountTypeToWords(i, this.getAmount(), desc)); + + sb.append(" into its owner's graveyard"); + + return sb.toString(); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#getHashForList() + */ + @Override + public String getHashForList() { + return "MovedToGrave"; + } + + /* + * (non-Javadoc) + * + * @see + * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility, + * forge.Card, forge.Player, forge.card.cost.Cost) + */ + @Override + public final boolean canPay(final SpellAbility ability) { + final Player activator = ability.getActivatingPlayer(); + final Card source = ability.getSourceCard(); + + Integer i = this.convertAmount(); + + if (i == null) { + i = AbilityUtils.calculateAmount(source, this.getAmount(), ability); + } + + + List typeList = activator.getGame().getCardsIn(ZoneType.Exile); + + typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source); + if (typeList.size() < i) { + return false; + } + + return true; + + } + + /* + * (non-Javadoc) + * + * @see + * forge.card.cost.CostPart#payHuman(forge.card.spellability.SpellAbility, + * forge.Card, forge.card.cost.Cost_Payment) + */ + @Override + public final boolean payHuman(final SpellAbility ability, final Game game) { + final String amount = this.getAmount(); + Integer c = this.convertAmount(); + final Card source = ability.getSourceCard(); + final Player activator = ability.getActivatingPlayer(); + + List list = activator.getGame().getCardsIn(ZoneType.Exile); + + + if (c == null) { + c = AbilityUtils.calculateAmount(source, amount, ability); + } + + list = CardLists.getValidCards(list, this.getType().split(";"), activator, source); + + for (int i = 0; i < c; i++) { + if (list.isEmpty()) { + return false; + } + + final Card card = GuiChoose.oneOrNone("Choose an exiled card to put into graveyard", list); + + if (card != null) { + list.remove(card); + executePayment(ability, card); + } else { + return false; + } + } + return true; + + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + protected void doPayment(SpellAbility ability, Card targetCard) { + ability.getActivatingPlayer().getGame().getAction().moveToGraveyard(targetCard); + } + + /* (non-Javadoc) + * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) + */ + @Override + public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { + Integer c = this.convertAmount(); + List chosen = new ArrayList(); + + if (c == null) { + c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); + } + + List typeList = ai.getGame().getCardsIn(ZoneType.Exile); + + typeList = CardLists.getValidCards(typeList, this.getType().split(","), ai, source); + + if (typeList.size() < c) { + return null; + } + + CardLists.sortByPowerAsc(typeList); + Collections.reverse(typeList); + + for (int i = 0; i < c; i++) { + chosen.add(typeList.get(i)); + } + + return chosen.isEmpty() ? null : new PaymentDecision(chosen); + } +}