From ea94d76c0f94165631e1f57b76dd3a21a2ec1654 Mon Sep 17 00:00:00 2001 From: moomarc Date: Tue, 19 Mar 2013 16:35:41 +0000 Subject: [PATCH] - Added Infinite Reflection - Converted Essence of the Wild to script - added ImageSource parameter to CloneEffect - some small checkstyle fixed --- .gitattributes | 1 + res/cardsfolder/e/essence_of_the_wild.txt | 2 + res/cardsfolder/i/infinite_reflection.txt | 16 ++++++ .../java/forge/card/ability/ai/AttachAi.java | 16 +++++- .../card/ability/effects/CloneEffect.java | 5 ++ .../cardfactory/CardFactoryCreatures.java | 47 ---------------- .../card/cardfactory/CardFactoryUtil.java | 55 +++++++++++-------- 7 files changed, 70 insertions(+), 72 deletions(-) create mode 100644 res/cardsfolder/i/infinite_reflection.txt diff --git a/.gitattributes b/.gitattributes index 72a0f0c6f00..286ce5b4e8e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5226,6 +5226,7 @@ res/cardsfolder/i/infiltration_lens.txt svneol=native#text/plain res/cardsfolder/i/infiltrator_il_kor.txt svneol=native#text/plain res/cardsfolder/i/infiltrators_magemark.txt -text res/cardsfolder/i/infinite_hourglass.txt -text +res/cardsfolder/i/infinite_reflection.txt -text res/cardsfolder/i/inflame.txt svneol=native#text/plain res/cardsfolder/i/information_dealer.txt svneol=native#text/plain res/cardsfolder/i/infuse.txt svneol=native#text/plain diff --git a/res/cardsfolder/e/essence_of_the_wild.txt b/res/cardsfolder/e/essence_of_the_wild.txt index 057e92175c6..242a1809739 100644 --- a/res/cardsfolder/e/essence_of_the_wild.txt +++ b/res/cardsfolder/e/essence_of_the_wild.txt @@ -2,6 +2,8 @@ Name:Essence of the Wild ManaCost:3 G G G Types:Creature Avatar PT:6/6 +K:ETBReplacement:Copy:EssenceClone:Mandatory:Battlefield:Creature.YouCtrl +SVar:EssenceClone:DB$ Clone | Defined$ Self | CloneTarget$ ReplacedCard | SpellDescription$ Creatures you control enter the battlefield as a copy of CARDNAME. SVar:Picture:http://www.wizards.com/global/images/magic/general/essence_of_the_wild.jpg Oracle:Creatures you control enter the battlefield as a copy of Essence of the Wild. SetInfo:ISD Mythic \ No newline at end of file diff --git a/res/cardsfolder/i/infinite_reflection.txt b/res/cardsfolder/i/infinite_reflection.txt new file mode 100644 index 00000000000..b7f3daa9542 --- /dev/null +++ b/res/cardsfolder/i/infinite_reflection.txt @@ -0,0 +1,16 @@ +Name:Infinite Reflection +ManaCost:5 U +Types:Enchantment Aura +K:Enchant creature +A:SP$ Attach | Cost$ 5 U | ValidTgts$ Creature | AILogic$ HighestEvaluation +T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+AttachedTo Card | Execute$ RememberInitialAttach | Static$ True +SVar:RememberInitialAttach:DB$ Pump | RememberObjects$ Valid Card.AttachedBy +T:Mode$ ChangesZone | Destination$ Battlefield | ValidCard$ Card.Self+AttachedTo Card | Execute$ FirstReflections | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature. +SVar:FirstReflections:DB$ RepeatEach | RepeatCards$ Creature.nonToken+YouCtrl | UseImprinted$ True | Zone$ Battlefield | RepeatSubAbility$ Reflect | SubAbility$ DBCleanup +SVar:Reflect:DB$ Clone | Defined$ Remembered | CloneTarget$ Imprinted | ImageSource$ Remembered +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +K:ETBReplacement:Copy:Reflections:Mandatory:Battlefield:Creature.nonToken+YouCtrl +SVar:Reflections:DB$ Clone | Defined$ Enchanted | CloneTarget$ ReplacedCard | ImageSource$ Enchanted | SpellDescription$ Nontoken creatures you control enter the battlefield as a copy of enchanted creature. +SVar:Picture:http://www.wizards.com/global/images/magic/general/infinite_reflection.jpg +Oracle:Enchant creature\nWhen Infinite Reflection enters the battlefield attached to a creature, each other nontoken creature you control becomes a copy of that creature.\nNontoken creatures you control enter the battlefield as a copy of enchanted creature. +SetInfo:AVR Rare \ No newline at end of file diff --git a/src/main/java/forge/card/ability/ai/AttachAi.java b/src/main/java/forge/card/ability/ai/AttachAi.java index 946c1a242ba..65ad5050c43 100644 --- a/src/main/java/forge/card/ability/ai/AttachAi.java +++ b/src/main/java/forge/card/ability/ai/AttachAi.java @@ -352,7 +352,7 @@ public class AttachAi extends SpellAbilityAi { } /** - * Attach ai control preference. + * Attach ai reanimate preference. * * @param sa * the sa @@ -380,7 +380,7 @@ public class AttachAi extends SpellAbilityAi { } /** - * Attach ai control preference. + * Attach ai specific card preference. * * @param sa * the sa @@ -463,6 +463,16 @@ public class AttachAi extends SpellAbilityAi { return acceptableChoice(c, mandatory); } + /** + * Attach ai highest evaluated preference. + * + * @param list the initial valid list + * @return the card + */ + private static Card attachAIHighestEvaluationPreference(final List list) { + return ComputerUtilCard.getBestAI(list); + } + /** * Attach ai curse preference. * @@ -947,6 +957,8 @@ public class AttachAi extends SpellAbilityAi { c = attachAIReanimatePreference(sa, prefList, mandatory, attachSource); } else if ("SpecificCard".equals(logic)) { c = attachAISpecificCardPreference(sa, prefList, mandatory, attachSource); + } else if ("HighestEvaluation".equals(logic)) { + c = attachAIHighestEvaluationPreference(prefList); } return c; diff --git a/src/main/java/forge/card/ability/effects/CloneEffect.java b/src/main/java/forge/card/ability/effects/CloneEffect.java index 517a9cffab6..4077402337c 100644 --- a/src/main/java/forge/card/ability/effects/CloneEffect.java +++ b/src/main/java/forge/card/ability/effects/CloneEffect.java @@ -86,7 +86,12 @@ public class CloneEffect extends SpellAbilityEffect { tgtCard = cloneTargets.get(0); } + // determine the image to be used for the clone String imageFileName = host.getImageKey(); + List cloneImgSources = AbilityUtils.getDefinedCards(host, sa.getParam("ImageSource"), sa); + if (!cloneImgSources.isEmpty()) { + imageFileName = cloneImgSources.get(0).getImageKey(); + } boolean keepName = sa.hasParam("KeepName"); String originalName = tgtCard.getName(); diff --git a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java index bf27308d9b5..40856e3aa3c 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java @@ -27,7 +27,6 @@ import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import forge.Card; -import forge.CardCharacteristicName; import forge.CardLists; import forge.CardPredicates; import forge.CardPredicates.Presets; @@ -37,9 +36,6 @@ import forge.Singletons; import forge.card.ability.AbilityFactory; import forge.card.cost.Cost; import forge.card.mana.ManaCost; -import forge.card.replacement.ReplacementEffect; -import forge.card.replacement.ReplacementHandler; -import forge.card.replacement.ReplacementLayer; import forge.card.spellability.Ability; import forge.card.spellability.AbilityActivated; import forge.card.spellability.AbilityStatic; @@ -687,47 +683,6 @@ public class CardFactoryCreatures { card.addSpellAbility(finalAb); } - private static void getCard_EssenceOfTheWild(final Card card) { - class EOTWReplacement extends Ability { - - /** - * TODO: Write javadoc for Constructor. - * @param sourceCard - * @param manaCost - */ - public EOTWReplacement(Card sourceCard, ManaCost manaCost) { - super(sourceCard, manaCost); - } - - /* (non-Javadoc) - * @see forge.card.spellability.SpellAbility#resolve() - */ - @Override - public void resolve() { - Card movedCard = (Card) this.getReplacingObject("Card"); - if (movedCard.isCloned()) { // cloning again - movedCard.switchStates(CardCharacteristicName.Cloner, CardCharacteristicName.Original); - movedCard.setState(CardCharacteristicName.Original); - movedCard.clearStates(CardCharacteristicName.Cloner); - } - movedCard.addAlternateState(CardCharacteristicName.Cloner); - movedCard.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloner); - movedCard.setState(CardCharacteristicName.Original); - movedCard.getCharacteristics().copy(this.getSourceCard().getCharacteristics()); - } - - } - - SpellAbility repAb = new EOTWReplacement(card, ManaCost.ZERO); - CardFactoryUtil.setupETBReplacementAbility(repAb); - - ReplacementEffect re = ReplacementHandler.parseReplacement("Event$ Moved | ValidCard$ Creature.Other+YouCtrl | Destination$ Battlefield | ActiveZones$ Battlefield | Description$ Creatures you control enter the battlefield as copies of CARDNAME.", card); - re.setLayer(ReplacementLayer.Copy); - re.setOverridingAbility(repAb); - - card.addReplacementEffect(re); - } - // // This is a hardcoded card template // // private static void getCard_(final Card card, final String cardName) { @@ -754,8 +709,6 @@ public class CardFactoryCreatures { } else if (cardName.equals("Duct Crawler") || cardName.equals("Shrewd Hatchling") || cardName.equals("Spin Engine") || cardName.equals("Screeching Griffin")) { getCard_DuctCrawler(card, cardName); - } else if (cardName.equals("Essence of the Wild")) { - getCard_EssenceOfTheWild(card); } // *************************************************** diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index 2f03178b575..f7c91c15f0d 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -659,13 +659,13 @@ public class CardFactoryUtil { */ public static int getNumberOfManaSymbolsByColor(final String colorAbb, final List cards) { int count = 0; - for(Card c : cards) { + for (Card c : cards) { // Certain tokens can have mana cost, so don't skip them count += CardFactoryUtil.getNumberOfManaSymbolsByColor(colorAbb, c); } return count; } - + /** *

