diff --git a/res/cardsfolder/m/master_of_the_wild_hunt.txt b/res/cardsfolder/m/master_of_the_wild_hunt.txt index 92623342b64..762c59c1b20 100644 --- a/res/cardsfolder/m/master_of_the_wild_hunt.txt +++ b/res/cardsfolder/m/master_of_the_wild_hunt.txt @@ -4,5 +4,12 @@ Types:Creature Human Shaman PT:3/3 T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your upkeep, put a 2/2 green Wolf creature token onto the battlefield. SVar:TrigToken:AB$Token | Cost$ 0 | TokenAmount$ 1 | TokenName$ Wolf | TokenTypes$ Creature,Wolf | TokenOwner$ You | TokenColors$ Green | TokenPower$ 2 | TokenToughness$ 2 +A:AB$ DealDamage | Cost$ T | SubAbility$ TapWolves | ValidTgts$ Creature | NumDmg$ 0 | AILogic$ WildHunt | SpellDescription$ Tap all untapped Wolf creatures you control. Each Wolf tapped this way deals damage equal to its power to target creature. That creature deals damage equal to its power divided as its controller chooses among any number of those Wolves. | StackDescription$ Tap all untapped Wolf creatures you control. Each Wolf tapped this way deals damage equal to its power to {c:Targeted}. That creature deals damage equal to its power divided as its controller chooses among any number of those Wolves. +SVar:TapWolves:DB$ TapAll | ValidCards$ Creature.Wolf+YouCtrl+untapped | RememberTapped$ True | SubAbility$ WildHuntDamage | StackDescription$ None +SVar:WildHuntDamage:DB$ RepeatEach | RepeatSubAbility$ WolfStrike | UseImprinted$ True | RepeatCards$ Card.IsRemembered | SubAbility$ HuntedDamage | StackDescription$ None +SVar:WolfStrike:DB$ DealDamage | DamageSource$ Imprinted | NumDmg$ X | References$ X | Defined$ ParentTarget | StackDescription$ None +SVar:HuntedDamage:DB$ DealDamage | DamageSource$ ParentTarget | NumDmg$ Y | References$ Y | DividerOnResolution$ ParentTargetedController | Defined$ Remembered | StackDescription$ None +SVar:X:Imprinted$CardPower +SVar:Y:Targeted$CardPower SVar:Picture:http://www.wizards.com/global/images/magic/general/master_of_the_wild_hunt.jpg Oracle:At the beginning of your upkeep, put a 2/2 green Wolf creature token onto the battlefield.\n{T}: Tap all untapped Wolf creatures you control. Each Wolf tapped this way deals damage equal to its power to target creature. That creature deals damage equal to its power divided as its controller chooses among any number of those Wolves. \ No newline at end of file diff --git a/src/main/java/forge/card/ability/AbilityUtils.java b/src/main/java/forge/card/ability/AbilityUtils.java index 729cec9c1bd..7c7eeee1639 100644 --- a/src/main/java/forge/card/ability/AbilityUtils.java +++ b/src/main/java/forge/card/ability/AbilityUtils.java @@ -744,6 +744,22 @@ public class AbilityUtils { Iterables.addAll(players, saTargeting.getTargets().getTargetPlayers()); players.add(sa.getActivatingPlayer()); } + } else if (defined.equals("ParentTargetedController")) { + final List list = getDefinedCards(card, "ParentTarget", sa); + final List sas = AbilityUtils.getDefinedSpellAbilities(card, "Targeted", sa); + + for (final Card c : list) { + final Player p = c.getController(); + if (!players.contains(p)) { + players.add(p); + } + } + for (final SpellAbility s : sas) { + final Player p = s.getActivatingPlayer(); + if (!players.contains(p)) { + players.add(p); + } + } } else if (defined.equals("Remembered")) { for (final Object rem : card.getRemembered()) { if (rem instanceof Player) { diff --git a/src/main/java/forge/card/ability/ai/DamageDealAi.java b/src/main/java/forge/card/ability/ai/DamageDealAi.java index 080a89e3b4f..d089366cfca 100644 --- a/src/main/java/forge/card/ability/ai/DamageDealAi.java +++ b/src/main/java/forge/card/ability/ai/DamageDealAi.java @@ -4,10 +4,12 @@ import java.util.List; import java.util.Random; import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.Card; import forge.CardLists; +import forge.CardPredicates; import forge.ITargetable; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; @@ -25,6 +27,7 @@ import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.zone.ZoneType; +import forge.util.Aggregates; import forge.util.MyRandom; public class DamageDealAi extends DamageAiBase { @@ -60,8 +63,14 @@ public class DamageDealAi extends DamageAiBase { dmg = ComputerUtilMana.determineLeftoverMana(sa, ai); source.setSVar("PayX", Integer.toString(dmg)); } - if ("DiscardLands".equals(sa.getParam("AILogic"))) { + String logic = sa.getParam("AILogic"); + + if ("DiscardLands".equals(logic)) { dmg = 2; + } else if ("WildHunt".equals(logic)) { + // This dummy ability will just deal 0 damage, but holds the logic for the AI for Master of Wild Hunt + List wolves = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), "Creature.Wolf+untapped+YouCtrl+Other", ai, source); + dmg = Aggregates.sum(wolves, CardPredicates.Accessors.fnGetNetAttack); } if (dmg <= 0) { @@ -499,5 +508,4 @@ public class DamageDealAi extends DamageAiBase { return true; } - } diff --git a/src/main/java/forge/card/ability/effects/DamageDealEffect.java b/src/main/java/forge/card/ability/effects/DamageDealEffect.java index f337ff187dc..162c3a9f9c6 100644 --- a/src/main/java/forge/card/ability/effects/DamageDealEffect.java +++ b/src/main/java/forge/card/ability/effects/DamageDealEffect.java @@ -1,7 +1,10 @@ package forge.card.ability.effects; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import forge.Card; import forge.CardUtil; @@ -72,6 +75,7 @@ public class DamageDealEffect extends SpellAbilityEffect { final boolean noPrevention = sa.hasParam("NoPrevention"); final boolean combatDmg = sa.hasParam("CombatDamage"); final boolean removeDamage = sa.hasParam("Remove"); + final boolean divideOnResolution = sa.hasParam("DividerOnResolution"); List tgts = getTargets(sa); @@ -110,6 +114,31 @@ public class DamageDealEffect extends SpellAbilityEffect { } final Card source = definedSources.get(0); + if (divideOnResolution) { + // Dividing Damage up to multiple targets using combat damage box + // Currently only used for Master of the Wild Hutn + List players = AbilityUtils.getDefinedPlayers(sa.getSourceCard(), sa.getParam("DividerOnResolution"), sa); + if (players.isEmpty()) { + return; + } + + List assigneeCards = new ArrayList(); + // Do we have a way of doing this in a better fashion? + for(ITargetable obj : tgts) { + if (obj instanceof Card) { + assigneeCards.add((Card)obj); + } + } + + Player assigningPlayer = players.get(0); + Map map = assigningPlayer.getController().assignCombatDamage(source, assigneeCards, dmg, null, true); + for (Entry dt : map.entrySet()) { + dt.getKey().addDamage(dt.getValue(), source); + } + + return; + } + for (final Object o : tgts) { dmg = (sa.usesTargeting() && sa.hasParam("DividedAsYouChoose")) ? sa.getTargetRestrictions().getDividedValue(o) : dmg; if (o instanceof Card) { @@ -158,5 +187,4 @@ public class DamageDealEffect extends SpellAbilityEffect { } } } - } diff --git a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java index 4980c948c93..513fde35522 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java @@ -130,162 +130,6 @@ public class CardFactoryCreatures { card.addSpellAbility(ability1); } - private static void getCard_MasterOfTheWildHunt(final Card card) { - final Cost abCost = new Cost("T", true); - final TargetRestrictions abTgt = new TargetRestrictions("Target a creature to Hunt", new String[]{"Creature"}, "1", "1"); - class MasterOfTheWildHuntAbility extends AbilityActivated { - public MasterOfTheWildHuntAbility(final Card ca, final Cost co, final TargetRestrictions t) { - super(ca, co, t); - } - - @Override - public AbilityActivated getCopy() { - return new MasterOfTheWildHuntAbility(getSourceCard(), - getPayCosts(), new TargetRestrictions(getTargetRestrictions())); - } - - private static final long serialVersionUID = 35050145102566898L; - private final Predicate untappedCreature = Predicates.and(CardPredicates.Presets.UNTAPPED, CardPredicates.Presets.CREATURES); - - @Override - public boolean canPlayAI() { - List wolves = CardLists.getType(getActivatingPlayer().getCardsIn(ZoneType.Battlefield), "Wolf"); - Iterable untappedWolves = Iterables.filter(wolves, untappedCreature); - - final int totalPower = Aggregates.sum(untappedWolves, CardPredicates.Accessors.fnGetNetAttack); - if (totalPower == 0) { - return false; - } - - List targetables = new ArrayList(getActivatingPlayer().getOpponent().getCardsIn(ZoneType.Battlefield)); - - targetables = CardLists.filter(CardLists.getTargetableCards(targetables, this), new Predicate() { - @Override - public boolean apply(final Card c) { - return c.isCreature() && (c.getNetDefense() <= totalPower); - } - }); - - if (targetables.size() == 0) { - return false; - } - - this.resetTargets(); - this.setTargetCard(ComputerUtilCard.getBestCreatureAI(targetables)); - - return true; - } - - @Override - public void resolve() { - List wolves = CardLists.getType(card.getController().getCardsIn(ZoneType.Battlefield), "Wolf"); - wolves = CardLists.filter(wolves, untappedCreature); - - final Card target = this.getTargetCard(); - - if (wolves.isEmpty() || !target.canBeTargetedBy(this)) { - return; - } - - for (final Card c : wolves) { - c.tap(); - target.addDamage(c.getNetAttack(), c); - } - - if (target.getController().isHuman()) { // Human choose spread damage - final Predicate stillInPlay = new Predicate() { - @Override - public boolean apply(final Card c){ - return c.isInPlay(); - } - }; - final int netAttack = target.getNetAttack(); - - for (int points = netAttack; points > 0; points--) { - if (!Iterables.any(wolves, stillInPlay)) break; - InputSelectCards inp = new InputSelectCardsFromList(1,1,wolves); - inp.setMessage(String.format("Select target wolf to damage for %s (%d point%s to allocate)", - target, points, points > 1? "s": "")); - Singletons.getControl().getInputQueue().setInputAndWait(inp); - inp.getSelected().get(0).addDamage(1, target); - } - } else { // AI Choose spread Damage - final List damageableWolves = CardLists.filter(wolves, new Predicate() { - @Override - public boolean apply(final Card c) { - return (ComputerUtilCombat.predictDamageTo(c, target.getNetAttack(), target, false) > 0); - } - }); - - if (damageableWolves.size() == 0) { - // can't damage - // anything - return; - } - - List wolvesLeft = CardLists.filter(damageableWolves, new Predicate() { - @Override - public boolean apply(final Card c) { - return !c.hasKeyword("Indestructible"); - } - }); - - for (int i = 0; i < target.getNetAttack(); i++) { - wolvesLeft = CardLists.filter(wolvesLeft, new Predicate() { - @Override - public boolean apply(final Card c) { - return (ComputerUtilCombat.getDamageToKill(c) > 0) - && ((ComputerUtilCombat.getDamageToKill(c) <= target.getNetAttack()) || target - .hasKeyword("Deathtouch")); - } - }); - - // Kill Wolves that can be killed first - if (wolvesLeft.size() > 0) { - final Card best = ComputerUtilCard.getBestCreatureAI(wolvesLeft); - best.addDamage(1, target); - if ((ComputerUtilCombat.getDamageToKill(best) <= 0) || target.hasKeyword("Deathtouch")) { - wolvesLeft.remove(best); - } - } else { - // Add -1/-1s to Random Indestructibles - if (target.hasKeyword("Infect") || target.hasKeyword("Wither")) { - final List indestructibles = CardLists.filter(damageableWolves, new Predicate() { - @Override - public boolean apply(final Card c) { - return c.hasKeyword("Indestructible"); - } - }); - CardLists.shuffle(indestructibles); - indestructibles.get(0).addDamage(1, target); - } - - // Then just add Damage randomnly - - else { - CardLists.shuffle(damageableWolves); - wolves.get(0).addDamage(1, target); - } - } - } - } - } // resolve() - - @Override - public String getDescription() { - final StringBuilder sb = new StringBuilder(); - sb.append("Tap: Tap all untapped Wolf creatures you control. "); - sb.append("Each Wolf tapped this way deals damage equal to its "); - sb.append("power to target creature. That creature deals damage "); - sb.append("equal to its power divided as its controller "); - sb.append("chooses among any number of those Wolves."); - return sb.toString(); - } - } - final AbilityActivated ability = new MasterOfTheWildHuntAbility(card, abCost, abTgt); - card.addSpellAbility(ability); - } - private static void getCard_SurturedGhoul(final Card card) { final Command intoPlay = new Command() { private static final long serialVersionUID = -75234586897814L; @@ -390,8 +234,6 @@ public class CardFactoryCreatures { if (cardName.equals("Sphinx of Jwar Isle")) { getCard_SphinxJwar(card); - } else if (cardName.equals("Master of the Wild Hunt")) { - getCard_MasterOfTheWildHunt(card); } else if (cardName.equals("Sutured Ghoul")) { getCard_SurturedGhoul(card); } else if (cardName.equals("Phyrexian Dreadnought")) {