Genericize Target Adjusters (#12107)

* Create generic X MV adjuster

* Update XTargetsAdjuster

* Create DynamicValueTargetsAdjuster to replace VerseCounterAdjuster

* Convert XTargetsAdjuster to use DynamicValueTargetsAdjuster

* Genericize MV target adjuster

* Converting custom classes for A and B cards, fix Back in Town to only target creature cards

* Add Power and Toughness target adjusters, C cards

* Set up and use Monstrosity X DynamicValue

* Move Scry amount dynamic value to common, add D and E cards

* Convert F to I cards

* Cards K-M

* N, O cards

* Cards O-R

* S cards (check Scrap Welder)

* Cards T - Z

* Rename target adjusters

* Add filter messages, don't add 0 count targets

* Clear blueprint targets (just in case), fix target names, Temporal Firestorm is not target

* Requested renames

* Aether Burst is "up to"

* Review fixes

* Add new cards, add source to dynamic value calculation
This commit is contained in:
ssk97 2024-05-02 22:12:52 -07:00 committed by GitHub
parent 5e8aee48b3
commit 32bf3eb9bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
161 changed files with 949 additions and 2567 deletions

View file

@ -0,0 +1,41 @@
package mage.abilities.dynamicvalue.common;
import mage.abilities.Ability;
import mage.abilities.common.BecomesMonstrousSourceTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.game.Game;
/**
* Monstrosity X
*
* @author notgreat
*/
public enum GetMonstrosityXValue implements DynamicValue {
instance;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
if (sourceAbility instanceof BecomesMonstrousSourceTriggeredAbility) {
return ((BecomesMonstrousSourceTriggeredAbility) sourceAbility).getMonstrosityValue();
} else {
throw new IllegalArgumentException("Trying to get Monstrosity X value with non-Monstrosity sourceAbility "+sourceAbility.getClass().getName());
}
}
@Override
public GetMonstrosityXValue copy() {
return GetMonstrosityXValue.instance;
}
@Override
public String toString() {
return "X";
}
@Override
public String getMessage() {
return "";
}
}

View file

@ -0,0 +1,39 @@
package mage.abilities.dynamicvalue.common;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.game.Game;
/**
* @author notgreat
*/
public enum GetScryAmount implements DynamicValue {
instance;
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
return sourceAbility
.getEffects()
.stream()
.mapToInt(thisEffect -> (Integer) thisEffect.getValue("amount"))
.findFirst()
.orElse(0);
}
@Override
public GetScryAmount copy() {
return GetScryAmount.instance;
}
@Override
public String getMessage() {
return "card looked at while scrying this way";
}
@Override
public String toString() {
return "1";
}
}

View file

