diff --git a/Mage.Sets/src/mage/sets/zendikar/LullmageMentor.java b/Mage.Sets/src/mage/sets/zendikar/LullmageMentor.java new file mode 100644 index 00000000000..181d8da30ad --- /dev/null +++ b/Mage.Sets/src/mage/sets/zendikar/LullmageMentor.java @@ -0,0 +1,200 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.zendikar; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; +import mage.game.stack.StackObject; +import mage.target.Target; +import mage.target.TargetSpell; +import mage.target.common.TargetControlledCreaturePermanent; +import mage.watchers.WatcherImpl; + +/** + * + * @author LevelX2 + */ +public class LullmageMentor extends CardImpl { + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Merfolks you control"); + + static { + filter.add(new SubtypePredicate("Merfolk")); + filter.add(Predicates.not(new TappedPredicate())); + } + public LullmageMentor(UUID ownerId) { + super(ownerId, 54, "Lullmage Mentor", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); + this.expansionSetCode = "ZEN"; + this.subtype.add("Merfolk"); + this.subtype.add("Wizard"); + + this.color.setBlue(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever a spell or ability you control counters a spell, you may put a 1/1 blue Merfolk creature token onto the battlefield. + this.addAbility(new LullmageMentorTriggeredAbility()); + this.addWatcher(new CastedSpellsWithSpellTarget()); + // Tap seven untapped Merfolk you control: Counter target spell. + Ability ability = new SimpleActivatedAbility(Constants.Zone.BATTLEFIELD, new CounterTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(7, 7, filter, true))); + ability.addTarget(new TargetSpell()); + this.addAbility(ability); + + } + + public LullmageMentor(final LullmageMentor card) { + super(card); + } + + @Override + public LullmageMentor copy() { + return new LullmageMentor(this); + } +} + +class LullmageMentorTriggeredAbility extends TriggeredAbilityImpl { + + public LullmageMentorTriggeredAbility() { + super(Zone.BATTLEFIELD, new CreateTokenEffect(new MerfolkToken()), false); + } + + public LullmageMentorTriggeredAbility(final LullmageMentorTriggeredAbility ability) { + super(ability); + } + + @Override + public LullmageMentorTriggeredAbility copy() { + return new LullmageMentorTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (event.getType() == EventType.COUNTERED) { + CastedSpellsWithSpellTarget watcher = (CastedSpellsWithSpellTarget) game.getState().getWatchers().get("CastedSpellsWithSpellTarget"); + UUID controllerIdCounter = watcher.getControllerSpell(event.getSourceId(), event.getTargetId()); + if (controllerIdCounter != null && controllerIdCounter.equals(controllerId)) { + return true; + } + } + return false; + } + + @Override + public String getRule() { + return new StringBuilder("Whenever a spell or ability you control counters a spell, ").append(super.getRule()).toString(); + } +} + +class MerfolkToken extends Token { + + public MerfolkToken() { + super("Merfolk", "1/1 blue Merfolk creature token"); + cardType.add(Constants.CardType.CREATURE); + color.setBlue(true); + subtype.add("Merfolk"); + power = new MageInt(1); + toughness = new MageInt(1); + } +} + +class CastedSpellsWithSpellTarget extends WatcherImpl { + + // + private Map casted = new HashMap(); + + public CastedSpellsWithSpellTarget() { + super("CastedSpellsWithSpellTarget", Constants.WatcherScope.GAME); + } + + public CastedSpellsWithSpellTarget(final CastedSpellsWithSpellTarget watcher) { + super(watcher); + for (Map.Entry entry: watcher.casted.entrySet()) { + casted.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.SPELL_CAST || event.getType() == GameEvent.EventType.ACTIVATED_ABILITY) { + StackObject stackObject = game.getStack().getStackObject(event.getTargetId()); + if (stackObject != null && stackObject.getStackAbility() != null) { + for (Target target: stackObject.getStackAbility().getTargets()) { + if (target instanceof TargetSpell && target.getFirstTarget() != null) { + casted.put(getKey(target.getFirstTarget(), stackObject.getSourceId()), stackObject.getControllerId()); + } + } + } + } + } + + private String getKey(UUID targetId, UUID sourceId) { + return new StringBuilder(targetId.toString()).append("_").append(sourceId.toString()).toString(); + } + + public UUID getControllerSpell(UUID sourceId, UUID counteredSpell) { + if (sourceId != null && counteredSpell != null){ + return casted.get(getKey(counteredSpell, sourceId)); + } + return null; + } + + @Override + public void reset() { + super.reset(); + casted.clear(); + } + + @Override + public CastedSpellsWithSpellTarget copy() { + return new CastedSpellsWithSpellTarget(this); + } + +} diff --git a/Mage.Sets/src/mage/sets/zendikar/ObsidianFireheart.java b/Mage.Sets/src/mage/sets/zendikar/ObsidianFireheart.java new file mode 100644 index 00000000000..f4c49bae116 --- /dev/null +++ b/Mage.Sets/src/mage/sets/zendikar/ObsidianFireheart.java @@ -0,0 +1,128 @@ +/* + * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.sets.zendikar; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Duration; +import mage.Constants.Rarity; +import mage.Constants.TargetController; +import mage.Constants.Zone; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageControllerEffect; +import mage.abilities.effects.common.continious.GainAbilityTargetEffect; +import mage.abilities.effects.common.counter.AddCountersTargetEffect; +import mage.cards.CardImpl; +import mage.counters.CounterType; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.CounterPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.target.common.TargetLandPermanent; + +/** + * + * @author LevelX2 + */ +public class ObsidianFireheart extends CardImpl { + + private static final String rule = "For as long as that land has a blaze counter on it, it has \"At the beginning of your upkeep, this land deals 1 damage to you.\" (The land continues to burn after Obsidian Fireheart has left the battlefield.)"; + private static final FilterLandPermanent filter = new FilterLandPermanent("land without a blaze counter on it"); + + static { + filter.add(Predicates.not(new CounterPredicate(CounterType.BLAZE))); + } + + public ObsidianFireheart(UUID ownerId) { + super(ownerId, 140, "Obsidian Fireheart", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{1}{R}{R}{R}"); + this.expansionSetCode = "ZEN"; + this.subtype.add("Elemental"); + this.color.setRed(true); + + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // {1}{R}{R}: Put a blaze counter on target land without a blaze counter on it. + // For as long as that land has a blaze counter on it, it has "At the beginning + // of your upkeep, this land deals 1 damage to you." (The land continues to burn + // after Obsidian Fireheart has left the battlefield.) + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersTargetEffect(CounterType.BLAZE.createInstance()),new ManaCostsImpl("{1}{R}{R}{R}")); + ability.addTarget(new TargetLandPermanent(filter)); + Effect effect = new ObsidianFireheartGainAbilityEffect( + new BeginningOfUpkeepTriggeredAbility( + new DamageControllerEffect(1), + TargetController.YOU, + false), + Duration.Custom, rule); + ability.addEffect(effect); + this.addAbility(ability); + + } + + public ObsidianFireheart(final ObsidianFireheart card) { + super(card); + } + + @Override + public ObsidianFireheart copy() { + return new ObsidianFireheart(this); + } +} + + +class ObsidianFireheartGainAbilityEffect extends GainAbilityTargetEffect { + + public ObsidianFireheartGainAbilityEffect(Ability ability, Duration duration, String rule) { + super(ability, duration, rule); + } + + public ObsidianFireheartGainAbilityEffect(final ObsidianFireheartGainAbilityEffect effect) { + super(effect); + } + + @Override + public boolean isInactive(Ability source, Game game) { + Permanent land = game.getPermanent(this.targetPointer.getFirst(game, source)); + if (land != null && land.getCounters().getCount(CounterType.BLAZE) < 1) { + return true; + } + return false; + } + + @Override + public ObsidianFireheartGainAbilityEffect copy() { + return new ObsidianFireheartGainAbilityEffect(this); + } +} diff --git a/Mage/src/mage/counters/CounterType.java b/Mage/src/mage/counters/CounterType.java index 0d5d7282b7e..29deac4a78e 100644 --- a/Mage/src/mage/counters/CounterType.java +++ b/Mage/src/mage/counters/CounterType.java @@ -70,7 +70,8 @@ public enum CounterType { PETRIFICATION(new PetrificationCounter().name), MINING(new MiningCounter().name), THEFT(new TheftCounter().name), - AGE(new AgeCounter().name); + AGE(new AgeCounter().name), + BLAZE(new BlazeCounter().name); private String name; @@ -174,6 +175,8 @@ public enum CounterType { return new TheftCounter(amount); case AGE: return new AgeCounter(amount); + case BLAZE: + return new BlazeCounter(amount); } return null; diff --git a/Mage/src/mage/counters/common/BlazeCounter.java b/Mage/src/mage/counters/common/BlazeCounter.java new file mode 100644 index 00000000000..a83711625f5 --- /dev/null +++ b/Mage/src/mage/counters/common/BlazeCounter.java @@ -0,0 +1,14 @@ +package mage.counters.common; + +import mage.counters.Counter; + +public class BlazeCounter extends Counter { + public BlazeCounter() { + this(1); + } + + public BlazeCounter(int amount) { + super("Blaze"); + this.count = amount; + } +} \ No newline at end of file