From f75305e581ee717e50f7da6b2d1e448624f87d92 Mon Sep 17 00:00:00 2001 From: jendave Date: Sat, 6 Aug 2011 13:02:38 +0000 Subject: [PATCH] - AF_Damage can now handle Defined$ Parameters. - Updated Psionic Entity, Orcish Cannonade, and Breath of Malfegor --- res/cardsfolder/breath_of_malfegor.txt | 2 +- res/cardsfolder/orcish_cannonade.txt | 2 +- res/cardsfolder/psionic_entity.txt | 2 +- src/forge/AbilityFactory.java | 65 +++++- src/forge/AbilityFactory_DealDamage.java | 265 ++++++++++------------- 5 files changed, 174 insertions(+), 162 deletions(-) diff --git a/res/cardsfolder/breath_of_malfegor.txt b/res/cardsfolder/breath_of_malfegor.txt index 6aebd1df252..14e8f600fe4 100644 --- a/res/cardsfolder/breath_of_malfegor.txt +++ b/res/cardsfolder/breath_of_malfegor.txt @@ -2,7 +2,7 @@ Name:Breath of Malfegor ManaCost:3 B R Types:Instant Text:no text -K:spDamageTgtP:5 +A:SP$DealDamage | Cost$ 3 B R | Defined$ Opponent | NumDmg$ 5 | SpellDescription$ Breath of Malfegor deals 5 damage to each opponent. SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/breath_of_malfegor.jpg SetInfo:ARB|Common|http://magiccards.info/scans/en/arb/35.jpg diff --git a/res/cardsfolder/orcish_cannonade.txt b/res/cardsfolder/orcish_cannonade.txt index d351cd77d24..5a2c2b28ddc 100644 --- a/res/cardsfolder/orcish_cannonade.txt +++ b/res/cardsfolder/orcish_cannonade.txt @@ -3,7 +3,7 @@ ManaCost:1 R R Types:Instant Text:no text A:SP$DealDamage | Cost$ 1 R R | Tgt$ CP | NumDmg$2 | SubAbility$SVar=DB1 | SpellDescription$ Orcish Cannonade deals 2 damage to target creature or player and 3 damage to you. Draw a card. -SVar:DB1:DB$DealDamage | NumDmg$ 3 | Affected$ You | SubAbility$SVar=DB2 +SVar:DB1:DB$DealDamage | NumDmg$ 3 | Defined$ You | SubAbility$SVar=DB2 SVar:DB2:DB$Draw | NumCards$ 1 SVar:Rarity:Common SVar:Picture:http://www.wizards.com/global/images/magic/general/orcish_cannonade.jpg diff --git a/res/cardsfolder/psionic_entity.txt b/res/cardsfolder/psionic_entity.txt index 07fa5e37c3e..6df1a993e04 100644 --- a/res/cardsfolder/psionic_entity.txt +++ b/res/cardsfolder/psionic_entity.txt @@ -4,7 +4,7 @@ Types:Creature Illusion Text:no text PT:2/2 A:AB$DealDamage | Cost$ T | Tgt$ CP | NumDmg$2 | SubAbility$SVar=DB1 | SpellDescription$ Psionic Entity deals 2 damage to target creature or player and 3 damage to itself. -SVar:DB1:DB$DealDamage | NumDmg$ 3 | Affected$ Self +SVar:DB1:DB$DealDamage | NumDmg$ 3 | Defined$ Self SVar:Rarity:Rare SVar:Picture:http://www.wizards.com/global/images/magic/general/psionic_entity.jpg SetInfo:4ED|Rare|http://magiccards.info/scans/en/4e/95.jpg diff --git a/src/forge/AbilityFactory.java b/src/forge/AbilityFactory.java index 8ff7b0894b4..19c2c77026b 100644 --- a/src/forge/AbilityFactory.java +++ b/src/forge/AbilityFactory.java @@ -534,13 +534,17 @@ public class AbilityFactory { return Integer.parseInt(amount) * multiplier; } + // should the three getDefined functions be merged into one? Or better to have separate? + // If we only have one, each function needs to Cast the Object to the appropriate type when using + // But then we only need update one function at a time once the casting is everywhere. + // Probably will move to One function solution sometime in the future public static ArrayList getDefinedCards(Card hostCard, String def, SpellAbility sa){ ArrayList cards = new ArrayList(); - String defined = (def == null) ? "Self" : def; + String defined = (def == null) ? "Self" : def; // default to Self Card c = null; - if (defined == null || defined.equals("Self")) // default to Self + if (defined.equals("Self")) c = hostCard; else if (defined.equals("Equipped")) @@ -563,7 +567,7 @@ public class AbilityFactory { public static ArrayList getDefinedPlayers(Card card, String def, SpellAbility sa){ ArrayList players = new ArrayList(); - String defined = (def == null) ? "Self" : def; + String defined = (def == null) ? "You" : def; players = new ArrayList(); if (defined.equals("Targeted")){ @@ -575,30 +579,67 @@ public class AbilityFactory { players.addAll(parent.getTarget().getTargetPlayers()); } else{ - if (defined.equals("Self") || defined.equals("Each")) + if (defined.equals("You") || defined.equals("Each")) players.add(sa.getActivatingPlayer()); - if (defined.equals("Each")) + + if (defined.equals("Opponent") || defined.equals("Each")) players.add(sa.getActivatingPlayer().getOpponent()); } return players; } - public static SpellAbility findRootAbility(SpellAbility sa){ - if (!(sa instanceof Ability_Sub)) - return sa; + public static ArrayList getDefinedObjects(Card card, String def, SpellAbility sa){ + ArrayList objects = new ArrayList(); + String defined = (def == null) ? "Self" : def; + objects = new ArrayList(); + if (defined.equals("Targeted")){ + SpellAbility parent; + do{ + parent = ((Ability_Sub)sa).getParent(); + }while(parent.getTarget() == null && parent.getTarget().getTargets().size() == 0); + + objects.addAll(parent.getTarget().getTargets()); + } + else{ + // Player checks + if (defined.equals("You") || defined.equals("Each")) + objects.add(sa.getActivatingPlayer()); + + if (defined.equals("Opponent") || defined.equals("Each")) + objects.add(sa.getActivatingPlayer().getOpponent()); + + // Card checks + Card c = null; + + if (defined.equals("Self")) + c = card; + + if (defined.equals("Equipped")) + c = card.getEquippingCard(); + + if (defined.equals("Enchanted")) + c = card.getEnchantingCard(); + + if (c != null) + objects.add(c); + } + return objects; + } + + + public static SpellAbility findRootAbility(SpellAbility sa){ SpellAbility parent = sa; - do{ + while (parent instanceof Ability_Sub) parent = ((Ability_Sub)parent).getParent(); - }while(parent instanceof Ability_Sub); return parent; } public static SpellAbility findParentsTargetedCard(SpellAbility sa){ - SpellAbility parent; + SpellAbility parent = sa; do{ - parent = ((Ability_Sub)sa).getParent(); + parent = ((Ability_Sub)parent).getParent(); }while(parent.getTarget() == null && parent.getTarget().getTargetCards().size() == 0); return parent; diff --git a/src/forge/AbilityFactory_DealDamage.java b/src/forge/AbilityFactory_DealDamage.java index bc0b64d2e95..6541c55b15b 100644 --- a/src/forge/AbilityFactory_DealDamage.java +++ b/src/forge/AbilityFactory_DealDamage.java @@ -19,74 +19,69 @@ import java.util.Random; // Note: TgtOpp should not be used, Please use ValidTgts$ Opponent instead } - public SpellAbility getAbility() - { - final SpellAbility abDamage = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) - { - private static final long serialVersionUID = -7560349014757367722L; - - @Override - public boolean canPlay(){ - return super.canPlay(); - } - - @Override - public boolean canPlayAI() { - return doCanPlayAI(this); - - } - - @Override - public String getStackDescription(){ - return damageStackDescription(AF, this); - } - - @Override - public void resolve() { - doResolve(this); - AF.getHostCard().setAbilityUsed(AF.getHostCard().getAbilityUsed() + 1); - - } - };//Ability_Activated - - return abDamage; - } - - public SpellAbility getSpell() - { - final SpellAbility spDealDamage = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) { - private static final long serialVersionUID = 7239608350643325111L; + public SpellAbility getAbility() { + final SpellAbility abDamage = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) { + private static final long serialVersionUID = -7560349014757367722L; - @Override - public boolean canPlay(){ - return super.canPlay(); - } - - @Override - public boolean canPlayAI() { - return doCanPlayAI(this); - - } - - @Override - public String getStackDescription(){ - return damageStackDescription(AF, this); - } - - @Override - public void resolve() { - doResolve(this); - - } + @Override + public boolean canPlay() { + return super.canPlay(); + } - - }; // Spell - - return spDealDamage; - } + @Override + public boolean canPlayAI() { + return doCanPlayAI(this); - public SpellAbility getDrawback() - { + } + + @Override + public String getStackDescription() { + return damageStackDescription(AF, this); + } + + @Override + public void resolve() { + doResolve(this); + AF.getHostCard().setAbilityUsed(AF.getHostCard().getAbilityUsed() + 1); + + } + };// Ability_Activated + + return abDamage; + } + + public SpellAbility getSpell() { + final SpellAbility spDealDamage = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) { + private static final long serialVersionUID = 7239608350643325111L; + + @Override + public boolean canPlay() { + return super.canPlay(); + } + + @Override + public boolean canPlayAI() { + return doCanPlayAI(this); + + } + + @Override + public String getStackDescription() { + return damageStackDescription(AF, this); + } + + @Override + public void resolve() { + doResolve(this); + + } + + }; // Spell + + return spDealDamage; + } + + public SpellAbility getDrawback() { final SpellAbility dbDealDamage = new Ability_Sub(AF.getHostCard(), AF.getAbTgt()) { private static final long serialVersionUID = 7239608350643325111L; @@ -119,7 +114,7 @@ import java.util.Random; int restDamage = d; if (!noPrevention) - restDamage = AllZone.HumanPlayer.staticDamagePrevention(restDamage,AF.getHostCard(),false); + restDamage = AllZone.HumanPlayer.staticDamagePrevention(restDamage, AF.getHostCard(), false); if (restDamage == 0) return false; @@ -157,11 +152,13 @@ import java.util.Random; return best; } - // Combo alert!! + // Combo alert!! Casting burn on your own Stuffy Dolls is a waste + /* PlayerZone compy = AllZone.getZone(Constant.Zone.Play, AllZone.ComputerPlayer); CardList cPlay = new CardList(compy.getCards()); if(cPlay.size() > 0) for(int i = 0; i < cPlay.size(); i++) if(cPlay.get(i).getName().equals("Stuffy Doll")) return cPlay.get(i); + */ return null; } @@ -191,6 +188,7 @@ import java.util.Random; // TODO handle proper calculation of X values based on Cost + // todo: this should only happen during Players EOT if(AF.getHostCard().equals("Stuffy Doll")) { return true; } @@ -220,17 +218,20 @@ import java.util.Random; boolean noPrevention = params.containsKey("NoPrevention"); - // AI handle multi-targeting? if (tgt == null){ - if (AF.getMapParams().containsKey("Affected")){ - String affected = AF.getMapParams().get("Affected"); - if (affected.equals("You")) - // todo: when should AI not use an SA like Psionic Blast? - ; - else if (affected.equals("Self")) - // todo: when should AI not use an SA like Orcish Artillery? - ; - } + // todo: Improve circumstances where the Defined Damage is unwanted + ArrayList objects = AbilityFactory.getDefinedObjects(saMe.getSourceCard(), params.get("Defined"), saMe); + + for(Object o : objects){ + if (o instanceof Card){ + //Card c = (Card)o; + } + else if (o instanceof Player){ + Player p = (Player)o; + if (p.isComputer() && dmg >= p.getLife()) // Damage from this spell will kill me + return false; + } + } return true; } @@ -282,33 +283,29 @@ import java.util.Random; private String damageStackDescription(AbilityFactory af, SpellAbility sa){ // when damageStackDescription is called, just build exactly what is happening StringBuilder sb = new StringBuilder(); - String name = af.getHostCard().getName(); + String name = af.getHostCard().toString(); int dmg = getNumDamage(sa); - ArrayList tgts = findTargets(sa); + ArrayList tgts; + if(sa.getTarget() == null) + tgts = AbilityFactory.getDefinedObjects(sa.getSourceCard(), af.getMapParams().get("Defined"), sa); + else + tgts = sa.getTarget().getTargets(); if (!(sa instanceof Ability_Sub)) sb.append(name).append(" - "); sb.append("Deals ").append(dmg).append(" damage to "); - if(tgts == null || tgts.size() == 0) { - sb.append("itself"); - } - else { - for(int i = 0; i < tgts.size(); i++){ - if (i != 0) - sb.append(" "); + + for(int i = 0; i < tgts.size(); i++){ + if (i != 0) + sb.append(" "); - Object o = tgts.get(0); - if (o instanceof Player){ - sb.append(((Player)o).getName()); - } - else{ - sb.append(((Card)o).getName()); - } + Object o = tgts.get(0); + if (o instanceof Card || o instanceof Player) + sb.append(o.toString()); + } - } - } sb.append(". "); if (sa.getSubAbility() != null){ @@ -317,24 +314,6 @@ import java.util.Random; return sb.toString(); } - - private ArrayList findTargets(SpellAbility saMe){ - Target tgt = AF.getAbTgt(); - ArrayList tgts; - if (tgt != null) - tgts = tgt.getTargets(); - else{ - tgts = new ArrayList(); - if (AF.getMapParams().containsKey("Affected")){ - String affected = AF.getMapParams().get("Affected"); - if (affected.equals("You")) - tgts.add(saMe.getActivatingPlayer()); - else if (affected.equals("Self")) - tgts.add(saMe.getSourceCard()); - } - } - return tgts; - } private void doResolve(SpellAbility saMe) { @@ -343,43 +322,35 @@ import java.util.Random; boolean noPrevention = params.containsKey("NoPrevention"); - ArrayList tgts = findTargets(saMe); + ArrayList tgts; + if(saMe.getTarget() == null) + tgts = AbilityFactory.getDefinedObjects(saMe.getSourceCard(), params.get("Defined"), saMe); + else + tgts = saMe.getTarget().getTargets(); + boolean targeted = (AF.getAbTgt() != null); - if (tgts == null || tgts.size() == 0){ - System.out.println("AF_DealDamage ("+AF.getHostCard()+") - No targets? Ok. Just making sure."); - //if no targets, damage goes to self (Card; i.e. Stuffy Doll) - Card c = saMe.getSourceCard(); - if(AllZone.GameAction.isCardInPlay(c)) { - if (noPrevention) - c.addDamageWithoutPrevention(dmg, AF.getHostCard()); - else - c.addDamage(dmg, AF.getHostCard()); - } - } - else { - for(Object o : tgts){ - if (o instanceof Card){ - Card c = (Card)o; - if(AllZone.GameAction.isCardInPlay(c) && (!targeted || CardFactoryUtil.canTarget(AF.getHostCard(), c))) { - if (noPrevention) - c.addDamageWithoutPrevention(dmg, AF.getHostCard()); - else - c.addDamage(dmg, AF.getHostCard()); - } + for(Object o : tgts){ + if (o instanceof Card){ + Card c = (Card)o; + if(AllZone.GameAction.isCardInPlay(c) && (!targeted || CardFactoryUtil.canTarget(AF.getHostCard(), c))) { + if (noPrevention) + c.addDamageWithoutPrevention(dmg, AF.getHostCard()); + else + c.addDamage(dmg, AF.getHostCard()); + } - } - else if (o instanceof Player){ - Player p = (Player) o; - if (!targeted || p.canTarget(AF.getHostCard())) { - if (noPrevention) - p.addDamageWithoutPrevention(dmg, AF.getHostCard()); - else - p.addDamage(dmg, AF.getHostCard()); - } - } - } - } + } + else if (o instanceof Player){ + Player p = (Player) o; + if (!targeted || p.canTarget(AF.getHostCard())) { + if (noPrevention) + p.addDamageWithoutPrevention(dmg, AF.getHostCard()); + else + p.addDamage(dmg, AF.getHostCard()); + } + } + } if (AF.hasSubAbility()){ Ability_Sub abSub = saMe.getSubAbility();