From 9bea7c7df2318a2beb073fdc4aaed23180b134da Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 18 Jan 2019 17:29:58 -0600 Subject: [PATCH] - Added Aggression and Wiitigo. --- Mage.Sets/src/mage/cards/a/Aggression.java | 104 ++++++++++++++ Mage.Sets/src/mage/cards/w/Wiitigo.java | 136 ++++++++++++++++++ Mage.Sets/src/mage/sets/IceAge.java | 2 + Mage.Sets/src/mage/sets/MastersEditionII.java | 1 + 4 files changed, 243 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/a/Aggression.java create mode 100644 Mage.Sets/src/mage/cards/w/Wiitigo.java diff --git a/Mage.Sets/src/mage/cards/a/Aggression.java b/Mage.Sets/src/mage/cards/a/Aggression.java new file mode 100644 index 00000000000..78b9408748f --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/Aggression.java @@ -0,0 +1,104 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.MageObjectReference; +import mage.constants.SubType; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DestroyAttachedToEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.watchers.common.AttackedThisTurnWatcher; + +/** + * + * @author jeffwadsworth + */ +public final class Aggression extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(Predicates.not(new SubtypePredicate(SubType.WALL))); + } + + public Aggression(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + + this.subtype.add(SubType.AURA); + + // Enchant non-Wall creature + TargetPermanent auraTarget = new TargetPermanent(filter); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature has first strike and trample. + Ability ability2 = new SimpleStaticAbility( + Zone.BATTLEFIELD, + new GainAbilityAttachedEffect( + FirstStrikeAbility.getInstance(), + AttachmentType.AURA)); + ability2.addEffect(new GainAbilityAttachedEffect( + TrampleAbility.getInstance(), + AttachmentType.AURA)); + this.addAbility(ability2); + + // At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn. + this.addAbility(new ConditionalTriggeredAbility( + new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new DestroyAttachedToEffect("enchanted"), + TargetController.CONTROLLER_ATTACHED_TO), + DidNotAttackedThisTurnEnchantedCondition.instance, + "At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn."), + new AttackedThisTurnWatcher()); + + } + + private Aggression(final Aggression card) { + super(card); + } + + @Override + public Aggression copy() { + return new Aggression(this); + } +} + +enum DidNotAttackedThisTurnEnchantedCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + Permanent auraPermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (auraPermanent != null) { + Permanent enchantedPermanent = game.getPermanent(auraPermanent.getAttachedTo()); + AttackedThisTurnWatcher watcher = game.getState().getWatcher(AttackedThisTurnWatcher.class); + return enchantedPermanent != null + && watcher != null + && !watcher.getAttackedThisTurnCreatures().contains( + new MageObjectReference(enchantedPermanent, game)); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/w/Wiitigo.java b/Mage.Sets/src/mage/cards/w/Wiitigo.java new file mode 100644 index 00000000000..79f7c766f88 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/Wiitigo.java @@ -0,0 +1,136 @@ +package mage.cards.w; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.effects.common.counter.RemoveCounterSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.WatcherScope; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.watchers.Watcher; + +/** + * + * @author jeffwadsworth + */ +public final class Wiitigo extends CardImpl { + + public Wiitigo(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}{G}"); + + this.subtype.add(SubType.YETI); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Wiitigo enters the battlefield with six +1/+1 counters on it. + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(6)))); + + // At the beginning of your upkeep, put a +1/+1 counter on Wiitigo if it has blocked or been blocked since your last upkeep. Otherwise, remove a +1/+1 counter from it. + Ability triggeredAbility = new BeginningOfUpkeepTriggeredAbility( + new ConditionalOneShotEffect( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(1)), + new RemoveCounterSourceEffect(CounterType.P1P1.createInstance(1)), + new BlockedOrBeenBlockedSinceYourLastUpkeepCondition(), + "put a +1/+1 counter on enchanted creature if it blocked or been blocked since your last " + + "upkeep. Otherwise, remove a +1/+1 counter from it"), + TargetController.YOU, + false); + triggeredAbility.addWatcher(new BlockedOrBeenBlockedSinceYourLastUpkeepWatcher()); + this.addAbility(triggeredAbility); + } + + private Wiitigo(final Wiitigo card) { + super(card); + } + + @Override + public Wiitigo copy() { + return new Wiitigo(this); + } +} + +class BlockedOrBeenBlockedSinceYourLastUpkeepCondition implements Condition { + + @Override + public boolean apply(Game game, Ability source) { + Permanent wiitigo = game.getBattlefield().getPermanent(source.getSourceId()); + BlockedOrBeenBlockedSinceYourLastUpkeepWatcher watcher = game.getState().getWatcher( + BlockedOrBeenBlockedSinceYourLastUpkeepWatcher.class); + if (wiitigo != null + && watcher != null) { + return watcher.blockedOrBeenBlockedSinceLastUpkeep( + new MageObjectReference(wiitigo.getId(), + wiitigo.getZoneChangeCounter(game), + game), + wiitigo.getControllerId()); + } + return false; + } + + @Override + public String toString() { + return "it blocked or was blocked since your last upkeep"; + } +} + +class BlockedOrBeenBlockedSinceYourLastUpkeepWatcher extends Watcher { + + private final Map> blockedOrBeenBlockedCreatures = new HashMap<>(); + + public BlockedOrBeenBlockedSinceYourLastUpkeepWatcher() { + super(BlockedOrBeenBlockedSinceYourLastUpkeepWatcher.class, WatcherScope.GAME); + } + + public BlockedOrBeenBlockedSinceYourLastUpkeepWatcher(BlockedOrBeenBlockedSinceYourLastUpkeepWatcher watcher) { + super(watcher); + for (Map.Entry> entry : watcher.blockedOrBeenBlockedCreatures.entrySet()) { + Set creaturesThatBlockedOrWereBlocked = new HashSet<>(entry.getValue()); + blockedOrBeenBlockedCreatures.put(entry.getKey(), creaturesThatBlockedOrWereBlocked); + } + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.UPKEEP_STEP_POST) { + blockedOrBeenBlockedCreatures.put(event.getPlayerId(), new HashSet<>()); // clear the watcher after upkeep + } else if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) { + MageObjectReference morBlocker = new MageObjectReference(event.getSourceId(), game); // store blocker + MageObjectReference morAttackerBlocked = new MageObjectReference(event.getTargetId(), game); // store attacker blocked + for (UUID player : game.getPlayerList()) { + if (!blockedOrBeenBlockedCreatures.containsKey(player)) { + blockedOrBeenBlockedCreatures.put(player, new HashSet<>()); + } + blockedOrBeenBlockedCreatures.get(player).add(morBlocker); + blockedOrBeenBlockedCreatures.get(player).add(morAttackerBlocked); + } + } + } + + public boolean blockedOrBeenBlockedSinceLastUpkeep(MageObjectReference mor, UUID player) { + return (blockedOrBeenBlockedCreatures.get(player) != null) + && blockedOrBeenBlockedCreatures.get(player).contains(mor); + } + + @Override + public BlockedOrBeenBlockedSinceYourLastUpkeepWatcher copy() { + return new BlockedOrBeenBlockedSinceYourLastUpkeepWatcher(this); + } +} diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index 2856fd2a3f0..92bd54a7c97 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -29,6 +29,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Adarkar Sentinel", 306, Rarity.UNCOMMON, mage.cards.a.AdarkarSentinel.class)); cards.add(new SetCardInfo("Adarkar Wastes", 351, Rarity.RARE, mage.cards.a.AdarkarWastes.class)); cards.add(new SetCardInfo("Aegis of the Meek", 307, Rarity.RARE, mage.cards.a.AegisOfTheMeek.class)); + cards.add(new SetCardInfo("Aggression", 169, Rarity.UNCOMMON, mage.cards.a.Aggression.class)); cards.add(new SetCardInfo("Altar of Bone", 281, Rarity.RARE, mage.cards.a.AltarOfBone.class)); cards.add(new SetCardInfo("Anarchy", 170, Rarity.UNCOMMON, mage.cards.a.Anarchy.class)); cards.add(new SetCardInfo("Arenson's Aura", 3, Rarity.COMMON, mage.cards.a.ArensonsAura.class)); @@ -358,6 +359,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Whalebone Glider", 349, Rarity.UNCOMMON, mage.cards.w.WhaleboneGlider.class)); cards.add(new SetCardInfo("White Scarab", 56, Rarity.UNCOMMON, mage.cards.w.WhiteScarab.class)); cards.add(new SetCardInfo("Whiteout", 275, Rarity.UNCOMMON, mage.cards.w.Whiteout.class)); + cards.add(new SetCardInfo("Wiitigo", 276, Rarity.RARE, mage.cards.w.Wiitigo.class)); cards.add(new SetCardInfo("Wild Growth", 277, Rarity.COMMON, mage.cards.w.WildGrowth.class)); cards.add(new SetCardInfo("Wind Spirit", 106, Rarity.UNCOMMON, mage.cards.w.WindSpirit.class)); cards.add(new SetCardInfo("Wings of Aesthir", 305, Rarity.UNCOMMON, mage.cards.w.WingsOfAesthir.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index 891cfdbd1f0..706fd806055 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -249,6 +249,7 @@ public final class MastersEditionII extends ExpansionSet { cards.add(new SetCardInfo("Warning", 38, Rarity.COMMON, mage.cards.w.Warning.class)); cards.add(new SetCardInfo("Whirling Catapult", 224, Rarity.UNCOMMON, mage.cards.w.WhirlingCatapult.class)); cards.add(new SetCardInfo("Whiteout", 185, Rarity.COMMON, mage.cards.w.Whiteout.class)); + cards.add(new SetCardInfo("Wiitigo", 186, Rarity.RARE, mage.cards.w.Wiitigo.class)); cards.add(new SetCardInfo("Wind Spirit", 75, Rarity.UNCOMMON, mage.cards.w.WindSpirit.class)); cards.add(new SetCardInfo("Wings of Aesthir", 199, Rarity.UNCOMMON, mage.cards.w.WingsOfAesthir.class)); cards.add(new SetCardInfo("Winter's Night", 200, Rarity.RARE, mage.cards.w.WintersNight.class));