@ -10,7 +10,7 @@ import mage.constants.SubType;
public final class TuskenRaiderToken extends TokenImpl {
public TuskenRaiderToken() {
super("Tusken Raider Token", "white Tusken Raider creature token");
super("Tusken Raider Token", "1/1 white Tusken Raider creature token");
this.power = new MageInt(1);
this.toughness = new MageInt(1);
cardType.add(CardType.CREATURE);

View file

@ -38,7 +38,7 @@ public class EachOpponentPermanentTargetsAdjuster implements TargetAdjuster {
Filter<Permanent> filter = newTarget.getFilter();
filter.add(new ControllerIdPredicate(opponentId));
if (!newTarget.possibleTargets(ability.getControllerId(), ability, game).isEmpty()) {
filter.setMessage(filter.getMessage() + " controlled by " + opponent.getLogName());
newTarget.setTargetName(filter.getMessage() + " controlled by " + opponent.getLogName());
ability.addTarget(newTarget);
}
}

View file

@ -0,0 +1,45 @@
package mage.target.targetadjustment;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.constants.ComparisonType;
import mage.filter.Filter;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.target.Target;
/**
* @author TheElk801, notgreat
*/
public class ManaValueTargetAdjuster implements TargetAdjuster {
private Target blueprintTarget = null;
private final DynamicValue dynamicValue;
private final ComparisonType comparison;
/**
* Modifies the target to also require a mana value that satisfies the comparison to the dynamic value.
*
* @param value The value to be compared against
* @param compare Which comparison to use
*/
public ManaValueTargetAdjuster(DynamicValue value, ComparisonType compare) {
this.dynamicValue = value;
this.comparison = compare;
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (blueprintTarget == null) {
blueprintTarget = ability.getTargets().get(0).copy();
blueprintTarget.clearChosen();
}
Target newTarget = blueprintTarget.copy();
int amount = dynamicValue.calculate(game, ability, ability.getEffects().get(0));
Filter<MageObject> filter = newTarget.getFilter();
filter.add(new ManaValuePredicate(comparison, amount));
newTarget.setTargetName(filter.getMessage() + " (Mana Value " + comparison + " " + amount + ")");
ability.getTargets().clear();
ability.addTarget(newTarget);
}
}

View file

@ -0,0 +1,50 @@
package mage.target.targetadjustment;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.constants.ComparisonType;
import mage.filter.Filter;
import mage.filter.predicate.mageobject.PowerPredicate;
import mage.game.Game;
import mage.target.Target;
/**
* @author TheElk801, notgreat
*/
public class PowerTargetAdjuster implements TargetAdjuster {
private Target blueprintTarget = null;
private final DynamicValue dynamicValue;
private final ComparisonType comparison;
/**
* Modifies the target to also require a power that satisfies the comparison to the dynamic value.
*
* @param value The value to be compared against
* @param compare Which comparison to use
*/
public PowerTargetAdjuster(DynamicValue value, ComparisonType compare) {
this.dynamicValue = value;
this.comparison = compare;
}
public PowerTargetAdjuster(ComparisonType comparison) {
this(ManacostVariableValue.REGULAR, comparison);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (blueprintTarget == null) {
blueprintTarget = ability.getTargets().get(0).copy();
blueprintTarget.clearChosen();
}
Target newTarget = blueprintTarget.copy();
int amount = dynamicValue.calculate(game, ability, ability.getEffects().get(0));
Filter<MageObject> filter = newTarget.getFilter();
filter.add(new PowerPredicate(comparison, amount));
newTarget.setTargetName(filter.getMessage() + " (Power " + comparison + " " + amount + ")");
ability.getTargets().clear();
ability.addTarget(newTarget);
}
}

View file

@ -0,0 +1,48 @@
package mage.target.targetadjustment;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.filter.Filter;
import mage.game.Game;
import mage.target.Target;
/**
* @author TheElk801, notgreat
*/
public class TargetsCountAdjuster implements TargetAdjuster {
private Target blueprintTarget = null;
private final DynamicValue dynamicValue;
/**
* Modifies the target to be X targets, where X is the dynamic value.
* If the ability's target has min targets of 0, it's treated as "up to X targets".
* Otherwise, it's exactly "X targets".
*
* @param value The number of targets
*/
public TargetsCountAdjuster(DynamicValue value) {
this.dynamicValue = value;
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (blueprintTarget == null) {
blueprintTarget = ability.getTargets().get(0).copy();
blueprintTarget.clearChosen();
}
Target newTarget = blueprintTarget.copy();
int count = dynamicValue.calculate(game, ability, ability.getEffects().get(0));
newTarget.setMaxNumberOfTargets(count);
Filter filter = newTarget.getFilter();
if (blueprintTarget.getMinNumberOfTargets() != 0) {
newTarget.setMinNumberOfTargets(count);
newTarget.setTargetName(filter.getMessage() + " (" + count + " targets)");
} else {
newTarget.setTargetName(filter.getMessage() + " (up to " + count + " targets)");
}
ability.getTargets().clear();
if (count > 0) {
ability.addTarget(newTarget);
}
}
}

View file

@ -0,0 +1,50 @@
package mage.target.targetadjustment;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.constants.ComparisonType;
import mage.filter.Filter;
import mage.filter.predicate.mageobject.ToughnessPredicate;
import mage.game.Game;
import mage.target.Target;
/**
* @author TheElk801, notgreat
*/
public class ToughnessTargetAdjuster implements TargetAdjuster {
private Target blueprintTarget = null;
private final DynamicValue dynamicValue;
private final ComparisonType comparison;
/**
* Modifies the target to also require a toughness that satisfies the comparison to the dynamic value.
*
* @param value The value to be compared against
* @param compare Which comparison to use
*/
public ToughnessTargetAdjuster(DynamicValue value, ComparisonType compare) {
this.dynamicValue = value;
this.comparison = compare;
}
public ToughnessTargetAdjuster(ComparisonType comparison) {
this(ManacostVariableValue.REGULAR, comparison);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (blueprintTarget == null) {
blueprintTarget = ability.getTargets().get(0).copy();
blueprintTarget.clearChosen();
}
Target newTarget = blueprintTarget.copy();
int amount = dynamicValue.calculate(game, ability, ability.getEffects().get(0));
Filter<MageObject> filter = newTarget.getFilter();
filter.add(new ToughnessPredicate(comparison, amount));
newTarget.setTargetName(filter.getMessage() + " (Toughness " + comparison + " " + amount + ")");
ability.getTargets().clear();
ability.addTarget(newTarget);
}
}

View file

@ -1,27 +0,0 @@
package mage.target.targetadjustment;
import mage.abilities.Ability;
import mage.counters.CounterType;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
/**
*
* @author TheElk801
*/
public enum VerseCounterAdjuster implements TargetAdjuster {
instance;
@Override
public void adjustTargets(Ability ability, Game game) {
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(ability.getSourceId());
if (sourcePermanent != null) {
int xValue = sourcePermanent.getCounters(game).getCount(CounterType.VERSE);
FilterPermanent permanentFilter = ((TargetPermanent) ability.getTargets().get(0)).getFilter();
ability.getTargets().clear();
ability.addTarget(new TargetPermanent(0, xValue, permanentFilter, false));
}
}
}

View file

@ -1,27 +0,0 @@
package mage.target.targetadjustment;
import mage.abilities.Ability;
import mage.constants.ComparisonType;
import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.target.TargetCard;
import mage.target.common.TargetCardInGraveyard;
/**
*
* @author TheElk801
*/
public enum XCMCGraveyardAdjuster implements TargetAdjuster {
instance;
@Override
public void adjustTargets(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
FilterCard filterCard = ((TargetCard) ability.getTargets().get(0)).getFilter().copy();
filterCard.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, xValue));
filterCard.setMessage(filterCard.getMessage().replace('X', (char) xValue));
ability.getTargets().clear();
ability.getTargets().add(new TargetCardInGraveyard(filterCard));
}
}

