- Convert Master of the Wild Hunt to script

This commit is contained in:
Sol
2013-07-09 01:28:52 +00:00
parent 59249a7155
commit 5ad15655a9
5 changed files with 62 additions and 161 deletions

View File

@@ -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.

View File

@@ -744,6 +744,22 @@ public class AbilityUtils {
Iterables.addAll(players, saTargeting.getTargets().getTargetPlayers());
players.add(sa.getActivatingPlayer());
}
} else if (defined.equals("ParentTargetedController")) {
final List<Card> list = getDefinedCards(card, "ParentTarget", sa);
final List<SpellAbility> 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) {

View File

@@ -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<Card> 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;
}
}

View File

@@ -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<ITargetable> 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<Player> players = AbilityUtils.getDefinedPlayers(sa.getSourceCard(), sa.getParam("DividerOnResolution"), sa);
if (players.isEmpty()) {
return;
}
List<Card> assigneeCards = new ArrayList<Card>();
// 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<Card, Integer> map = assigningPlayer.getController().assignCombatDamage(source, assigneeCards, dmg, null, true);
for (Entry<Card, Integer> 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 {
}
}
}
}

View File

@@ -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<Card> untappedCreature = Predicates.and(CardPredicates.Presets.UNTAPPED, CardPredicates.Presets.CREATURES);
@Override
public boolean canPlayAI() {
List<Card> wolves = CardLists.getType(getActivatingPlayer().getCardsIn(ZoneType.Battlefield), "Wolf");
Iterable<Card> untappedWolves = Iterables.filter(wolves, untappedCreature);
final int totalPower = Aggregates.sum(untappedWolves, CardPredicates.Accessors.fnGetNetAttack);
if (totalPower == 0) {
return false;
}
List<Card> targetables = new ArrayList<Card>(getActivatingPlayer().getOpponent().getCardsIn(ZoneType.Battlefield));
targetables = CardLists.filter(CardLists.getTargetableCards(targetables, this), new Predicate<Card>() {
@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<Card> 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<Card> stillInPlay = new Predicate<Card>() {
@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<Card> damageableWolves = CardLists.filter(wolves, new Predicate<Card>() {
@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<Card> wolvesLeft = CardLists.filter(damageableWolves, new Predicate<Card>() {
@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<Card>() {
@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<Card> indestructibles = CardLists.filter(damageableWolves, new Predicate<Card>() {
@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")) {