Remove custom multitarget handling from DestroyTargetEffect (use EachTargetPointer instead)

This commit is contained in:
Alex W. Jackson 2022-09-04 07:04:46 -04:00
parent addfd5166e
commit e3b8a813e5
24 changed files with 124 additions and 217 deletions

View file

@ -1,73 +0,0 @@
package mage.abilities.effects.common;
import java.util.Iterator;
import java.util.UUID;
import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class DestroyMultiTargetEffect extends OneShotEffect {
protected boolean noRegen;
public DestroyMultiTargetEffect() {
this(false);
}
public DestroyMultiTargetEffect(boolean noRegen) {
super(Outcome.DestroyPermanent);
this.noRegen = noRegen;
}
public DestroyMultiTargetEffect(final DestroyMultiTargetEffect effect) {
super(effect);
this.noRegen = effect.noRegen;
}
@Override
public DestroyMultiTargetEffect copy() {
return new DestroyMultiTargetEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
int affectedTargets = 0;
for (Target target: source.getTargets()) {
for (UUID permanentId: target.getTargets()) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null) {
permanent.destroy(source, game, noRegen);
affectedTargets++;
}
}
}
return affectedTargets > 0;
}
@Override
public String getText(Mode mode) {
StringBuilder sb = new StringBuilder();
sb.append("Destroy ");
Iterator<Target> iterator = mode.getTargets().iterator();
while (iterator.hasNext()) {
Target target = iterator.next();
if (target.getNumberOfTargets() > 1) {
sb.append(target.getNumberOfTargets()).append(' ');
}
sb.append("target ").append(target.getTargetName());
if (iterator.hasNext()) {
sb.append(" and ");
}
}
return sb.toString();
}
}

View file

@ -19,7 +19,6 @@ import java.util.UUID;
public class DestroyTargetEffect extends OneShotEffect {
protected boolean noRegen;
protected boolean multitargetHandling;
public DestroyTargetEffect() {
this(false);
@ -30,24 +29,18 @@ public class DestroyTargetEffect extends OneShotEffect {
}
public DestroyTargetEffect(boolean noRegen) {
this(noRegen, false);
super(Outcome.DestroyPermanent);
this.noRegen = noRegen;
}
public DestroyTargetEffect(String ruleText, boolean noRegen) {
this(noRegen, false);
this(noRegen);
staticText = ruleText;
}
public DestroyTargetEffect(boolean noRegen, boolean multitargetHandling) {
super(Outcome.Detriment);
this.noRegen = noRegen;
this.multitargetHandling = multitargetHandling;
}
public DestroyTargetEffect(final DestroyTargetEffect effect) {
super(effect);
this.noRegen = effect.noRegen;
this.multitargetHandling = effect.multitargetHandling;
}
@Override
@ -58,29 +51,13 @@ public class DestroyTargetEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
int affectedTargets = 0;
if (multitargetHandling
&& source.getTargets().size() > 1
&& targetPointer instanceof FirstTargetPointer) { // Decimate
for (Target target : source.getTargets()) {
for (UUID permanentId : target.getTargets()) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null
&& permanent.isPhasedIn()
&& !permanent.isPhasedOutIndirectly()) {
permanent.destroy(source, game, noRegen);
affectedTargets++;
}
}
}
} else {
for (UUID permanentId : targetPointer.getTargets(game, source)) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null
&& permanent.isPhasedIn()
&& !permanent.isPhasedOutIndirectly()) {
permanent.destroy(source, game, noRegen);
affectedTargets++;
}
for (UUID permanentId : targetPointer.getTargets(game, source)) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null
&& permanent.isPhasedIn()
&& !permanent.isPhasedOutIndirectly()) {
permanent.destroy(source, game, noRegen);
affectedTargets++;
}
}
return affectedTargets > 0;
@ -91,36 +68,11 @@ public class DestroyTargetEffect extends OneShotEffect {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
StringBuilder sb = new StringBuilder();
if (mode.getTargets().isEmpty()) {
sb.append("destroy that creature"); //TODO add possibility to specify text with targetPointer usage
} else {
Target target;
if (targetPointer instanceof SecondTargetPointer && mode.getTargets().size() > 1) {
target = mode.getTargets().get(1);
} else {
target = mode.getTargets().get(0);
}
if (target.getNumberOfTargets() == 1) {
String targetName = target.getTargetName();
sb.append("destroy ");
if (!targetName.startsWith("another")) {
sb.append("target ");
}
sb.append(targetName);
} else {
if (target.getMaxNumberOfTargets() == target.getMinNumberOfTargets()) {
sb.append("destroy ").append(CardUtil.numberToText(target.getNumberOfTargets()));
} else {
sb.append("destroy up to ").append(CardUtil.numberToText(target.getMaxNumberOfTargets()));
}
sb.append(" target ").append(target.getTargetName());
}
}
StringBuilder sb = new StringBuilder("destroy " + getTargetPointer().describeTargets(mode.getTargets(), "that creature"));
if (noRegen) {
sb.append(". It can't be regenerated");
sb.append(getTargetPointer().isPlural(mode.getTargets()) ? ". They" : ". It");
sb.append(" can't be regenerated");
}
return sb.toString();
}
}

