diff --git a/res/cardsfolder/burst_of_energy.txt b/res/cardsfolder/burst_of_energy.txt index ced3987cd9b..1a144af87a8 100644 --- a/res/cardsfolder/burst_of_energy.txt +++ b/res/cardsfolder/burst_of_energy.txt @@ -2,7 +2,7 @@ Name:Burst of Energy ManaCost:W Types:Instant Text:no text -K:spUntapTgt:Permanent:Untap target permanent. +A:SP$Untap|Cost$W|TgtPrompt$Choose target permanent|ValidTgts$Permanent|SpellDescription$Untap target Permanent. SVar:RemAIDeck:True SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/burst_of_energy.jpg diff --git a/res/cardsfolder/mind_games.txt b/res/cardsfolder/mind_games.txt index 9bbb5d63964..4fb9fc198a7 100644 --- a/res/cardsfolder/mind_games.txt +++ b/res/cardsfolder/mind_games.txt @@ -2,7 +2,7 @@ Name:Mind Games ManaCost:U Types:Instant Text:no text -K:spTapTgt:Artifact,Creature,Land:Tap target artifact, creature, or land. +A:SP$Tap|Cost$U|TgtPrompt$Choose target artifact, creature or land|ValidTgts$Artifact,Creature,Land|SpellDescription$Tap target artifact, creature or land. SVar:Buyback:2 U SVar:RemAIDeck:True SVar:Rarity:Common diff --git a/src/forge/AbilityFactory.java b/src/forge/AbilityFactory.java index eb12063756f..48fe58b8c04 100644 --- a/src/forge/AbilityFactory.java +++ b/src/forge/AbilityFactory.java @@ -136,10 +136,14 @@ public class AbilityFactory { if (isTargeted) { + int min = mapParams.containsKey("TargetMin") ? Integer.parseInt(mapParams.get("TargetMin")) : 1; + int max = mapParams.containsKey("TargetMax") ? Integer.parseInt(mapParams.get("TargetMax")) : 1; + if (hasValid) - abTgt = new Target("TgtV", mapParams.get("TgtPrompt"), mapParams.get("ValidTgts").split(",")); + abTgt = new Target(mapParams.get("TgtPrompt"), mapParams.get("ValidTgts").split(","), min, max); else - abTgt = new Target(mapParams.get("Tgt")); + abTgt = new Target(mapParams.get("Tgt"), min, max); + if (mapParams.containsKey("TgtZone")) // if Targeting something not in play, this Key should be set abTgt.setZone(mapParams.get("TgtZone")); } @@ -251,6 +255,14 @@ public class AbilityFactory { } } + if (API.equals("Tap")){ + if (isAb) + SA = AbilityFactory_PermanentState.createAbilityTap(this); + if (isSp){ + SA = AbilityFactory_PermanentState.createSpellTap(this); + } + } + if (API.equals("Regenerate")){ if (isAb) SA = AbilityFactory_Regenerate.getAbility(this); diff --git a/src/forge/AbilityFactory_DealDamage.java b/src/forge/AbilityFactory_DealDamage.java index 20b2c95b328..3845b6d809f 100644 --- a/src/forge/AbilityFactory_DealDamage.java +++ b/src/forge/AbilityFactory_DealDamage.java @@ -176,7 +176,8 @@ public class AbilityFactory_DealDamage { else if (AF.isSpell()) rr = true; - if(AF.getAbTgt().canTgtCreaturePlayer()) { + // TODO: Consider targeting the planeswalker + if(AF.getAbTgt().canTgtCreatureAndPlayer()) { if(shouldTgtP(damage)) { saMe.setTargetPlayer(AllZone.HumanPlayer); return rr; diff --git a/src/forge/AbilityFactory_Fetch.java b/src/forge/AbilityFactory_Fetch.java index 54c44aa4ac9..7ae4e4782eb 100644 --- a/src/forge/AbilityFactory_Fetch.java +++ b/src/forge/AbilityFactory_Fetch.java @@ -171,8 +171,8 @@ public class AbilityFactory_Fetch { // Fetching should occur fairly often as it helps cast more spells, and have access to more mana Ability_Cost abCost = af.getAbCost(); Card source = af.getHostCard(); - HashMap params = af.getMapParams(); - String destination = params.get("Destination"); + //HashMap params = af.getMapParams(); + //String destination = params.get("Destination"); if (abCost != null){ // AI currently disabled for these costs diff --git a/src/forge/AbilityFactory_PermanentState.java b/src/forge/AbilityFactory_PermanentState.java index 1fd890acbbe..9b55ef4aed1 100644 --- a/src/forge/AbilityFactory_PermanentState.java +++ b/src/forge/AbilityFactory_PermanentState.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Random; public class AbilityFactory_PermanentState { + // Untapping public static SpellAbility createAbilityUntap(final AbilityFactory AF){ final SpellAbility abUntap = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){ private static final long serialVersionUID = 5445572699000471299L; @@ -89,17 +90,7 @@ public class AbilityFactory_PermanentState { untapList = untapList.getTargetableCards(source); untapList = untapList.filter(AllZoneUtil.tapped); - if (tgt.canTgtCreature()){ - untapList = untapList.getType("Creature"); - - if (untapList.size() == 0) - return false; - - Card c = CardFactoryUtil.AI_getBestCreature(untapList); - if (c != null) - sa.setTargetCard(c); - } - else if (tgt.canTgtValid()){ + if (tgt.doesTarget()){ untapList = untapList.getValidCards(tgt.getValidTgts(), source.getController()); if (untapList.size() == 0) @@ -149,4 +140,145 @@ public class AbilityFactory_PermanentState { CardFactoryUtil.doDrawBack(DrawBack, 0, card.getController(), card.getController().getOpponent(), card.getController(), card, null, sa); } + + // ****** Tapping ******** + public static SpellAbility createAbilityTap(final AbilityFactory AF){ + final SpellAbility abTap = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){ + private static final long serialVersionUID = 5445572699000471299L; + + final AbilityFactory af = AF; + + @Override + public String getStackDescription(){ + // when getStackDesc is called, just build exactly what is happening + StringBuilder sb = new StringBuilder("Untap "); + String name = af.getHostCard().getName(); + Card tgt = getTargetCard(); + if (tgt != null) + sb.append(tgt.getName()); + else + sb.append(name); + return sb.toString(); + } + + public boolean canPlay(){ + // super takes care of AdditionalCosts + return super.canPlay(); + } + + public boolean canPlayAI() + { + return tapCanPlayAI(af,this); + } + + @Override + public void resolve() { + tapResolve(af, this); + } + + }; + return abTap; + } + + public static SpellAbility createSpellTap(final AbilityFactory AF){ + final SpellAbility spTap = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){ + private static final long serialVersionUID = -4990932993654533449L; + + final AbilityFactory af = AF; + + public boolean canPlay(){ + // super takes care of AdditionalCosts + return super.canPlay(); + } + + public boolean canPlayAI() + { + return tapCanPlayAI(af, this); + } + + @Override + public void resolve() { + tapResolve(af, this); + } + + }; + return spTap; + } + + public static boolean tapCanPlayAI(final AbilityFactory af, SpellAbility sa){ + // AI cannot use this properly until he can use SAs during Humans turn + if (!ComputerUtil.canPayCost(sa)) + return false; + + Target tgt = af.getAbTgt(); + Card source = sa.getSourceCard(); + + Random r = new Random(); + boolean randomReturn = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed()); + + + + if (tgt == null){ + if (sa.getSourceCard().isTapped()) + return false; + } + else{ + CardList tapList = AllZoneUtil.getPlayerCardsInPlay(AllZone.HumanPlayer); + tapList = tapList.getTargetableCards(source); + tapList = tapList.filter(AllZoneUtil.untapped); + + if (tgt.doesTarget()){ + tapList = tapList.getValidCards(tgt.getValidTgts(), source.getController()); + + if (tapList.size() == 0) + return false; + + Card c = null; + CardList dChoices = new CardList(); + String[] Tgts = tgt.getValidTgts(); + + for(int i = 0; i < Tgts.length; i++) { + if (Tgts[i].startsWith("Creature")) { + c = CardFactoryUtil.AI_getBestCreature(tapList); + if (c != null) + dChoices.add(c); + } + + CardListUtil.sortByTextLen(tapList); + dChoices.add(tapList.get(0)); + + CardListUtil.sortCMC(tapList); + dChoices.add(tapList.get(0)); + } + + c = dChoices.get(CardUtil.getRandomIndex(dChoices)); + sa.setTargetCard(c); + } + } + + return randomReturn; + } + + public static void tapResolve(final AbilityFactory af, final SpellAbility sa){ + HashMap params = af.getMapParams(); + Card card = sa.getSourceCard(); + + Card target = sa.getTargetCard(); + + if (af.getAbTgt() == null) + card.tap(); + else if(AllZone.GameAction.isCardInPlay(target) && CardFactoryUtil.canTarget(card, target)) + target.tap(); + else // Fizzle? + return; + + String DrawBack = params.get("SubAbility"); + if (af.hasSubAbility()) + CardFactoryUtil.doDrawBack(DrawBack, 0, card.getController(), card.getController().getOpponent(), card.getController(), card, null, sa); + + } + + // Untap All/Tap All + + //Phasing? Something else? Who knows! } diff --git a/src/forge/CardFactory.java b/src/forge/CardFactory.java index f4fa39e59ef..852a84d022f 100644 --- a/src/forge/CardFactory.java +++ b/src/forge/CardFactory.java @@ -1655,7 +1655,6 @@ public class CardFactory implements NewConstants { String k[] = parse.split(":"); String tmpCost[] = k[0].replace("abAllPump", "").split(" ", 2); - final Target abTgt = new Target(tmpCost[0]); final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true); final String Scope[] = k[1].split("/"); @@ -1739,7 +1738,7 @@ public class CardFactory implements NewConstants { } } - SpellAbility abAllPump = new Ability_Activated(card, abCost, abTgt) + SpellAbility abAllPump = new Ability_Activated(card, abCost, null) { private static final long serialVersionUID = 7783282947592874L; @@ -1921,7 +1920,13 @@ public class CardFactory implements NewConstants { final boolean bPumpEquipped = (tmpCost[0].equals("Equipped")); - final Target abTgt = new Target(tmpCost[0]); + final Target abTgt; + + if (tmpCost[0].equals("TgtC")) + abTgt = new Target(tmpCost[0]); + else + abTgt = null; + final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true); final int NumAttack[] = {-1138}; @@ -1985,7 +1990,7 @@ public class CardFactory implements NewConstants { String d = "none"; StringBuilder sbD = new StringBuilder(); - if(abTgt.doesTarget()) + if(abTgt != null && abTgt.doesTarget()) sbD.append("Target creature"); else if (bPumpEquipped) sbD.append("Equipped creature"); @@ -2111,7 +2116,7 @@ public class CardFactory implements NewConstants { if(AllZone.Phase.getPhase().equals(Constant.Phase.Main2)) return false; - if(!abTgt.doesTarget()) { + if(abTgt == null) { Card creature; if (bPumpEquipped) creature = card.getEquippingCard(); @@ -2183,7 +2188,7 @@ public class CardFactory implements NewConstants { @Override public void resolve() { final Card[] creature = new Card[1]; - if(abTgt.doesTarget()) + if(abTgt != null && abTgt.doesTarget()) creature[0] = getTargetCard(); else if (bPumpEquipped) creature[0] = card.getEquippingCard(); @@ -2191,7 +2196,7 @@ public class CardFactory implements NewConstants { creature[0] = card; if(creature[0] != null && AllZone.GameAction.isCardInPlay(creature[0]) - && (!abTgt.doesTarget() || CardFactoryUtil.canTarget(card, getTargetCard()))) { + && (abTgt == null || CardFactoryUtil.canTarget(card, getTargetCard()))) { final int a = getNumAttack(); final int d = getNumDefense(); @@ -2237,9 +2242,6 @@ public class CardFactory implements NewConstants { ability.setDescription(spDesc[0]); ability.setStackDescription(stDesc[0]); - - if(!abTgt.doesTarget()) - ability.setTargetCard(card); card.addSpellAbility(ability); } @@ -2685,14 +2687,15 @@ public class CardFactory implements NewConstants { int drawBack = 2; - final Target abTgt = new Target(tmpCost[0]); - if (abTgt.canTgtValid()){ + // TODO: These can do for some converting for an improved message box + final Target abTgt; + if (tmpCost[0].contains("TgtV")){ int valid = drawBack; - // Looks like VTSelection is used for the Message box, should improve the message - abTgt.setVTSelection("Select a target: " + k[valid]); - abTgt.setValidTgts(k[valid].split(",")); + abTgt = new Target("Select a target: " + k[valid], k[valid].split(",")); drawBack++; } + else + abTgt = new Target(tmpCost[0]); final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true); @@ -2728,7 +2731,7 @@ public class CardFactory implements NewConstants { sb.append(card.getName()); sb.append(" deals " + NumDmg[0] + " damage to "); - sb.append(abTgt.targetString()); + sb.append(abTgt.getVTSelection()); spDesc[0] = sb.toString(); stDesc[0] = card.getName() + " -" + sb.toString(); } @@ -2818,7 +2821,7 @@ public class CardFactory implements NewConstants { if(r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed())) rr = true; - if(abTgt.canTgtCreaturePlayer()) { + if(abTgt.canTgtCreatureAndPlayer()) { if(shouldTgtP()) { setTargetPlayer(AllZone.HumanPlayer); return rr; @@ -3041,9 +3044,7 @@ public class CardFactory implements NewConstants { String tmpCost = k[0].substring(13); final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true); - final Target tgtDstryTgt = new Target("TgtV"); final String Tgts[] = k[1].split(","); - tgtDstryTgt.setValidTgts(Tgts); final boolean NoRegen[] = {false}; final String Drawback[] = {"none"}; @@ -3074,8 +3075,9 @@ public class CardFactory implements NewConstants { String tmpDesc = spDesc[0].substring(15); int i = tmpDesc.indexOf("."); tmpDesc = tmpDesc.substring(0, i); - //final String Selec = "Select target " + tmpDesc + " to destroy."; - tgtDstryTgt.setVTSelection("Select target " + tmpDesc + " to destroy."); + String Selec = "Select target " + tmpDesc + " to destroy."; + + final Target tgtDstryTgt = new Target(Selec, Tgts); spDesc[0] = abCost.toString() + spDesc[0]; @@ -4563,10 +4565,7 @@ public class CardFactory implements NewConstants { if (tmpCost[0].equals("")) abTgt = null; else{ - //abTgt = new Target(tmpCost[0]); - //abTgt.setValidTgts("player".split(",")); - //abTgt.setVTSelection("Target a player to draw cards"); - abTgt = new Target("TgtP"); + abTgt = new Target("Target a player to draw cards", "player".split(",")); } final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true); @@ -4952,9 +4951,7 @@ public class CardFactory implements NewConstants { if (tmpCost[0].equals("")) abTgt = null; else{ - abTgt = new Target(tmpCost[0]+"V"); - abTgt.setValidTgts("player".split(",")); - abTgt.setVTSelection("Target a player to lose life"); + abTgt = new Target("Target a player to lose life", "player".split(",")); } final Ability_Cost abCost = new Ability_Cost(tmpCost[1], card.getName(), true); @@ -5241,9 +5238,7 @@ public class CardFactory implements NewConstants { if (tmpCost[0].equals("")) abTgt = null; else{ - abTgt = new Target(tmpCost[0]); - abTgt.setValidTgts(k[1].split(",")); - abTgt.setVTSelection("Target a player to gain life"); + abTgt = new Target("Target a player to gain life", k[1].split(",")); inc++; } @@ -6362,17 +6357,20 @@ public class CardFactory implements NewConstants { String tmpCost = k[0].substring(8); final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true); - final Target tapTargets = new Target("TgtV"); final String Tgts[] = k[1].split(","); - tapTargets.setValidTgts(Tgts); + final String abDesc[] = {"none"}; abDesc[0] = k[2]; String tmpDesc = abDesc[0].substring(11); int i = tmpDesc.indexOf("."); tmpDesc = tmpDesc.substring(0, i); - tapTargets.setVTSelection("Select target " + tmpDesc + " to tap."); + StringBuilder vtDesc = new StringBuilder(); + vtDesc.append("Select target ").append(tmpDesc).append(" to tap."); + + final Target tapTargets = new Target(vtDesc.toString(), Tgts); + abDesc[0] = abCost.toString() + abDesc[0]; final SpellAbility AbTapTgt = new Ability_Activated(card, abCost, tapTargets) { @@ -6650,17 +6648,20 @@ public class CardFactory implements NewConstants { String tmpCost = k[0].substring(10); final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true); - final Target untapTargets = new Target("TgtV"); + final String Tgts[] = k[1].split(","); - untapTargets.setValidTgts(Tgts); final String abDesc[] = {"none"}; abDesc[0] = k[2]; String tmpDesc = abDesc[0].substring(13); int i = tmpDesc.indexOf("."); tmpDesc = tmpDesc.substring(0, i); - untapTargets.setVTSelection("Select target " + tmpDesc + " to untap."); + + StringBuilder vtDesc = new StringBuilder(); + vtDesc.append("Select target ").append(tmpDesc).append(" to untap."); + final Target untapTargets = new Target(vtDesc.toString(), Tgts); + abDesc[0] = abCost.toString() + abDesc[0]; final SpellAbility AbUntapTgt = new Ability_Activated(card, abCost, untapTargets) { @@ -6748,123 +6749,6 @@ public class CardFactory implements NewConstants { card.addSpellAbility(AbUntapTgt); }//End abUntapTgt - /* - * Generic tap target ___ spell - * - * syntax: spTapTgt:{Valid Targets}:{Description} - */ - if (hasKeyword(card, "spTapTgt") != -1) { - int n = hasKeyword(card, "spTapTgt"); - - String parse = card.getKeyword().get(n).toString(); - card.removeIntrinsicKeyword(parse); - - String k[] = parse.split(":"); - - final Target tapTargets = new Target("TgtV"); - final String Tgts[] = k[1].split(","); - tapTargets.setValidTgts(Tgts); - final String spDesc[] = {"none"}; - spDesc[0] = k[2]; - - String tmpDesc = spDesc[0].substring(11); - int i = tmpDesc.indexOf("."); - tmpDesc = tmpDesc.substring(0, i); - String Selec = "Select target " + tmpDesc + " to tap."; - - card.clearSpellAbility(); - - final SpellAbility SpTapTgt = new Spell(card) { - private static final long serialVersionUID = 6956356114247328396L; - - @Override - public boolean canPlayAI() { - CardList hCards = getTargets(); - - Random r = new Random(); - boolean rr = false; - if (r.nextFloat() <= .6667) - rr = true; - - if(hCards.size() > 0) { - Card c = null; - CardList dChoices = new CardList(); - - for(int i = 0; i < Tgts.length; i++) { - if (Tgts[i].startsWith("Creature")) { - c = CardFactoryUtil.AI_getBestCreature(hCards); - if (c != null) - dChoices.add(c); - } - - CardListUtil.sortByTextLen(hCards); - dChoices.add(hCards.get(0)); - - CardListUtil.sortCMC(hCards); - dChoices.add(hCards.get(0)); - } - - c = dChoices.get(CardUtil.getRandomIndex(dChoices)); - setTargetCard(c); - - return rr; - } - - return false; - } - - CardList getTargets() { - CardList tmpList = AllZoneUtil.getPlayerCardsInPlay(AllZone.HumanPlayer); - tmpList = tmpList.getValidCards(Tgts, card.getController()); - tmpList = tmpList.getTargetableCards(card); - tmpList = tmpList.filter(AllZoneUtil.untapped); - return tmpList; - } - - /* - @Override - public boolean canPlay() { - return (CardFactoryUtil.canUseAbility(card) && super.canPlay()); - } - */ - - @Override - public void resolve() { - Card tgtC = getTargetCard(); - if(AllZone.GameAction.isCardInPlay(tgtC) - && CardFactoryUtil.canTarget(card, tgtC)) { - tgtC.tap(); - } - } - }; //SpTapTgt - - Input InGetTarget = CardFactoryUtil.input_targetValid(SpTapTgt, Tgts, Selec); - - SpTapTgt.setBeforePayMana(InGetTarget); - - SpTapTgt.setDescription(spDesc[0]); - - card.addSpellAbility(SpTapTgt); - card.setSVar("PlayMain1", "TRUE"); - - String bbCost = card.getSVar("Buyback"); - if (!bbCost.equals("")) - { - SpellAbility bbDstryTgt = SpTapTgt.copy(); - bbDstryTgt.setManaCost(CardUtil.addManaCosts(card.getManaCost(), bbCost)); - - StringBuilder sb = new StringBuilder(); - sb.append("Buyback ").append(bbCost).append(" (You may pay an additional ").append(bbCost); - sb.append(" as you cast this spell. If you do, put this card into your hand as it resolves.)"); - bbDstryTgt.setDescription(sb.toString()); - // bbDstryTgt.setDescription("Buyback " + bbCost + "(You may pay an additional " + bbCost + " as you cast this spell. If you do, put this card into your hand as it resolves.)"); - bbDstryTgt.setIsBuyBackAbility(true); - - bbDstryTgt.setBeforePayMana(CardFactoryUtil.input_targetValid(bbDstryTgt, Tgts, Selec)); - - card.addSpellAbility(bbDstryTgt); - } - }//End spTapTgt /* * Generic untap all targets spell @@ -6879,11 +6763,10 @@ public class CardFactory implements NewConstants { String k[] = parse.split(":"); - final Target untapTargets = new Target("TgtV"); - + String Targets = k[1]; final String Tgts[] = Targets.split(","); - untapTargets.setValidTgts(Tgts); + final String spDesc[] = {"none"}; final String stackDesc[] = {"none"}; stackDesc[0] = k[2]; @@ -6965,98 +6848,6 @@ public class CardFactory implements NewConstants { card.setSVar("PlayMain1", "TRUE"); }//End spUntapAll keyword - /* - * Generic untap target ___ spell - * - * syntax: spUntapTgt:{Valid Targets}:{Description} - */ - if (hasKeyword(card, "spUntapTgt") != -1) { - int n = hasKeyword(card, "spUntapTgt"); - - String parse = card.getKeyword().get(n).toString(); - card.removeIntrinsicKeyword(parse); - - String k[] = parse.split(":"); - - final Target untapTargets = new Target("TgtV"); - final String Tgts[] = k[1].split(","); - untapTargets.setValidTgts(Tgts); - final String spDesc[] = {"none"}; - spDesc[0] = k[2]; - - String tmpDesc = spDesc[0].substring(13); - int i = tmpDesc.indexOf("."); - tmpDesc = tmpDesc.substring(0, i); - String Selec = "Select target " + tmpDesc + " to untap."; - - final SpellAbility SpUntapTgt = new Spell(card) { - private static final long serialVersionUID = 1740994300027185986L; - - @Override - public boolean canPlayAI() { - /*CardList hCards = getTargets(); - - Random r = new Random(); - boolean rr = false; - if (r.nextFloat() <= .6667) - rr = true; - - if(hCards.size() > 0) { - Card c = null; - CardList dChoices = new CardList(); - - for(int i = 0; i < Tgts.length; i++) { - if (Tgts[i].startsWith("Creature")) { - c = CardFactoryUtil.AI_getBestCreature(hCards); - if (c != null) - dChoices.add(c); - } - - CardListUtil.sortByTextLen(hCards); - dChoices.add(hCards.get(0)); - - CardListUtil.sortCMC(hCards); - dChoices.add(hCards.get(0)); - } - - c = dChoices.get(CardUtil.getRandomIndex(dChoices)); - setTargetCard(c); - - return rr; - } - */ - return false; - } - - /* - CardList getTargets() { - CardList tmpList = AllZoneUtil.getPlayerCardsInPlay(AllZone.HumanPlayer); - tmpList = tmpList.getValidCards(Tgts); - tmpList = tmpList.getTargetableCards(card); - tmpList = tmpList.filter(AllZoneUtil.untapped); - return tmpList; - }*/ - - @Override - public void resolve() { - Card tgtC = getTargetCard(); - if(AllZone.GameAction.isCardInPlay(tgtC) - && CardFactoryUtil.canTarget(card, tgtC)) { - tgtC.untap(); - } - } - }; //SpUntapTgt - - card.clearSpellAbility(); - Input InGetTarget = CardFactoryUtil.input_targetValid(SpUntapTgt, Tgts, Selec); - - SpUntapTgt.setBeforePayMana(InGetTarget); - - SpUntapTgt.setDescription(spDesc[0]); - card.addSpellAbility(SpUntapTgt); - card.setSVar("PlayMain1", "TRUE"); - }//End spUntapTgt - if (hasKeyword(card, "Flashback") != -1) { int n = hasKeyword(card, "Flashback"); if (n != -1) { @@ -8601,7 +8392,7 @@ public class CardFactory implements NewConstants { else if(cardName.equals("AEther Spellbomb")) { Ability_Cost abCost = new Ability_Cost("U Sac<1/CARDNAME>", cardName, true); String[] valid = {"Creature"}; - Target abTgt = new Target("TgtV", "Target a creature to bounce", valid); + Target abTgt = new Target("Target a creature to bounce", valid); final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt) { private static final long serialVersionUID = 1L; @@ -8643,7 +8434,7 @@ public class CardFactory implements NewConstants { else if(cardName.equals("Lifespark Spellbomb")) { Ability_Cost abCost = new Ability_Cost("G Sac<1/CARDNAME>", cardName, true); String[] valid = {"Land"}; - Target abTgt = new Target("TgtV", "Target a land to animate", valid); + Target abTgt = new Target("Target a land to animate", valid); final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt) { private static final long serialVersionUID = -5744842090293912606L; @@ -8711,7 +8502,7 @@ public class CardFactory implements NewConstants { else if(cardName.equals("Necrogen Spellbomb")) { Ability_Cost abCost = new Ability_Cost("B Sac<1/CARDNAME>", cardName, true); String[] valid = {"player"}; - Target abTgt = new Target("TgtV","Target player discards a card", valid); + Target abTgt = new Target("Target player discards a card", valid); final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt) { private static final long serialVersionUID = -5712428914792877529L; @@ -9041,7 +8832,7 @@ public class CardFactory implements NewConstants { else if(cardName.equals("Volrath's Dungeon")) { Ability_Cost dungeonCost = new Ability_Cost("Discard<1/Any>", cardName, true); - Target dungeonTgt = new Target("TgtV", "Volrath's Dungeon - Target player" , "player".split(",")); + Target dungeonTgt = new Target("Volrath's Dungeon - Target player" , "player".split(",")); final SpellAbility dungeon = new Ability_Activated(card, dungeonCost, dungeonTgt){ private static final long serialVersionUID = 334033015590321821L; @@ -9649,7 +9440,7 @@ public class CardFactory implements NewConstants { final String[] Tgts = { "Creature.nonArtifact" }; Ability_Cost abCost = new Ability_Cost("T Sac<1/CARDNAME>", cardName, true); - Target abTgt = new Target("TgtV", "Target a non-Artifact Creature to Transmogrify", Tgts); + Target abTgt = new Target("Target a non-Artifact Creature to Transmogrify", Tgts); final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt){ private static final long serialVersionUID = -401631574059431293L; @@ -11658,10 +11449,8 @@ public class CardFactory implements NewConstants { //*************** START *********** START ************************** else if(cardName.equals("Barl's Cage")) { - Target target = new Target("TgtV"); - target.setVTSelection("Select target creature."); final String Tgts[] = {"Creature"}; - target.setValidTgts(Tgts); + Target target= new Target("Select target creature.", Tgts, 1, 1); final Ability_Cost cost = new Ability_Cost("3", card.getName(), true); diff --git a/src/forge/CardFactoryUtil.java b/src/forge/CardFactoryUtil.java index f30da5dbdd6..cd959abf247 100644 --- a/src/forge/CardFactoryUtil.java +++ b/src/forge/CardFactoryUtil.java @@ -3394,9 +3394,7 @@ public class CardFactoryUtil { Target tgt = ability.getTarget(); if (tgt != null){ // Reconfirm the Validity of a TgtValid, or if the Creature is still a Creature - if (tgt.canTgtValid() && !target.isValidCard(tgt.getValidTgts(), ability.getActivatingPlayer())) - return false; - else if (tgt.canTgtCreature() && !target.isCreature()) + if (tgt.doesTarget() && !target.isValidCard(tgt.getValidTgts(), ability.getActivatingPlayer(), ability.getSourceCard())) return false; // Check if the target is in the zone it needs to be in to be targeted diff --git a/src/forge/CardFactory_Auras.java b/src/forge/CardFactory_Auras.java index 7980150266b..7be73d4aae9 100644 --- a/src/forge/CardFactory_Auras.java +++ b/src/forge/CardFactory_Auras.java @@ -1556,7 +1556,7 @@ class CardFactory_Auras { };//addSpellAbility // Target AbCost and Restriction are set here to get this working as expected - Target tgt = new Target("TgtV", "Select a creature in a graveyard", "Creature".split(",")); + Target tgt = new Target("Select a creature in a graveyard", "Creature".split(",")); tgt.setZone(Constant.Zone.Graveyard); animate.setTarget(tgt); diff --git a/src/forge/CardFactory_Creatures.java b/src/forge/CardFactory_Creatures.java index 0703961505d..e954b2c2b23 100644 --- a/src/forge/CardFactory_Creatures.java +++ b/src/forge/CardFactory_Creatures.java @@ -13910,7 +13910,7 @@ public class CardFactory_Creatures { else if(cardName.equals("Tradewind Rider")) { String select = "Select target permanent to return to owner's hand."; final String Tgts[] = {"Permanent"}; - Target target = new Target("TgtV", select, Tgts); + Target target = new Target(select, Tgts); final Ability_Cost cost = new Ability_Cost("T tapXType<2/Creature>", card.getName(), true); @@ -20416,7 +20416,7 @@ public class CardFactory_Creatures { //*************** START *********** START ************************** else if(cardName.equals("Singing Tree")) { final String Tgts[] = {"Creature.attacking"}; - Target target = new Target("TgtV", "Select target attacking creature.", Tgts); + Target target = new Target("Select target attacking creature.", Tgts); final Ability_Cost cost = new Ability_Cost("T", card.getName(), true); @@ -20657,7 +20657,7 @@ public class CardFactory_Creatures { //*************** START *********** START ************************** else if(cardName.equals("Witch Hunter")) { final String Tgts[] = {"Creature+YouDontCtrl"}; - Target target = new Target("TgtV", "Select target creature you don't control.", Tgts); + Target target = new Target("Select target creature you don't control.", Tgts); final Ability_Cost abCost = new Ability_Cost("1 W W T", card.getName(), true); final SpellAbility ability = new Ability_Activated(card, abCost, target) { diff --git a/src/forge/Target.java b/src/forge/Target.java index 5d411087d42..d4b0e0dffb9 100644 --- a/src/forge/Target.java +++ b/src/forge/Target.java @@ -1,115 +1,101 @@ package forge; -public class Target { - private boolean tgtPlayer = false; - public boolean canTgtPlayer() { return tgtPlayer; } - private boolean tgtCreature = false; - public boolean canTgtCreature() { return tgtCreature; } - - public boolean canTgtCreaturePlayer() { return tgtCreature && tgtPlayer; } - public boolean doesTarget() { return tgtCreature || tgtPlayer || tgtValid; } - +public class Target { private boolean tgtValid = false; private String ValidTgts[]; private String vtSelection = ""; - public boolean canTgtValid() { return tgtValid; } + + public boolean doesTarget() { return tgtValid; } public String[] getValidTgts() { return ValidTgts; } - public void setValidTgts(String vTgts[]) { ValidTgts = vTgts; } public String getVTSelection() { return vtSelection; } - public void setVTSelection(String vtSelStr) { vtSelection = vtSelStr; } + + private int minTargets = 1; + public int getMinTargets() { return minTargets; } + private int maxTargets = 1; + public int getMaxTargets() { return maxTargets; } private String tgtZone = Constant.Zone.Play; public void setZone(String tZone) { tgtZone = tZone; } public String getZone() { return tgtZone; } - private int minTargets = 0; - public int getMinTargets() { return minTargets; } - private int maxTargets = 0; - public int getMaxTargets() { return maxTargets; } // add array of targets here? - + private int numTargeted = 0; public int getNumTargeted() { return numTargeted; } public void incrementTargets() { numTargeted++; } public void resetTargets() { numTargeted = 0; } public Target(String parse){ - if (parse.contains("Tgt")){ - // Tgt{C}{P}[//] min-max is optional - String tgtStr = parse.replace("Tgt", ""); - String[] tgtSplit = tgtStr.split("/"); - - if (tgtSplit[0].contains("C")) // creature - tgtCreature = true; - if (tgtSplit[0].contains("P")) // player - tgtPlayer = true; - if (tgtSplit[0].contains("V")) // valid - tgtValid = true; - - if (tgtSplit.length != 3){ - minTargets = 1; - maxTargets = 1; - } - else{ - minTargets = Integer.parseInt(tgtSplit[1]); - maxTargets = Integer.parseInt(tgtSplit[2]); - } - } - } - - public Target(String parse, String select, String[] valid){ - if (parse.contains("Tgt")){ - // Tgt{C}{P}{V}[//] min-max is optional - String tgtStr = parse.replace("Tgt", ""); - String[] tgtSplit = tgtStr.split("/"); - - if (tgtSplit[0].contains("C")) // creature - tgtCreature = true; - if (tgtSplit[0].contains("P")) // player - tgtPlayer = true; - if (tgtSplit[0].contains("V")) // valid - tgtValid = true; - - if (tgtSplit.length != 3){ - minTargets = 1; - maxTargets = 1; - } - else{ - minTargets = Integer.parseInt(tgtSplit[1]); - maxTargets = Integer.parseInt(tgtSplit[2]); - } - - if (tgtValid){ - vtSelection = select; - ValidTgts = valid; - } - } + this(parse, 1, 1); } public Target(String parse, int min, int max){ - minTargets = min; - maxTargets = max; + // parse=Tgt{C}{P} - Primarily used for Pump or Damage + // C = Creature P=Player/Planeswalker + // CP = All three tgtValid = true; - ValidTgts = parse.split(","); + + if (parse.contains("Tgt")){ + parse = parse.replace("Tgt", ""); + } + + String valid; + String prompt; + + if (parse.equals("CP")){ + valid = "Creature,Planeswalker,Player"; + prompt = "Select target creature, planeswalker, or player"; + } + else if (parse.equals("C")){ + valid = "Creature"; + prompt = "Select target creature"; + } + else if (parse.equals("P")){ + valid = "Planeswalker,Player"; + prompt = "Select target planeswalker or player"; + } + else{ + System.out.println("Bad Parsing in Target(parse, min, max)"); + return; + } + + vtSelection = prompt; + ValidTgts = valid.split(","); + + minTargets = min; + maxTargets = max; } - public String targetString() - { - StringBuilder sb = new StringBuilder("target "); - - if (tgtCreature) - sb.append("creature"); - if (tgtPlayer){ - if (tgtCreature) - sb.append(" or "); - sb.append("player"); - } - if (tgtValid){ - sb.append(vtSelection); - } - sb.append("."); - - return sb.toString(); + public Target(String select, String[] valid){ + this(select, valid, 1, 1); } + + public Target(String select, String[] valid, int min, int max){ + tgtValid = true; + vtSelection = select; + ValidTgts = valid; + + minTargets = min; + maxTargets = max; + } + + // These below functions are quite limited to the damage classes, we should find a way to move them into AF_DealDamage + public boolean canTgtPlayer() { + for(String s: ValidTgts){ + if (s.equals("Player")) + return true; + } + return false; + } + + public boolean canTgtCreature() { + for(String s: ValidTgts){ + if (s.contains("Creature") && !s.contains("nonCreature")) + return true; + } + return false; + } + + public boolean canTgtCreatureAndPlayer() { return canTgtPlayer() && canTgtCreature(); } } diff --git a/src/forge/Target_Selection.java b/src/forge/Target_Selection.java index 95baee201dd..5a9e7bc8d48 100644 --- a/src/forge/Target_Selection.java +++ b/src/forge/Target_Selection.java @@ -52,150 +52,15 @@ public class Target_Selection { } // if we haven't reached minimum targets, or we're still less than Max targets keep choosing - // targeting, with forward code for multiple target abilities + // targeting, with forward code for multiple target abilities if (!bDoneTarget && target.getMinTargets() > 0 && target.getNumTargeted() < target.getMaxTargets()){ - if (target.canTgtCreature() && target.canTgtPlayer()) - changeInput.stopSetNext(targetCreaturePlayer(ability, Command.Blank, true, this, req)); - else if(target.canTgtCreature()) - changeInput.stopSetNext(targetCreature(ability, this, req)); - else if(target.canTgtPlayer()) - changeInput.stopSetNext(targetPlayer(ability, this, req)); - else if (target.canTgtValid()) - changeInput.stopSetNext(input_targetValid(ability, target.getValidTgts(), target.getVTSelection(), this, req)); + changeInput.stopSetNext(input_targetValid(ability, target.getValidTgts(), target.getVTSelection(), this, req)); return false; } return true; } - - public static Input targetCreaturePlayer(final SpellAbility ability, final Command paid, final boolean targeted, - final Target_Selection select, final SpellAbility_Requirements req) { - Input target = new Input() { - private static final long serialVersionUID = 2781418414287281005L; - - @Override - public void showMessage() { - AllZone.Display.showMessage("Select target Creature, Player, or Planeswalker"); - // when multi targets (Arc Mage) are added, need this: - // if payment.targeted < mintarget only enable cancel - // else if payment.targeted < maxtarget enable cancel and ok - ButtonUtil.enableOnlyCancel(); - } - - @Override - public void selectButtonCancel() { - select.setCancel(true); - stop(); - req.finishedTargeting(); - } - - @Override - public void selectButtonOK() { - select.setDoneTarget(true); - stop(); - req.finishedTargeting(); - } - - @Override - public void selectCard(Card card, PlayerZone zone) { - if((card.isCreature() || card.isPlaneswalker()) && zone.is(Constant.Zone.Play) - && (!targeted || CardFactoryUtil.canTarget(ability, card))) { - ability.setTargetCard(card); - done(); - } - }//selectCard() - - @Override - public void selectPlayer(Player player) { - ability.setTargetPlayer(player); - // if multitarget increment then select again - done(); - } - - void done() { - select.incrementTargets(); - paid.execute(); - stop(); - req.finishedTargeting(); - } - }; - return target; - }//input_targetCreaturePlayer() - - public static Input targetCreature(final SpellAbility ability, final Target_Selection select, final SpellAbility_Requirements req) { - Input target = new Input() { - private static final long serialVersionUID = 2781418414287281005L; - - @Override - public void showMessage() { - AllZone.Display.showMessage("Select target Creature"); - ButtonUtil.enableOnlyCancel(); - } - - @Override - public void selectButtonCancel() { - select.setCancel(true); - stop(); - req.finishedTargeting(); - } - - @Override - public void selectCard(Card card, PlayerZone zone) { - if(card.isCreature() && zone.is(Constant.Zone.Play) && (CardFactoryUtil.canTarget(ability, card))) { - ability.setTargetCard(card); - done(); - } - }//selectCard() - - void done() { - select.incrementTargets(); - stop(); - req.finishedTargeting(); - } - }; - return target; - }//targetCreature() - - public static Input targetPlayer(final SpellAbility ability, final Target_Selection select, final SpellAbility_Requirements req) { - Input target = new Input() { - private static final long serialVersionUID = 2781418414287281005L; - - @Override - public void showMessage() { - AllZone.Display.showMessage("Select target Player or Planeswalker"); - ButtonUtil.enableOnlyCancel(); - } - - @Override - public void selectButtonCancel() { - select.setCancel(true); - stop(); - req.finishedTargeting(); - } - - @Override - public void selectCard(Card card, PlayerZone zone) { - if(card.isPlaneswalker() && zone.is(Constant.Zone.Play) && (!CardFactoryUtil.canTarget(ability, card))) { - ability.setTargetCard(card); - done(); - } - }//selectCard() - - @Override - public void selectPlayer(Player player) { - ability.setTargetPlayer(player); - done(); - } - - void done() { - select.incrementTargets(); - stop(); - req.finishedTargeting(); - } - }; - return target; - }//targetPlayer() - + // these have been copied over from CardFactoryUtil as they need two extra parameters for target selection. // however, due to the changes necessary for SA_Requirements this is much different than the original public static Input input_targetValid(final SpellAbility sa, final String[] Tgts, final String message, @@ -213,7 +78,7 @@ public class Target_Selection { if (zone.equals(Constant.Zone.Play)){ boolean canTargetPlayer = false; for(String s : Tgts) - if (s.equals("player")) + if (s.equals("player") || s.equals("Player")) canTargetPlayer = true; stopSetNext(input_targetSpecific(sa, choices, message, true, canTargetPlayer, select, req));