From 6a78684da8428cb702d8593482871e16d8688e6f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 6 Oct 2015 00:47:17 +0200 Subject: [PATCH 1/2] * Blatant Thievery - Changed handling to custom target. --- .../mage/sets/magic2015/SoulOfShandalar.java | 9 +- .../mage/sets/onslaught/BlatantThievery.java | 132 +++++++++++++++--- .../mage/sets/planechase2012/MassMutiny.java | 18 ++- .../effects/common/BasicManaEffect.java | 5 +- Mage/src/mage/filter/FilterPermanent.java | 57 ++++---- 5 files changed, 158 insertions(+), 63 deletions(-) diff --git a/Mage.Sets/src/mage/sets/magic2015/SoulOfShandalar.java b/Mage.Sets/src/mage/sets/magic2015/SoulOfShandalar.java index 7c26bd2161..98de37ffea 100644 --- a/Mage.Sets/src/mage/sets/magic2015/SoulOfShandalar.java +++ b/Mage.Sets/src/mage/sets/magic2015/SoulOfShandalar.java @@ -27,6 +27,9 @@ */ package mage.sets.magic2015; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; @@ -48,10 +51,6 @@ import mage.players.Player; import mage.target.TargetPermanent; import mage.target.TargetPlayer; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - /** * @author noxx */ @@ -145,7 +144,7 @@ class SoulOfShandalarTarget extends TargetPermanent { @Override public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set availablePossibleTargets = super.possibleTargets(sourceId, sourceControllerId, game); - Set possibleTargets = new HashSet(); + Set possibleTargets = new HashSet<>(); MageObject object = game.getObject(sourceId); for (StackObject item : game.getState().getStack()) { diff --git a/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java b/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java index 09586f6108..b4ec25b2bc 100644 --- a/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java +++ b/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java @@ -27,7 +27,12 @@ */ package mage.sets.onslaught; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.effects.ContinuousEffect; @@ -39,10 +44,8 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.filter.FilterPermanent; -import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; -import mage.players.Player; -import mage.target.Target; +import mage.game.permanent.Permanent; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; @@ -63,19 +66,12 @@ public class BlatantThievery extends CardImpl { public BlatantThievery(final BlatantThievery card) { super(card); } - + @Override public void adjustTargets(Ability ability, Game game) { if (ability instanceof SpellAbility) { ability.getTargets().clear(); - for (UUID opponentId : game.getOpponents(ability.getControllerId())) { - Player opponent = game.getPlayer(opponentId); - if (opponent != null) { - FilterPermanent filter = new FilterPermanent("permanent controlled by " + opponent.getName()); - filter.add(new ControllerIdPredicate(opponentId)); - ability.addTarget(new TargetPermanent(filter)); - } - } + ability.addTarget(new BlatantThieveryTarget(game.getOpponents(ability.getControllerId()).size())); } } @@ -86,28 +82,128 @@ public class BlatantThievery extends CardImpl { } class BlatantThieveryEffect extends OneShotEffect { - + BlatantThieveryEffect() { super(Outcome.GainControl); this.staticText = "For each opponent, gain control of target permanent that player controls"; } - + BlatantThieveryEffect(final BlatantThieveryEffect effect) { super(effect); } - + @Override public BlatantThieveryEffect copy() { return new BlatantThieveryEffect(this); } - + @Override public boolean apply(Game game, Ability source) { - for (Target target : source.getTargets()) { + for (UUID targetId : getTargetPointer().getTargets(game, source)) { ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame); - effect.setTargetPointer(new FixedTarget(target.getFirstTarget())); + effect.setTargetPointer(new FixedTarget(targetId)); game.addEffect(effect, source); } return true; } } + +class BlatantThieveryTarget extends TargetPermanent { + + Map targetOpponent = new HashMap<>(); + + public BlatantThieveryTarget(int opponents) { + super(opponents, opponents, new FilterPermanent("a permanent for each opponent"), false); + } + + public BlatantThieveryTarget(final BlatantThieveryTarget target) { + super(target); + this.targetOpponent.putAll(target.targetOpponent); + } + + @Override + public boolean canTarget(UUID controllerId, UUID objectId, Ability source, Game game) { + Permanent targetObject = game.getPermanent(objectId); + if (targetObject == null || !game.getOpponents(source.getControllerId()).contains(targetObject.getControllerId())) { + return false; + } + // If a permanent changes controller after being targeted but before this spell resolves, you won't gain control of that permanent. + if (targetOpponent.containsKey(objectId)) { + if (!targetOpponent.get(objectId).equals(targetObject.getControllerId())) { + return false; + } + } else { + // if already a target from this opponent exists, another can't be target + if (targetOpponent.values().contains(targetObject.getControllerId())) { + return false; + } + } + return super.canTarget(controllerId, objectId, source, game); + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set opponents = new HashSet<>(); + for (UUID targetId : getTargets()) { + Permanent oldTargets = game.getPermanent(targetId); + if (oldTargets != null) { + opponents.add(oldTargets.getControllerId()); + } + } + Set possibleTargets = new HashSet<>(); + MageObject mageObject = game.getObject(sourceId); + if (mageObject == null) { + return possibleTargets; + } + for (UUID opponentId : game.getOpponents(sourceControllerId)) { + if (opponents.contains(opponentId)) { + // Target for this opponent already selected + continue; + } + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(opponentId)) { + if (permanent.canBeTargetedBy(mageObject, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + } + } + return possibleTargets; + } + + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + for (UUID opponentId : game.getOpponents(sourceControllerId)) { + boolean targetAvailable = false; + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(opponentId)) { + if (!targets.containsKey(permanent.getId())) { + MageObject mageObject = game.getObject(sourceId); + if (mageObject != null && permanent.canBeTargetedBy(mageObject, sourceControllerId, game)) { + targetAvailable = true; + break; + } + + } else { + targetAvailable = true; + break; + } + } + if (!targetAvailable) { + return false; + } + } + return true; + } + + @Override + public void addTarget(UUID objectId, int amount, Ability source, Game game, boolean skipEvent) { + Permanent targetObject = game.getPermanent(objectId); + if (targetObject != null) { + targetOpponent.put(objectId, targetObject.getControllerId()); + } + super.addTarget(objectId, amount, source, game, skipEvent); + } + + @Override + public BlatantThieveryTarget copy() { + return new BlatantThieveryTarget(this); + } +} diff --git a/Mage.Sets/src/mage/sets/planechase2012/MassMutiny.java b/Mage.Sets/src/mage/sets/planechase2012/MassMutiny.java index fd242dfa30..3931ee3e8e 100644 --- a/Mage.Sets/src/mage/sets/planechase2012/MassMutiny.java +++ b/Mage.Sets/src/mage/sets/planechase2012/MassMutiny.java @@ -28,11 +28,6 @@ package mage.sets.planechase2012; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.effects.ContinuousEffect; @@ -41,6 +36,10 @@ import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; @@ -60,20 +59,20 @@ public class MassMutiny extends CardImpl { super(ownerId, 48, "Mass Mutiny", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{3}{R}{R}"); this.expansionSetCode = "PC2"; - this.getSpellAbility().addEffect(new MassMutinyEffect()); // For each opponent, gain control of up to one target creature that player controls until end of turn. Untap those creatures. They gain haste until end of turn. + this.getSpellAbility().addEffect(new MassMutinyEffect()); } @Override public void adjustTargets(Ability ability, Game game) { if (ability instanceof SpellAbility) { - for(UUID opponentId : game.getOpponents(ability.getControllerId())) { + for (UUID opponentId : game.getOpponents(ability.getControllerId())) { Player opponent = game.getPlayer(opponentId); if (opponent != null) { ability.getTargets().clear(); FilterCreaturePermanent filter = new FilterCreaturePermanent("creature from opponent " + opponent.getLogName()); filter.add(new ControllerIdPredicate(opponentId)); - TargetCreaturePermanent target = new TargetCreaturePermanent(0,1, filter,false); + TargetCreaturePermanent target = new TargetCreaturePermanent(0, 1, filter, false); ability.addTarget(target); } } @@ -90,7 +89,6 @@ public class MassMutiny extends CardImpl { } } - class MassMutinyEffect extends OneShotEffect { public MassMutinyEffect() { @@ -110,7 +108,7 @@ class MassMutinyEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { boolean result = false; - for (Target target: source.getTargets()) { + for (Target target : source.getTargets()) { if (target instanceof TargetCreaturePermanent) { Permanent targetCreature = game.getPermanent(target.getFirstTarget()); if (targetCreature != null) { diff --git a/Mage/src/mage/abilities/effects/common/BasicManaEffect.java b/Mage/src/mage/abilities/effects/common/BasicManaEffect.java index b98d1dd7ef..95e7faa8ea 100644 --- a/Mage/src/mage/abilities/effects/common/BasicManaEffect.java +++ b/Mage/src/mage/abilities/effects/common/BasicManaEffect.java @@ -6,18 +6,19 @@ import mage.abilities.Ability; import mage.game.Game; public class BasicManaEffect extends ManaEffect { + protected Mana mana; public BasicManaEffect(Mana mana) { super(); this.mana = mana; - staticText = "Add " + mana.toString() + " to your mana pool"; + staticText = "add " + mana.toString() + " to your mana pool"; } public BasicManaEffect(ConditionalMana conditionalMana) { super(); this.mana = conditionalMana; - staticText = "Add " + mana.toString() + " to your mana pool. " + conditionalMana.getDescription(); + staticText = "add " + mana.toString() + " to your mana pool. " + conditionalMana.getDescription(); } public BasicManaEffect(final BasicManaEffect effect) { diff --git a/Mage/src/mage/filter/FilterPermanent.java b/Mage/src/mage/filter/FilterPermanent.java index 24b5418451..5e14f969cc 100644 --- a/Mage/src/mage/filter/FilterPermanent.java +++ b/Mage/src/mage/filter/FilterPermanent.java @@ -1,31 +1,30 @@ /* -* 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. -*/ - + * 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.filter; import java.util.ArrayList; @@ -44,6 +43,7 @@ import mage.game.permanent.Permanent; * @author North */ public class FilterPermanent extends FilterObject implements FilterInPlay { + protected List>> extraPredicates = new ArrayList<>(); public FilterPermanent() { @@ -58,12 +58,13 @@ public class FilterPermanent extends FilterObject implements FilterIn public FilterPermanent(String name) { super(name); } - + public FilterPermanent(String subtype, String name) { super(name); this.add(new SubtypePredicate(subtype)); } + @Override public boolean match(Permanent permanent, UUID sourceId, UUID playerId, Game game) { if (!this.match(permanent, game)) { return false; From 5b4248f81dd7ce73f9bbe1cab4a2d3a51e2a773f Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 6 Oct 2015 00:53:40 +0200 Subject: [PATCH 2/2] * Blatant Thievery - Changed handling to custom target. --- Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java b/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java index b4ec25b2bc..12c5dc8cfe 100644 --- a/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java +++ b/Mage.Sets/src/mage/sets/onslaught/BlatantThievery.java @@ -202,6 +202,12 @@ class BlatantThieveryTarget extends TargetPermanent { super.addTarget(objectId, amount, source, game, skipEvent); } + @Override + public void remove(UUID id) { + super.remove(id); + targetOpponent.remove(id); + } + @Override public BlatantThieveryTarget copy() { return new BlatantThieveryTarget(this);