update RemoveCountersSourceCost, Gwen Stacy, and Price of Betrayal (#13941)

* update RemoveCountersSourceCost, Gwen Stacy, and Price of Betrayal

* added support for choosing multiple counters to RemoveCountersSourceCost

* changed Price of Betrayal to use player.getMultiAmount method

* added REMOVE_COUNTERS to MultiAmountType

* create common RemoveUpToAmountCountersEffect and update cards

* update default target wording on RemoveUpToAmountCountersEffect
This commit is contained in:
Jmlundeen 2025-09-07 16:50:46 -05:00 committed by GitHub
parent 432de6f9fe
commit 4dd7e963bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 270 additions and 297 deletions

View file

@ -3,19 +3,15 @@ package mage.abilities.costs.common;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.MultiAmountType;
import mage.constants.Outcome;
import mage.counters.Counter;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.RandomUtil;
import mage.util.CardUtil;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import java.util.*;
/**
* @author BetaSteward_at_googlemail.com
@ -31,6 +27,12 @@ public class RemoveCountersSourceCost extends CostImpl {
this.text = "remove a counter from {this}";
}
public RemoveCountersSourceCost(int amount) {
this.amount = amount;
this.name = "";
this.text = "remove " + CardUtil.numberToText(amount) + " counters from {this}";
}
public RemoveCountersSourceCost(Counter counter) {
this.amount = counter.getCount();
this.name = counter.getName();
@ -56,8 +58,8 @@ public class RemoveCountersSourceCost extends CostImpl {
.getCounters(game)
.values()
.stream()
.map(Counter::getCount)
.anyMatch(i -> i >= amount);
.mapToInt(Counter::getCount)
.sum() >= amount;
} else {
// specific counter
return permanent.getCounters(game).getCount(name) >= amount;
@ -71,36 +73,22 @@ public class RemoveCountersSourceCost extends CostImpl {
if (player == null || permanent == null) {
return paid;
}
String toRemove;
if (name.isEmpty()) {
Set<String> toChoose = new LinkedHashSet<>(permanent.getCounters(game).keySet());
switch (toChoose.size()) {
case 0:
return paid;
case 1:
toRemove = RandomUtil.randomFromCollection(toChoose);
break;
case 2:
Iterator<String> iterator = toChoose.iterator();
String choice1 = iterator.next();
String choice2 = iterator.next();
toRemove = player.chooseUse(
Outcome.UnboostCreature, "Choose a type of counter to remove",
null, choice1, choice2, source, game
) ? choice1 : choice2;
break;
default:
Choice choice = new ChoiceImpl(true);
choice.setChoices(toChoose);
choice.setMessage("Choose a type of counter to remove");
player.choose(Outcome.UnboostCreature, choice, game);
toRemove = choice.getChoice();
List<String> toChoose = new ArrayList<>(permanent.getCounters(game).keySet());
if (toChoose.isEmpty()) {
return paid;
} else {
List<Integer> counterList = player.getMultiAmount(Outcome.UnboostCreature, toChoose, 0, amount, amount, MultiAmountType.REMOVE_COUNTERS, game);
for (int i = 0; i < toChoose.size(); i++) {
int amountToRemove = counterList.get(i);
if (amountToRemove > 0) {
permanent.removeCounters(toChoose.get(i), amountToRemove, source, game);
}
}
paid = true;
}
} else {
toRemove = name;
}
if (permanent.getCounters(game).getCount(toRemove) >= amount) {
permanent.removeCounters(toRemove, amount, source, game);
} else if (permanent.getCounters(game).getCount(name) >= amount){
permanent.removeCounters(name, amount, source, game);
this.paid = true;
}
return paid;

View file

@ -0,0 +1,86 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.constants.MultiAmountType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.ArrayList;
import java.util.List;
public class RemoveUpToAmountCountersEffect extends OneShotEffect {
final DynamicValue amount;
public RemoveUpToAmountCountersEffect(int amount) {
super(Outcome.Neutral);
this.amount = StaticValue.get(amount);
}
public RemoveUpToAmountCountersEffect(DynamicValue amount) {
super(Outcome.Neutral);
this.amount = amount;
}
private RemoveUpToAmountCountersEffect(final RemoveUpToAmountCountersEffect effect) {
super(effect);
this.amount = effect.amount;
}
@Override
public RemoveUpToAmountCountersEffect copy() {
return new RemoveUpToAmountCountersEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
int max = this.amount.calculate(game, source, this);
// from permanent
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (permanent != null) {
List<String> toChoose = new ArrayList<>(permanent.getCounters(game).keySet());
List<Integer> counterList = controller.getMultiAmount(Outcome.UnboostCreature, toChoose, 0, 0, max, MultiAmountType.REMOVE_COUNTERS, game);
for (int i = 0; i < toChoose.size(); i++) {
int amountToRemove = counterList.get(i);
if (amountToRemove > 0) {
permanent.removeCounters(toChoose.get(i), amountToRemove, source, game);
}
}
return true;
}
// from player
Player player = game.getPlayer(source.getFirstTarget());
if (player != null) {
List<String> toChoose = new ArrayList<>(player.getCountersAsCopy().keySet());
List<Integer> counterList = controller.getMultiAmount(Outcome.Neutral, toChoose, 0, 0, max, MultiAmountType.REMOVE_COUNTERS, game);
for (int i = 0; i < toChoose.size(); i++) {
int amountToRemove = counterList.get(i);
if (amountToRemove > 0) {
player.loseCounters(toChoose.get(i), amountToRemove, source, game);
}
}
return true;
}
return false;
}
@Override
public String getText(Mode mode) {
if (staticText != null && !staticText.isEmpty()) {
return staticText;
}
return "remove up to " + CardUtil.numberToText(this.amount.toString()) + " counters from " + getTargetPointer().describeTargets(mode.getTargets(), "that permanent");
}
}

View file

@ -15,6 +15,7 @@ public class MultiAmountType {
public static final MultiAmountType P1P1 = new MultiAmountType("Add +1/+1 counters", "Distribute +1/+1 counters among creatures");
public static final MultiAmountType COUNTERS = new MultiAmountType("Choose counters", "Move counters");
public static final MultiAmountType REMOVE_COUNTERS = new MultiAmountType("Choose counters", "Remove counters");
public static final MultiAmountType CHEAT_LANDS = new MultiAmountType("Choose lands", "Add lands to your battlefield", true);
private final String title;