* getNumberOfManaSymbolsByColor. @@ -1174,7 +1174,7 @@ public class CardFactoryUtil { return CardFactoryUtil.doXMath(players.get(0).getLifeLostThisTurn(), m, source); } } - + if (sq[0].contains("PoisonCounters")) { if (players.size() > 0) { return CardFactoryUtil.doXMath(players.get(0).getPoisonCounters(), m, source); @@ -2134,19 +2134,19 @@ public class CardFactoryUtil { if (sq[0].equals("Random")) { int min = 0; int max = 0; - + if (StringUtils.isNumeric(sq[1])) { min = Integer.parseInt(sq[1]); } else { min = CardFactoryUtil.xCount(c, c.getSVar(sq[1])); } - + if (StringUtils.isNumeric(sq[2])) { max = Integer.parseInt(sq[2]); } else { max = CardFactoryUtil.xCount(c, c.getSVar(sq[2])); } - + return forge.util.MyRandom.getRandom().nextInt(max) + min; } @@ -2568,7 +2568,7 @@ public class CardFactoryUtil { final SpellAbility sa = card.getSpellAbility()[0]; sa.setIsMultiKicker(true); - sa.setMultiKickerManaCost(new ManaCost( new ManaCostParser(k[1]))); + sa.setMultiKickerManaCost(new ManaCost(new ManaCostParser(k[1]))); } } @@ -2651,36 +2651,36 @@ public class CardFactoryUtil { if (championPos != -1) { String parse = card.getKeyword().get(championPos); card.removeIntrinsicKeyword(parse); - + final String[] k = parse.split(":"); final String[] valid = k[1].split(","); String desc = k.length > 2 ? k[2] : k[1]; - + StringBuilder changeType = new StringBuilder(); - for(String v : valid) { + for (String v : valid) { if (changeType.length() != 0) { changeType.append(","); } changeType.append(v).append(".YouCtrl+Other"); } - + StringBuilder trig = new StringBuilder(); trig.append("Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | "); trig.append("Execute$ ChampionAbility | TriggerDescription$ Champion a(n) "); trig.append(desc).append(" (When this enters the battlefield, sacrifice it unless you exile another "); trig.append(desc).append(" you control. When this leaves the battlefield, that card returns to the battlefield.)"); - + StringBuilder trigReturn = new StringBuilder(); trigReturn.append("Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | "); trigReturn.append("Execute$ ChampionReturn | Secondary$ True | TriggerDescription$ When this leaves the battlefield, that card returns to the battlefield."); - + StringBuilder ab = new StringBuilder(); ab.append("DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | Champion$ True | "); ab.append("Hidden$ True | Optional$ True | SubAbility$ DBSacrifice | ChangeType$ ").append(changeType); - + StringBuilder subAb = new StringBuilder(); subAb.append("DB$ Sacrifice | Defined$ Card.Self | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0"); - + String returnChampion = "DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield"; final Trigger parsedTrigger = TriggerHandler.parseTrigger(trig.toString(), card, true); final Trigger parsedTrigReturn = TriggerHandler.parseTrigger(trigReturn.toString(), card, true); @@ -2690,7 +2690,7 @@ public class CardFactoryUtil { card.setSVar("ChampionReturn", returnChampion); card.setSVar("DBSacrifice", subAb.toString()); } - + final int echoPos = CardFactoryUtil.hasKeyword(card, "Echo"); if (echoPos != -1) { // card.removeIntrinsicKeyword(parse); @@ -2966,14 +2966,23 @@ public class CardFactoryUtil { String desc = repAb.getDescription(); setupETBReplacementAbility(repAb); - String repeffstr = "Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | Description$ " + desc; - if (splitkw.length == 4) { + final String valid = splitkw.length >= 6 ? splitkw[5] : "Card.Self"; + + StringBuilder repEffsb = new StringBuilder(); + repEffsb.append("Event$ Moved | ValidCard$ ").append(valid); + repEffsb.append(" | Destination$ Battlefield | Description$ ").append(desc); + if (splitkw.length >= 4) { if (splitkw[3].contains("Optional")) { - repeffstr += " | Optional$ True"; + repEffsb.append(" | Optional$ True"); + } + } + if (splitkw.length >= 5) { + if (!splitkw[4].isEmpty()) { + repEffsb.append(" | ActiveZones$ " + splitkw[4]); } } - ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card); + ReplacementEffect re = ReplacementHandler.parseReplacement(repEffsb.toString(), card); re.setLayer(layer); re.setOverridingAbility(repAb); @@ -3085,7 +3094,7 @@ public class CardFactoryUtil { if (card.getController().isHuman()) { game.getActionPlay().playSpellAbilityNoStack(card.getController(), origSA, false); } else { - ComputerUtil.playNoStack((AIPlayer)card.getController(), origSA, game); + ComputerUtil.playNoStack((AIPlayer) card.getController(), origSA, game); } } }; @@ -3142,7 +3151,7 @@ public class CardFactoryUtil { }; haunterDiesWork.setDescription(hauntDescription); - final InputSelectManyCards target = new InputSelectManyCards(1,1) { + final InputSelectManyCards target = new InputSelectManyCards(1, 1) { private static final long serialVersionUID = 1981791992623774490L; @Override @@ -3160,7 +3169,7 @@ public class CardFactoryUtil { } return c.canBeTargetedBy(haunterDiesWork); } - }; + }; target.setMessage("Choose target creature to haunt."); final Ability haunterDiesSetup = new Ability(card, ManaCost.ZERO) {