View file

@ -7,6 +7,10 @@ import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author awjackson
*/
public enum AttachedOrShareCreatureTypePredicate implements ObjectSourcePlayerPredicate<Permanent> {
instance;

View file

@ -7,6 +7,8 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.Target;
import mage.target.Targets;
import mage.util.CardUtil;
import java.util.*;
import java.util.stream.Collectors;
@ -129,4 +131,17 @@ public class EachTargetPointer extends TargetPointerImpl {
}
return permanent;
}
@Override
public String describeTargets(Targets targets, String defaultDescription) {
if (targets.isEmpty()) {
return defaultDescription;
}
return CardUtil.concatWithAnd(targets.stream().map(Target::getDescription).collect(Collectors.toList()));
}
@Override
public boolean isPlural(Targets targets) {
return true;
}
}

View file

@ -123,4 +123,9 @@ public class FirstTargetPointer extends TargetPointerImpl {
public String describeTargets(Targets targets, String defaultDescription) {
return targets.isEmpty() ? defaultDescription : targets.get(0).getDescription();
}
@Override
public boolean isPlural(Targets targets) {
return !targets.isEmpty() && targets.get(0).getMaxNumberOfTargets() > 1;
}
}

View file

@ -120,4 +120,9 @@ public class SecondTargetPointer extends TargetPointerImpl {
public String describeTargets(Targets targets, String defaultDescription) {
return targets.size() < 2 ? defaultDescription : targets.get(1).getDescription();
}
@Override
public boolean isPlural(Targets targets) {
return targets.size() > 1 && targets.get(1).getMaxNumberOfTargets() > 1;
}
}

View file

@ -39,15 +39,20 @@ public interface TargetPointer extends Serializable, Copyable<TargetPointer> {
Permanent getFirstTargetPermanentOrLKI(Game game, Ability source);
/**
* Returns description of targets for ability text
* Describes the appropriate subset of targets for ability text.
*
* @param targets
* @param defaultText
* @return
*/
default String describeTargets(Targets targets, String defaultDescription) {
return defaultDescription;
}
default boolean isPlural(Targets targets) {
return false;
}
/**
* Store text to target pointer (usefull to keep data for specific trigger, e.g. selected target name for rules)
*

View file

@ -124,4 +124,9 @@ public class ThirdTargetPointer extends TargetPointerImpl {
public String describeTargets(Targets targets, String defaultDescription) {
return targets.size() < 3 ? defaultDescription : targets.get(2).getDescription();
}
@Override
public boolean isPlural(Targets targets) {
return targets.size() > 2 && targets.get(2).getMaxNumberOfTargets() > 1;
}
}