View file

@ -1,28 +0,0 @@
package mage.target.targetadjustment;
import mage.abilities.Ability;
import mage.constants.ComparisonType;
import mage.filter.FilterPermanent;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.target.TargetPermanent;
/**
*
* @author TheElk801
*/
public enum XCMCPermanentAdjuster implements TargetAdjuster {
instance;
@Override
public void adjustTargets(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
TargetPermanent oldTargetPermanent = (TargetPermanent) ability.getTargets().get(0);
int minTargets = oldTargetPermanent.getMinNumberOfTargets();
int maxTargets = oldTargetPermanent.getMaxNumberOfTargets();
FilterPermanent permanentFilter = oldTargetPermanent.getFilter().copy();
permanentFilter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, xValue));
ability.getTargets().clear();
ability.getTargets().add(new TargetPermanent(minTargets, maxTargets, permanentFilter, false));
}
}

View file

@ -0,0 +1,18 @@
package mage.target.targetadjustment;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
import mage.constants.ComparisonType;
/**
* @author notgreat
*/
public class XManaValueTargetAdjuster extends ManaValueTargetAdjuster {
public XManaValueTargetAdjuster() {
super(ManacostVariableValue.REGULAR, ComparisonType.EQUAL_TO);
}
public XManaValueTargetAdjuster(ComparisonType comparison) {
super(ManacostVariableValue.REGULAR, comparison);
}
}

View file

@ -1,22 +0,0 @@
package mage.target.targetadjustment;
import mage.abilities.Ability;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.target.TargetPermanent;
/**
*
* @author TheElk801
*/
public enum XTargetsAdjuster implements TargetAdjuster {
instance;
@Override
public void adjustTargets(Ability ability, Game game) {
int xValue = ability.getManaCostsToPay().getX();
FilterPermanent permanentFilter = ((TargetPermanent) ability.getTargets().get(0)).getFilter();
ability.getTargets().clear();
ability.addTarget(new TargetPermanent(xValue, permanentFilter));
}
}

View file

@ -0,0 +1,13 @@
package mage.target.targetadjustment;
import mage.abilities.dynamicvalue.common.ManacostVariableValue;
/**
* @author notgreat
*/
public class XTargetsCountAdjuster extends TargetsCountAdjuster {
public XTargetsCountAdjuster() {
super(ManacostVariableValue.REGULAR);
}
}