diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/SerpentineSpike.java b/Mage.Sets/src/mage/sets/battleforzendikar/SerpentineSpike.java index b6de1e9f1a..292dc45afd 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/SerpentineSpike.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/SerpentineSpike.java @@ -39,6 +39,7 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -60,9 +61,23 @@ public class SerpentineSpike extends CardImpl { this.addAbility(ability); // Serpentine Spike deals 2 damage to target creature, 3 damage to another target creature, and 4 damage to a third target creature. If a creature dealt damage this way would die this turn, exile it instead. this.getSpellAbility().addEffect(new SerpentineSpikeEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2 damage)"))); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (3 damage)"))); - this.getSpellAbility().addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (4 damage)"))); + + TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature (2 damage)")); + target.setTargetTag(1); + this.getSpellAbility().addTarget(target); + + FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature (3 damage)"); + filter.add(new AnotherTargetPredicate(2)); + target = new TargetCreaturePermanent(filter); + target.setTargetTag(2); + this.getSpellAbility().addTarget(target); + + filter = new FilterCreaturePermanent("another target creature (4 damage)"); + filter.add(new AnotherTargetPredicate(3)); + target = new TargetCreaturePermanent(filter); + target.setTargetTag(3); + this.getSpellAbility().addTarget(target); + Effect effect = new DealtDamageToCreatureBySourceDies(this, Duration.EndOfTurn); effect.setText("If a creature dealt damage this way would die this turn, exile it instead"); this.getSpellAbility().addEffect(effect); diff --git a/Mage.Sets/src/mage/sets/exodus/KorChant.java b/Mage.Sets/src/mage/sets/exodus/KorChant.java index 0269d443ed..3aa8d9effb 100644 --- a/Mage.Sets/src/mage/sets/exodus/KorChant.java +++ b/Mage.Sets/src/mage/sets/exodus/KorChant.java @@ -35,6 +35,8 @@ 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.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.target.TargetSource; @@ -53,8 +55,15 @@ public class KorChant extends CardImpl { // All damage that would be dealt this turn to target creature you control by a source of your choice is dealt to another target creature instead. this.getSpellAbility().addEffect(new KorChantEffect()); - this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); - this.getSpellAbility().addTarget(new KorChantSecondTarget()); + TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); + target.setTargetTag(1); + this.getSpellAbility().addTarget(target); + + FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); + filter.add(new AnotherTargetPredicate(2)); + TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); + target2.setTargetTag(2); + this.getSpellAbility().addTarget(target2); } public KorChant(final KorChant card) { @@ -67,33 +76,8 @@ public class KorChant extends CardImpl { } } -class KorChantSecondTarget extends TargetCreaturePermanent { - - KorChantSecondTarget() { - super(); - this.targetName = "another creature"; - } - - KorChantSecondTarget(final KorChantSecondTarget target) { - super(target); - } - - @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - if (source.getTargets().get(0).getTargets().contains(id)) { - return false; - } - return super.canTarget(controllerId, id, source, game); - } - - @Override - public KorChantSecondTarget copy() { - return new KorChantSecondTarget(this); - } -} - class KorChantEffect extends RedirectionEffect { - + protected TargetSource target = new TargetSource(); KorChantEffect() { @@ -121,7 +105,7 @@ class KorChantEffect extends RedirectionEffect { public boolean checksEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.DAMAGE_CREATURE; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getTargetId().equals(this.getTargetPointer().getFirst(game, source)) diff --git a/Mage.Sets/src/mage/sets/jacevsvraska/DroolingGroodion.java b/Mage.Sets/src/mage/sets/jacevsvraska/DroolingGroodion.java index b27d9824f7..dda545b51e 100644 --- a/Mage.Sets/src/mage/sets/jacevsvraska/DroolingGroodion.java +++ b/Mage.Sets/src/mage/sets/jacevsvraska/DroolingGroodion.java @@ -44,6 +44,7 @@ import mage.constants.SubLayer; import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetControlledCreaturePermanent; @@ -66,8 +67,17 @@ public class DroolingGroodion extends CardImpl { // {2}{B}{G}, Sacrifice a creature: Target creature gets +2/+2 until end of turn. Another target creature gets -2/-2 until end of turn. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DroolingGroodionEffect(), new ManaCostsImpl("{2}{B}{G}")); ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent(1, 1, new FilterControlledCreaturePermanent(), true))); - ability.addTarget(new TargetCreaturePermanent(new FilterCreaturePermanent("creature (first target)"))); - ability.addTarget(new TargetOtherCreaturePermanent(new FilterCreaturePermanent("creature (second target)"))); + + TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature (first target)")); + target.setTargetTag(1); + ability.addTarget(target); + + FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature (second target"); + filter.add(new AnotherTargetPredicate(2)); + target = new TargetCreaturePermanent(filter); + target.setTargetTag(2); + ability.addTarget(target); + this.addAbility(ability); } @@ -112,28 +122,3 @@ class DroolingGroodionEffect extends ContinuousEffectImpl { return true; } } - -class TargetOtherCreaturePermanent extends TargetCreaturePermanent { - - public TargetOtherCreaturePermanent(FilterCreaturePermanent filter) { - super(filter); - } - - public TargetOtherCreaturePermanent(final TargetOtherCreaturePermanent target) { - super(target); - } - - @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - if (source.getTargets().get(0).getTargets().contains(id)) { - return false; - } - return super.canTarget(controllerId, id, source, game); - } - - @Override - public TargetOtherCreaturePermanent copy() { - return new TargetOtherCreaturePermanent(this); - } - -} diff --git a/Mage.Sets/src/mage/sets/tempestremastered/Deadshot.java b/Mage.Sets/src/mage/sets/tempestremastered/Deadshot.java index e2fd17d882..1aa0222736 100644 --- a/Mage.Sets/src/mage/sets/tempestremastered/Deadshot.java +++ b/Mage.Sets/src/mage/sets/tempestremastered/Deadshot.java @@ -36,29 +36,39 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.SecondTargetPointer; /** * * @author fireshoes */ public class Deadshot extends CardImpl { - + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("another target creature"); + static { + filter.add(new AnotherTargetPredicate(2)); + } + public Deadshot(UUID ownerId) { super(ownerId, 129, "Deadshot", Rarity.UNCOMMON, new CardType[]{CardType.SORCERY}, "{3}{R}"); this.expansionSetCode = "TPR"; // Tap target creature. this.getSpellAbility().addEffect(new TapTargetEffect()); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - + TargetCreaturePermanent target = new TargetCreaturePermanent(); + target.setTargetTag(1); + this.getSpellAbility().addTarget(target); + // It deals damage equal to its power to another target creature. this.getSpellAbility().addEffect(new DeadshotDamageEffect()); - this.getSpellAbility().addTarget(new DeadshotTargetCreaturePermanent(filter)); + target = new TargetCreaturePermanent(filter); + target.setTargetTag(2); + this.getSpellAbility().addTarget(target); } public Deadshot(final Deadshot card) { @@ -80,6 +90,7 @@ class DeadshotDamageEffect extends OneShotEffect { public DeadshotDamageEffect(final DeadshotDamageEffect effect) { super(effect); + this.setTargetPointer(new SecondTargetPointer()); } @Override @@ -89,10 +100,10 @@ class DeadshotDamageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent ownCreature = game.getPermanent(source.getFirstTarget()); + Permanent ownCreature = game.getPermanentOrLKIBattlefield(source.getFirstTarget()); if (ownCreature != null) { int damage = ownCreature.getPower().getValue(); - Permanent targetCreature = game.getPermanent(source.getTargets().get(1).getFirstTarget()); + Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); if (targetCreature != null) { targetCreature.damage(damage, ownCreature.getId(), game, false, true); return true; @@ -101,27 +112,3 @@ class DeadshotDamageEffect extends OneShotEffect { return false; } } - -class DeadshotTargetCreaturePermanent extends TargetCreaturePermanent { - - public DeadshotTargetCreaturePermanent(FilterCreaturePermanent filter) { - super(filter); - } - - @Override - public boolean canTarget(UUID id, Ability source, Game game) { - if (source.getTargets().getFirstTarget().equals(id)) { - return false; - } - return super.canTarget(id, source, game); - } - - @Override - public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { - if (source.getTargets().getFirstTarget().equals(id)) { - return false; - } - return super.canTarget(controllerId, id, source, game); - } - -} \ No newline at end of file diff --git a/Mage/src/mage/filter/predicate/mageobject/AnotherTargetPredicate.java b/Mage/src/mage/filter/predicate/mageobject/AnotherTargetPredicate.java new file mode 100644 index 0000000000..cd906f4a2a --- /dev/null +++ b/Mage/src/mage/filter/predicate/mageobject/AnotherTargetPredicate.java @@ -0,0 +1,72 @@ +/* + * 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.predicate.mageobject; + +import mage.MageObject; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.stack.StackObject; +import mage.target.Target; + +/** + * All targets that are already selected in other target definitions of the + * source are omitted To use this predicate you have to set the targetTag of all + * targets involved in the card constructor to a unique value (e.g. using 1,2,3 + * for three targets) + * + * @author LevelX2 + */ +public class AnotherTargetPredicate implements ObjectSourcePlayerPredicate> { + + private final int targetTag; + + public AnotherTargetPredicate(int targetTag) { + this.targetTag = targetTag; + } + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + StackObject source = game.getStack().getStackObject(input.getSourceId()); + if (source != null) { + for (Target target : source.getStackAbility().getTargets()) { + if (target.getTargetTag() > 0 // target is included in the target group to check + && target.getTargetTag() != targetTag // it's not the target of this predicate + && target.getTargets().contains(input.getObject().getId())) { // if the uuid already is used for another target in the group it's no allowed here + return false; + } + } + } + return true; + } + + @Override + public String toString() { + return "Another target"; + } +} diff --git a/Mage/src/mage/target/Target.java b/Mage/src/mage/target/Target.java index b6bd637b1e..80b977f4ee 100644 --- a/Mage/src/mage/target/Target.java +++ b/Mage/src/mage/target/Target.java @@ -151,4 +151,8 @@ public interface Target extends Serializable { UUID getAbilityController(); Player getTargetController(Game game, UUID playerId); + + int getTargetTag(); + + void setTargetTag(int tag); } diff --git a/Mage/src/mage/target/TargetImpl.java b/Mage/src/mage/target/TargetImpl.java index ce0a8790f4..df09789ca1 100644 --- a/Mage/src/mage/target/TargetImpl.java +++ b/Mage/src/mage/target/TargetImpl.java @@ -70,6 +70,8 @@ public abstract class TargetImpl implements Target { protected UUID targetController = null; // if null the ability controller is the targetController protected UUID abilityController = null; // only used if target controller != ability controller + protected int targetTag; // can be set if other target check is needed (AnotherTargetPredicate) + @Override public abstract TargetImpl copy(); @@ -95,6 +97,7 @@ public abstract class TargetImpl implements Target { this.notTarget = target.notTarget; this.targetController = target.targetController; this.abilityController = target.abilityController; + this.targetTag = target.targetTag; } @Override @@ -545,4 +548,20 @@ public abstract class TargetImpl implements Target { return requiredExplicitlySet; } + @Override + public int getTargetTag() { + return targetTag; + } + + /** + * Is used to be able to check, that another target is slected within the + * group of targets of the ability with a target tag > 0. + * + * @param targetTag + */ + @Override + public void setTargetTag(int targetTag) { + this.targetTag = targetTag; + } + } diff --git a/Mage/src/mage/target/TargetPermanent.java b/Mage/src/mage/target/TargetPermanent.java index 222e08d058..068bac9f0c 100644 --- a/Mage/src/mage/target/TargetPermanent.java +++ b/Mage/src/mage/target/TargetPermanent.java @@ -1,44 +1,42 @@ /* -* 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.target; import java.util.HashSet; import java.util.Set; import java.util.UUID; -import mage.constants.Zone; import mage.MageObject; import mage.abilities.Ability; +import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; - /** * * @author BetaSteward_at_googlemail.com @@ -50,7 +48,7 @@ public class TargetPermanent extends TargetObject { public TargetPermanent() { this(1, 1, new FilterPermanent(), false); } - + public TargetPermanent(FilterPermanent filter) { this(1, 1, filter, false); } @@ -88,8 +86,8 @@ public class TargetPermanent extends TargetObject { // first for protection from spells or abilities (e.g. protection from colored spells, r1753) // second for protection from sources (e.g. protection from artifacts + equip ability) if (!isNotTarget()) { - if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) || - !permanent.canBeTargetedBy(game.getObject(source.getSourceId()), controllerId, game)) { + if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) + || !permanent.canBeTargetedBy(game.getObject(source.getSourceId()), controllerId, game)) { return false; } } @@ -117,7 +115,8 @@ public class TargetPermanent extends TargetObject { /** * Checks if there are enough {@link Permanent} that can be chosen. * - * Takes into account notTarget parameter, in case it's true doesn't check for protection, shroud etc. + * Takes into account notTarget parameter, in case it's true doesn't check + * for protection, shroud etc. * * @param sourceId the target event source * @param sourceControllerId controller of the target event source @@ -132,7 +131,7 @@ public class TargetPermanent extends TargetObject { } int count = 0; MageObject targetSource = game.getObject(sourceId); - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId())) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { count++; @@ -146,9 +145,10 @@ public class TargetPermanent extends TargetObject { } /** - * Checks if there are enough {@link Permanent} that can be selected. Should not be used - * for Ability targets since this does not check for protection, shroud etc. - * + * Checks if there are enough {@link Permanent} that can be selected. Should + * not be used for Ability targets since this does not check for protection, + * shroud etc. + * * @param sourceControllerId - controller of the select event * @param game * @return - true if enough valid {@link Permanent} exist @@ -162,7 +162,7 @@ public class TargetPermanent extends TargetObject { return true; } int count = 0; - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId())) { count++; if (count >= remainingTargets) { @@ -177,7 +177,7 @@ public class TargetPermanent extends TargetObject { public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); MageObject targetSource = game.getObject(sourceId); - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, sourceId, game)) { if (!targets.containsKey(permanent.getId())) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { possibleTargets.add(permanent.getId()); @@ -190,7 +190,7 @@ public class TargetPermanent extends TargetObject { @Override public Set possibleTargets(UUID sourceControllerId, Game game) { Set possibleTargets = new HashSet<>(); - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId())) { possibleTargets.add(permanent.getId()); }