mirror of
https://github.com/correl/mage.git
synced 2024-12-25 11:11:16 +00:00
Fix #9649 and clean up counter effect text generation
This commit is contained in:
parent
5ec2cd0378
commit
332db3aecb
17 changed files with 117 additions and 374 deletions
|
@ -46,6 +46,10 @@ class DustOfMomentsEffect extends OneShotEffect {
|
|||
private static final FilterPermanentOrSuspendedCard filter = new FilterPermanentOrSuspendedCard();
|
||||
private final boolean remove;
|
||||
|
||||
static {
|
||||
filter.getPermanentFilter().add(CounterType.TIME.getPredicate());
|
||||
}
|
||||
|
||||
DustOfMomentsEffect(boolean remove) {
|
||||
super(Outcome.Benefit);
|
||||
this.remove = remove;
|
||||
|
|
|
@ -180,7 +180,6 @@ public class NestOfScarabsTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
/*
|
||||
|
||||
Reported bug: Nest of Scarabs not triggering off wither damage dealt by creatures such as Sickle Ripper
|
||||
*/
|
||||
@Test
|
||||
|
@ -204,4 +203,48 @@ public class NestOfScarabsTest extends CardTestPlayerBase {
|
|||
assertCounterCount(playerB, wOmens, CounterType.M1M1, 2);
|
||||
assertPermanentCount(playerA, "Insect Token", 2);
|
||||
}
|
||||
|
||||
/*
|
||||
https://github.com/magefree/mage/issues/9649
|
||||
*/
|
||||
@Test
|
||||
public void scarabs_ETBWithCountersTriggers() {
|
||||
|
||||
String hatchling = "Noxious Hatchling"; // ETB with four -1/-1 counters
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, nestScarabs);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
addCard(Zone.HAND, playerA, hatchling);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hatchling);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, nestScarabs, 1);
|
||||
assertPermanentCount(playerA, hatchling, 1);
|
||||
assertPermanentCount(playerA, "Insect Token", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void scarabs_OpponentETBWithCountersNoTriggers() {
|
||||
|
||||
String hatchling = "Noxious Hatchling"; // ETB with four -1/-1 counters
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, nestScarabs);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
addCard(Zone.HAND, playerA, hatchling);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hatchling);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerB, nestScarabs, 1);
|
||||
assertPermanentCount(playerA, hatchling, 1);
|
||||
assertPermanentCount(playerA, "Insect Token", 0);
|
||||
assertPermanentCount(playerB, "Insect Token", 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,6 +74,9 @@ public class PutCounterOnCreatureTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return false;
|
||||
}
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||
if (permanent == null) {
|
||||
permanent = game.getPermanentEntering(event.getTargetId());
|
||||
}
|
||||
if (permanent == null || !filter.match(permanent, controllerId, this, game)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import mage.counters.CounterType;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.RandomUtil;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
@ -27,19 +26,15 @@ public class RemoveCountersSourceCost extends CostImpl {
|
|||
private final String name;
|
||||
|
||||
public RemoveCountersSourceCost() {
|
||||
this((Counter) null);
|
||||
this.amount = 1;
|
||||
this.name = "";
|
||||
this.text = "remove a counter from {this}";
|
||||
}
|
||||
|
||||
public RemoveCountersSourceCost(Counter counter) {
|
||||
this.amount = counter != null ? counter.getCount() : 1;
|
||||
this.name = counter != null ? counter.getName() : "";
|
||||
this.text = new StringBuilder("remove ")
|
||||
.append((amount == 1 ? CounterType.findArticle(name) : CardUtil.numberToText(amount)))
|
||||
.append(name.isEmpty() ? "" : (' ' + name))
|
||||
.append(" counter")
|
||||
.append((amount != 1 ? "s" : ""))
|
||||
.append(" from {this}").toString();
|
||||
|
||||
this.amount = counter.getCount();
|
||||
this.name = counter.getName();
|
||||
this.text = "remove " + counter.getDescription() + " from {this}";
|
||||
}
|
||||
|
||||
private RemoveCountersSourceCost(RemoveCountersSourceCost cost) {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import mage.MageObject;
|
||||
|
@ -6,14 +5,10 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author North
|
||||
|
@ -27,7 +22,7 @@ public class AddCountersAllEffect extends OneShotEffect {
|
|||
super(Outcome.Benefit);
|
||||
this.counter = counter;
|
||||
this.filter = filter;
|
||||
setText();
|
||||
staticText = "put " + counter.getDescription() + " on each " + filter.getMessage();
|
||||
}
|
||||
|
||||
public AddCountersAllEffect(final AddCountersAllEffect effect) {
|
||||
|
@ -45,7 +40,7 @@ public class AddCountersAllEffect extends OneShotEffect {
|
|||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) {
|
||||
permanent.addCounters(counter.copy(), source.getControllerId(), source, game);
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " + counter.getCount() + ' ' + counter.getName().toLowerCase(Locale.ENGLISH)
|
||||
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts " + counter.getCount() + ' ' + counter.getName()
|
||||
+ " counter on " + permanent.getLogName());
|
||||
}
|
||||
}
|
||||
|
@ -55,18 +50,6 @@ public class AddCountersAllEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("put ");
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append(CardUtil.numberToText(counter.getCount(), "a")).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters on each ");
|
||||
} else {
|
||||
sb.append(CounterType.findArticle(counter.getName())).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter on each ");
|
||||
}
|
||||
sb.append(filter.getMessage());
|
||||
staticText = sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddCountersAllEffect copy() {
|
||||
return new AddCountersAllEffect(this);
|
||||
|
|
|
@ -6,13 +6,10 @@ import mage.abilities.dynamicvalue.common.StaticValue;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
@ -20,7 +17,6 @@ public class AddCountersAttachedEffect extends OneShotEffect {
|
|||
|
||||
private Counter counter;
|
||||
private DynamicValue amount;
|
||||
private String textEnchanted;
|
||||
|
||||
public AddCountersAttachedEffect(Counter counter, String textEnchanted) {
|
||||
this(counter, StaticValue.get(1), textEnchanted);
|
||||
|
@ -35,8 +31,7 @@ public class AddCountersAttachedEffect extends OneShotEffect {
|
|||
super(Outcome.Benefit);
|
||||
this.counter = counter.copy();
|
||||
this.amount = amount;
|
||||
this.textEnchanted = textEnchanted;
|
||||
setText();
|
||||
staticText = CardUtil.getAddRemoveCountersText(amount, counter, textEnchanted, true);
|
||||
}
|
||||
|
||||
public AddCountersAttachedEffect(final AddCountersAttachedEffect effect) {
|
||||
|
@ -45,7 +40,6 @@ public class AddCountersAttachedEffect extends OneShotEffect {
|
|||
this.counter = effect.counter.copy();
|
||||
}
|
||||
this.amount = effect.amount;
|
||||
this.textEnchanted = effect.textEnchanted;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,38 +61,8 @@ public class AddCountersAttachedEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
if (!staticText.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// put a +1/+1 counter on it
|
||||
sb.append("put ");
|
||||
boolean plural = true;
|
||||
if (amount.toString().equals("X")) {
|
||||
sb.append("X ");
|
||||
} else if (counter.getCount() > 1) {
|
||||
sb.append(CardUtil.numberToText(counter.getCount())).append(' ');
|
||||
} else {
|
||||
sb.append(CounterType.findArticle(counter.getName())).append(' ');
|
||||
plural = false;
|
||||
}
|
||||
sb.append(counter.getName().toLowerCase(Locale.ENGLISH));
|
||||
if (plural) {
|
||||
sb.append(" counters on ");
|
||||
} else {
|
||||
sb.append(" counter on ");
|
||||
}
|
||||
sb.append(textEnchanted);
|
||||
if (!amount.getMessage().isEmpty()) {
|
||||
sb.append(" for each ").append(amount.getMessage());
|
||||
}
|
||||
staticText = sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddCountersAttachedEffect copy() {
|
||||
return new AddCountersAttachedEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
@ -30,7 +28,7 @@ public class AddCountersControllerEffect extends OneShotEffect {
|
|||
super(Outcome.Benefit);
|
||||
this.counter = counter.copy();
|
||||
this.enchantedEquipped = enchantedEquipped;
|
||||
setText();
|
||||
staticText = "its controller gets " + counter.getDescription();
|
||||
}
|
||||
|
||||
public AddCountersControllerEffect(final AddCountersControllerEffect effect) {
|
||||
|
@ -66,16 +64,6 @@ public class AddCountersControllerEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
if (counter.getCount() > 1) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("its controller gets ").append(Integer.toString(counter.getCount())).append(' ').append(counter.getName()).append(" counters");
|
||||
staticText = sb.toString();
|
||||
} else {
|
||||
staticText = "its controller gets " + CounterType.findArticle(counter.getName()) + " " + counter.getName() + " counter";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddCountersControllerEffect copy() {
|
||||
return new AddCountersControllerEffect(this);
|
||||
|
|
|
@ -8,7 +8,6 @@ import mage.cards.Card;
|
|||
import mage.constants.AbilityType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
@ -16,7 +15,6 @@ import mage.util.CardUtil;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -54,7 +52,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
this.informPlayers = informPlayers;
|
||||
this.amount = amount;
|
||||
this.putOnCard = putOnCard;
|
||||
setText();
|
||||
staticText = CardUtil.getAddRemoveCountersText(amount, counter, "{this}", true);
|
||||
}
|
||||
|
||||
public AddCountersSourceEffect(final AddCountersSourceEffect effect) {
|
||||
|
@ -95,7 +93,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
if (informPlayers && !game.isSimulation()) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
game.informPlayers(player.getLogName() + " puts " + newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + card.getLogName());
|
||||
game.informPlayers(player.getLogName() + " puts " + newCounter.getCount() + ' ' + newCounter.getName() + " counter on " + card.getLogName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -124,7 +122,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
int amountAdded = permanent.getCounters(game).getCount(newCounter.getName()) - before;
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
game.informPlayers(player.getLogName() + " puts " + amountAdded + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counter on " + permanent.getLogName());
|
||||
game.informPlayers(player.getLogName() + " puts " + amountAdded + ' ' + newCounter.getName() + " counter on " + permanent.getLogName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,32 +131,8 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("put ");
|
||||
boolean plural = true;
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append(CardUtil.numberToText(counter.getCount())).append(' ');
|
||||
} else if (amount.toString().equals("X") && amount.getMessage().isEmpty()) {
|
||||
sb.append("X ");
|
||||
} else {
|
||||
sb.append(CounterType.findArticle(counter.getName())).append(' ');
|
||||
plural = false;
|
||||
}
|
||||
sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter");
|
||||
if (plural) {
|
||||
sb.append('s');
|
||||
}
|
||||
sb.append(" on {this}");
|
||||
if (!amount.getMessage().isEmpty()) {
|
||||
sb.append(" for each ").append(amount.getMessage());
|
||||
}
|
||||
staticText = sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddCountersSourceEffect copy() {
|
||||
return new AddCountersSourceEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,10 +13,8 @@ import mage.counters.CounterType;
|
|||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.target.Target;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
@ -79,17 +77,17 @@ public class AddCountersTargetEffect extends OneShotEffect {
|
|||
permanent.addCounters(newCounter, source.getControllerId(), source, game);
|
||||
affectedTargets++;
|
||||
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts "
|
||||
+ newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counters on " + permanent.getLogName());
|
||||
+ newCounter.getCount() + ' ' + newCounter.getName() + " counters on " + permanent.getLogName());
|
||||
} else if (player != null) {
|
||||
player.addCounters(newCounter, source.getControllerId(), source, game);
|
||||
affectedTargets++;
|
||||
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts "
|
||||
+ newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counters on " + player.getLogName());
|
||||
+ newCounter.getCount() + ' ' + newCounter.getName() + " counters on " + player.getLogName());
|
||||
} else if (card != null) {
|
||||
card.addCounters(newCounter, source.getControllerId(), source, game);
|
||||
affectedTargets++;
|
||||
game.informPlayers(sourceObject.getLogName() + ": " + controller.getLogName() + " puts "
|
||||
+ newCounter.getCount() + ' ' + newCounter.getName().toLowerCase(Locale.ENGLISH) + " counters on " + card.getLogName());
|
||||
+ newCounter.getCount() + ' ' + newCounter.getName() + " counters on " + card.getLogName());
|
||||
}
|
||||
}
|
||||
return affectedTargets > 0;
|
||||
|
@ -102,51 +100,11 @@ public class AddCountersTargetEffect extends OneShotEffect {
|
|||
if (!staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("put ");
|
||||
String counterName = counter.getName().toLowerCase(Locale.ENGLISH);
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append(CardUtil.numberToText(counter.getCount())).append(' ');
|
||||
} else {
|
||||
sb.append(CounterType.findArticle(counterName)).append(' ');
|
||||
}
|
||||
sb.append(counterName).append(" counter");
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append('s');
|
||||
}
|
||||
sb.append(" on ");
|
||||
|
||||
Target target = mode.getTargets().getEffectTarget(this.targetPointer);
|
||||
if (target != null) {
|
||||
if (target.getNumberOfTargets() == 0) {
|
||||
if (target.getMaxNumberOfTargets() > 1) {
|
||||
sb.append("each of ");
|
||||
}
|
||||
sb.append("up to ");
|
||||
}
|
||||
|
||||
if (target.getMaxNumberOfTargets() > 1 || target.getNumberOfTargets() == 0) {
|
||||
sb.append(CardUtil.numberToText(target.getMaxNumberOfTargets()))
|
||||
.append(" target ").append(target.getTargetName());
|
||||
} else {
|
||||
if (!target.getTargetName().startsWith("another")) {
|
||||
sb.append("target ");
|
||||
}
|
||||
sb.append(target.getTargetName());
|
||||
}
|
||||
} else {
|
||||
sb.append("that creature");
|
||||
}
|
||||
|
||||
if (!amount.getMessage().isEmpty()) {
|
||||
sb.append(" for each ").append(amount.getMessage());
|
||||
}
|
||||
return sb.toString();
|
||||
return CardUtil.getAddRemoveCountersText(amount, counter, getTargetPointer().describeTargets(mode.getTargets(), "that creature"), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddCountersTargetEffect copy() {
|
||||
return new AddCountersTargetEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.Filter;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author Gal Lerman
|
||||
*/
|
||||
public class AddRemoveAllTimeSuspentCountersEffect extends OneShotEffect {
|
||||
|
||||
private final Counter counter;
|
||||
private final Filter<Card> filter;
|
||||
private final boolean removeCounter;
|
||||
private final String actionStr;
|
||||
|
||||
public AddRemoveAllTimeSuspentCountersEffect(Counter counter, Filter<Card> filter, boolean removeCounter) {
|
||||
super(Outcome.Benefit);
|
||||
this.counter = counter;
|
||||
this.filter = filter;
|
||||
this.removeCounter = removeCounter;
|
||||
actionStr = removeCounter ? " removes " : " puts ";
|
||||
setText();
|
||||
}
|
||||
|
||||
public AddRemoveAllTimeSuspentCountersEffect(final AddRemoveAllTimeSuspentCountersEffect effect) {
|
||||
super(effect);
|
||||
this.counter = effect.counter.copy();
|
||||
this.filter = effect.filter.copy();
|
||||
this.removeCounter = effect.removeCounter;
|
||||
this.actionStr = effect.actionStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObject sourceObject = game.getObject(source);
|
||||
if (controller != null && sourceObject != null) {
|
||||
if (counter != null) {
|
||||
List<Card> permanents = new ArrayList<>(game.getBattlefield().getAllActivePermanents());
|
||||
execute(game, controller, sourceObject, source, permanents, removeCounter);
|
||||
final List<Card> exiledCards = game.getExile().getAllCards(game);
|
||||
execute(game, controller, sourceObject, source, exiledCards, removeCounter);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void execute(final Game game, final Player controller, final MageObject sourceObject, Ability source, final List<Card> cards, final boolean removeCounter) {
|
||||
for (Card card : cards) {
|
||||
if (filter.match(card, game)) {
|
||||
final String counterName = counter.getName();
|
||||
if (removeCounter) {
|
||||
final Counter existingCounterOfSameType = card.getCounters(game).get(counterName);
|
||||
final int countersToRemove = Math.min(existingCounterOfSameType.getCount(), counter.getCount());
|
||||
final Counter modifiedCounter = new Counter(counterName, countersToRemove);
|
||||
card.removeCounters(modifiedCounter, source, game);
|
||||
} else {
|
||||
card.addCounters(counter, source.getControllerId(), source, game);
|
||||
}
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(new StringBuilder(sourceObject.getName()).append(": ")
|
||||
.append(controller.getLogName()).append(actionStr)
|
||||
.append(counter.getCount()).append(' ').append(counterName.toLowerCase(Locale.ENGLISH))
|
||||
.append(" counter on ").append(card.getName()).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
final String actionsStr2 = removeCounter ? "remove " : " put ";
|
||||
sb.append(actionsStr2);
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append(Integer.toString(counter.getCount())).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters on each ");
|
||||
} else {
|
||||
sb.append(CounterType.findArticle(counter.getName())).append(' ').append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter on each ");
|
||||
}
|
||||
sb.append(filter.getMessage());
|
||||
staticText = sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddRemoveAllTimeSuspentCountersEffect copy() {
|
||||
return new AddRemoveAllTimeSuspentCountersEffect(this);
|
||||
}
|
||||
}
|
|
@ -5,10 +5,8 @@ import mage.abilities.effects.OneShotEffect;
|
|||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* @author Loki
|
||||
|
@ -20,7 +18,7 @@ public class RemoveCounterSourceEffect extends OneShotEffect {
|
|||
public RemoveCounterSourceEffect(Counter counter) {
|
||||
super(Outcome.UnboostCreature);
|
||||
this.counter = counter;
|
||||
setText();
|
||||
staticText = "remove " + counter.getDescription() + " from {this}";
|
||||
}
|
||||
|
||||
public RemoveCounterSourceEffect(RemoveCounterSourceEffect effect) {
|
||||
|
@ -63,14 +61,4 @@ public class RemoveCounterSourceEffect extends OneShotEffect {
|
|||
public RemoveCounterSourceEffect copy() {
|
||||
return new RemoveCounterSourceEffect(this);
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
if (counter.getCount() > 1) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("remove ").append(CardUtil.numberToText(counter.getCount())).append(' ').append(counter.getName()).append(" counters from {this}");
|
||||
staticText = sb.toString();
|
||||
} else {
|
||||
staticText = "remove " + CounterType.findArticle(counter.getName()) + " " + counter.getName() + " counter from {this}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,9 @@ import mage.choices.Choice;
|
|||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
@ -41,7 +39,7 @@ public class RemoveCounterTargetEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent p = game.getPermanent(targetPointer.getFirst(game, source));
|
||||
Permanent p = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (p != null) {
|
||||
Counter toRemove = (counter == null ? selectCounterType(game, source, p) : counter);
|
||||
if (toRemove != null && p.getCounters(game).getCount(toRemove.getName()) >= toRemove.getCount()) {
|
||||
|
@ -52,7 +50,7 @@ public class RemoveCounterTargetEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
Card c = game.getCard(targetPointer.getFirst(game, source));
|
||||
Card c = game.getCard(getTargetPointer().getFirst(game, source));
|
||||
if (c != null && counter != null && c.getCounters(game).getCount(counter.getName()) >= counter.getCount()) {
|
||||
c.removeCounters(counter.getName(), counter.getCount(), source, game);
|
||||
if (!game.isSimulation()) {
|
||||
|
@ -106,15 +104,9 @@ public class RemoveCounterTargetEffect extends OneShotEffect {
|
|||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
|
||||
String text = "remove ";
|
||||
if (counter == null) {
|
||||
text += "a counter";
|
||||
} else {
|
||||
text += CardUtil.numberToText(counter.getCount(), CounterType.findArticle(counter.getName())) + ' ' + counter.getName();
|
||||
text += counter.getCount() > 1 ? " counters" : " counter";
|
||||
}
|
||||
text += " from target " + (mode.getTargets().isEmpty() ? " object" : mode.getTargets().get(0).getTargetName());
|
||||
return text;
|
||||
return "remove "
|
||||
+ (counter == null ? "a counter" : counter.getDescription())
|
||||
+ " from "
|
||||
+ getTargetPointer().describeTargets(mode.getTargets(), "that creature");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
@ -7,13 +6,10 @@ import mage.abilities.dynamicvalue.common.StaticValue;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author noahg
|
||||
*/
|
||||
|
@ -21,7 +17,6 @@ public class RemoveCountersAttachedEffect extends OneShotEffect {
|
|||
|
||||
private Counter counter;
|
||||
private DynamicValue amount;
|
||||
private String textEnchanted;
|
||||
|
||||
public RemoveCountersAttachedEffect(Counter counter, String textEnchanted) {
|
||||
this(counter, StaticValue.get(0), textEnchanted);
|
||||
|
@ -36,8 +31,7 @@ public class RemoveCountersAttachedEffect extends OneShotEffect {
|
|||
super(Outcome.UnboostCreature);
|
||||
this.counter = counter.copy();
|
||||
this.amount = amount;
|
||||
this.textEnchanted = textEnchanted;
|
||||
setText();
|
||||
this.staticText = CardUtil.getAddRemoveCountersText(amount, counter, textEnchanted, false);
|
||||
}
|
||||
|
||||
public RemoveCountersAttachedEffect(final RemoveCountersAttachedEffect effect) {
|
||||
|
@ -46,7 +40,6 @@ public class RemoveCountersAttachedEffect extends OneShotEffect {
|
|||
this.counter = effect.counter.copy();
|
||||
}
|
||||
this.amount = effect.amount;
|
||||
this.textEnchanted = effect.textEnchanted;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,27 +57,8 @@ public class RemoveCountersAttachedEffect extends OneShotEffect {
|
|||
return false;
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
// put a +1/+1 counter on it
|
||||
sb.append("remove ");
|
||||
if (counter.getCount() > 1) {
|
||||
sb.append(CardUtil.numberToText(counter.getCount())).append(' ');
|
||||
sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counters from ");
|
||||
} else {
|
||||
sb.append(CounterType.findArticle(counter.getName())).append(' ');
|
||||
sb.append(counter.getName().toLowerCase(Locale.ENGLISH)).append(" counter from ");
|
||||
}
|
||||
sb.append(textEnchanted);
|
||||
if (!amount.getMessage().isEmpty()) {
|
||||
sb.append(" for each ").append(amount.getMessage());
|
||||
}
|
||||
staticText = sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoveCountersAttachedEffect copy() {
|
||||
return new RemoveCountersAttachedEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
package mage.counters;
|
||||
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -56,20 +57,6 @@ public class Counter implements Serializable {
|
|||
count += amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the {@code count} by one. Will not allow the count to be less
|
||||
* than 0. If an attempt is made to make the count be less than zero, the
|
||||
* call will be logged.
|
||||
*/
|
||||
public void decrease() {
|
||||
if (count > 0) {
|
||||
count--;
|
||||
} else {
|
||||
logger.warn("An attempt was made to set the counter '" + name
|
||||
+ "' to less than 0. Setting to 0.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decreases the {@code count} by the passed in {@code amount}. Will not
|
||||
* allow the count to be less than 0. If an attempt is made to make the
|
||||
|
@ -105,6 +92,15 @@ public class Counter implements Serializable {
|
|||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a full description of this {@link Counter}, e.g. "a +1/+1 counter" or "two -1/-1 counters"
|
||||
*
|
||||
* @return a full description of this {@link Counter}
|
||||
*/
|
||||
public String getDescription() {
|
||||
return CardUtil.numberToText(Math.max(count, 1), CounterType.findArticle(name)) + ' ' + name + (count > 1 ? " counters" : " counter");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a deep copy of this object.
|
||||
*
|
||||
|
|
|
@ -5,6 +5,9 @@ import mage.cards.Card;
|
|||
import mage.filter.predicate.Predicate;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enum for counters, names and instances.
|
||||
*
|
||||
|
@ -205,6 +208,14 @@ public enum CounterType {
|
|||
private final String article;
|
||||
private final CounterPredicate predicate;
|
||||
|
||||
private static final Map<String, CounterType> counterNameMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (CounterType counter : CounterType.values()) {
|
||||
counterNameMap.put(counter.name, counter);
|
||||
}
|
||||
}
|
||||
|
||||
CounterType(String name) {
|
||||
this(name, "aeiou".contains("" + name.charAt(0)) ? "an" : "a");
|
||||
}
|
||||
|
@ -301,12 +312,7 @@ public enum CounterType {
|
|||
}
|
||||
|
||||
public static CounterType findByName(String name) {
|
||||
for (CounterType counterType : values()) {
|
||||
if (counterType.getName().equals(name)) {
|
||||
return counterType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return counterNameMap.get(name);
|
||||
}
|
||||
|
||||
public static String findArticle(String name) {
|
||||
|
|
|
@ -5,7 +5,6 @@ import mage.constants.Outcome;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.target.targetpointer.*;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -17,8 +16,6 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class Targets extends ArrayList<Target> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Targets.class);
|
||||
|
||||
public Targets(Target... targets) {
|
||||
for (Target target : targets) {
|
||||
this.add(target);
|
||||
|
@ -147,42 +144,6 @@ public class Targets extends ArrayList<Target> {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Target getEffectTarget(TargetPointer targetPointer) {
|
||||
boolean proccessed = false;
|
||||
|
||||
if (targetPointer instanceof FirstTargetPointer) {
|
||||
proccessed = true;
|
||||
if (this.size() > 0) {
|
||||
return this.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPointer instanceof SecondTargetPointer) {
|
||||
proccessed = true;
|
||||
if (this.size() > 1) {
|
||||
return this.get(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPointer instanceof ThirdTargetPointer) {
|
||||
proccessed = true;
|
||||
if (this.size() > 2) {
|
||||
return this.get(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetPointer instanceof FixedTarget || targetPointer instanceof FixedTargets) {
|
||||
// fixed target = direct ID, you can't find target type and description
|
||||
proccessed = true;
|
||||
}
|
||||
|
||||
if (!proccessed) {
|
||||
logger.error("Unknown target pointer " + (targetPointer != null ? targetPointer : "null"), new Throwable());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Targets copy() {
|
||||
return new Targets(this);
|
||||
}
|
||||
|
|
|
@ -870,10 +870,10 @@ public final class CardUtil {
|
|||
String p = power.toString();
|
||||
String t = toughness.toString();
|
||||
if (!p.startsWith("-")) {
|
||||
p = (t.startsWith("-") && p.equals("0") ? "-" : "+") + p;
|
||||
p = t.startsWith("-") && p.equals("0") ? "-0" : "+" + p;
|
||||
}
|
||||
if (!t.startsWith("-")) {
|
||||
t = (p.startsWith("-") && t.equals("0") ? "-" : "+") + t;
|
||||
t = p.startsWith("-") && t.equals("0") ? "-0" : "+" + t;
|
||||
}
|
||||
return p + "/" + t;
|
||||
}
|
||||
|
@ -889,7 +889,7 @@ public final class CardUtil {
|
|||
if (duration != Duration.EndOfGame) {
|
||||
String d = duration.toString();
|
||||
if (!d.isEmpty()) {
|
||||
sb.append(" ").append(d);
|
||||
sb.append(' ').append(d);
|
||||
}
|
||||
}
|
||||
String message = power.getMessage();
|
||||
|
@ -912,6 +912,21 @@ public final class CardUtil {
|
|||
return Outcome.BoostCreature;
|
||||
}
|
||||
|
||||
public static String getAddRemoveCountersText(DynamicValue amount, Counter counter, String description, boolean add) {
|
||||
StringBuilder sb = new StringBuilder(add ? "put " : "remove ");
|
||||
boolean xValue = amount.toString().equals("X");
|
||||
if (xValue) {
|
||||
sb.append("X ").append(counter.getName()).append(" counters");
|
||||
} else {
|
||||
sb.append(counter.getDescription());
|
||||
}
|
||||
sb.append(add ? " on " : " from ").append(description);
|
||||
if (!amount.getMessage().isEmpty()) {
|
||||
sb.append(xValue ? ", where X is " : " for each ").append(amount.getMessage());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static boolean isFusedPartAbility(Ability ability, Game game) {
|
||||
// TODO: does it work fine with copies of spells on stack?
|
||||
if (!(ability instanceof SpellAbility)) {
|
||||
|
|
Loading…
Reference in a new issue