mirror of
https://github.com/magefree/mage.git
synced 2026-01-09 12:22:10 -08:00
prevent direct access of Player->counters ; some cleanup on counter removal effects ; implement [MH3] Izzet Generatorium (#12314)
This commit is contained in:
parent
8d02ff14ff
commit
20b7a115da
110 changed files with 895 additions and 646 deletions
|
|
@ -13,6 +13,10 @@ import mage.constants.Zone;
|
|||
*/
|
||||
public class ActivateIfConditionActivatedAbility extends ActivatedAbilityImpl {
|
||||
|
||||
public ActivateIfConditionActivatedAbility(Effect effect, Cost cost, Condition condition) {
|
||||
this(Zone.BATTLEFIELD, effect, cost, condition, TimingRule.INSTANT);
|
||||
}
|
||||
|
||||
public ActivateIfConditionActivatedAbility(Zone zone, Effect effect, Cost cost, Condition condition) {
|
||||
this(zone, effect, cost, condition, TimingRule.INSTANT);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import java.util.Objects;
|
|||
/**
|
||||
* A condition which checks whether any players being attacked are poisoned
|
||||
* (have one or more poison counters on them)
|
||||
*
|
||||
*
|
||||
* @author alexander-novo
|
||||
*/
|
||||
public enum AttackedPlayersPoisonedCondition implements Condition {
|
||||
|
|
@ -27,7 +27,7 @@ public enum AttackedPlayersPoisonedCondition implements Condition {
|
|||
.distinct()
|
||||
.map(game::getPlayer)
|
||||
.filter(Objects::nonNull)
|
||||
.anyMatch(player -> player.getCounters().containsKey(CounterType.POISON));
|
||||
.anyMatch(player -> player.getCountersCount(CounterType.POISON) > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import mage.abilities.hint.ConditionHint;
|
|||
import mage.abilities.hint.Hint;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
|
@ -24,8 +23,7 @@ public enum CorruptedCondition implements Condition {
|
|||
.stream()
|
||||
.map(game::getPlayer)
|
||||
.filter(Objects::nonNull)
|
||||
.map(Player::getCounters)
|
||||
.anyMatch(counters -> counters.getCount(CounterType.POISON) >= 3);
|
||||
.anyMatch(player -> player.getCountersCount(CounterType.POISON) >= 3);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import mage.util.CardUtil;
|
|||
|
||||
import java.util.UUID;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author emerald000
|
||||
*/
|
||||
|
|
@ -31,14 +33,14 @@ public class PayEnergyCost extends CostImpl {
|
|||
@Override
|
||||
public boolean canPay(Ability ability, Ability source, UUID controllerId, Game game) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
return player != null && player.getCounters().getCount(CounterType.ENERGY) >= amount;
|
||||
return player != null && player.getCountersCount(CounterType.ENERGY) >= amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player != null && player.getCounters().getCount(CounterType.ENERGY) >= amount) {
|
||||
player.getCounters().removeCounter(CounterType.ENERGY, amount);
|
||||
if (player != null && player.getCountersCount(CounterType.ENERGY) >= amount) {
|
||||
player.loseCounters(CounterType.ENERGY.getName(), amount, source, game);
|
||||
paid = true;
|
||||
}
|
||||
return paid;
|
||||
|
|
|
|||
|
|
@ -38,10 +38,7 @@ public class RemoveAllCountersSourceCost extends CostImpl {
|
|||
public boolean pay(Ability ability, Game game, Ability source, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Permanent permanent = game.getPermanent(ability.getSourceId());
|
||||
if (permanent != null) {
|
||||
this.removedCounters = permanent.getCounters(game).getCount(counterType);
|
||||
if (this.removedCounters > 0) {
|
||||
permanent.removeCounters(counterType.createInstance(this.removedCounters), source, game);
|
||||
}
|
||||
this.removedCounters = permanent.removeAllCounters(counterType.getName(), source, game);
|
||||
}
|
||||
this.paid = true;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public enum OpponentsPoisonCountersCount implements DynamicValue {
|
|||
for (UUID playerUUID : playerList) {
|
||||
Player player = game.getPlayer(playerUUID);
|
||||
if (player != null) {
|
||||
amount += player.getCounters().getCount(CounterType.POISON);
|
||||
amount += player.getCountersCount(CounterType.POISON);
|
||||
}
|
||||
}
|
||||
return amount;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public enum SourceControllerCountersCount implements DynamicValue {
|
|||
int amount = 0;
|
||||
Player player = game.getPlayer(sourceAbility.getControllerId());
|
||||
if (player != null) {
|
||||
amount = player.getCounters().getCount(counterType);
|
||||
amount = player.getCountersCount(counterType);
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ public class RemoveAllCountersSourceEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (sourcePermanent != null) {
|
||||
int count = sourcePermanent.getCounters(game).getCount(counterType);
|
||||
sourcePermanent.removeCounters(counterType.getName(), count, source, game);
|
||||
sourcePermanent.removeAllCounters(counterType.getName(), source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ public class ProliferateEffect extends OneShotEffect {
|
|||
if (player == null) {
|
||||
continue;
|
||||
}
|
||||
for (Counter counter : player.getCounters().values()) {
|
||||
for (Counter counter : player.getCountersAsCopy().values()) {
|
||||
// TODO: this does not work with ability counters that are not explicitly in CounterType. Like the Hexproof from XXX counters from Indominus Rex, Alpha
|
||||
Counter newCounter = CounterType.findByName(counter.getName()).createInstance();
|
||||
if (player.addCounters(newCounter, source.getControllerId(), source, game)) {
|
||||
game.informPlayers(player.getLogName() + " had " + newCounter.getDescription() + " added to them.");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* Removes all counters (optionally of a given counter type) from the target permanent.
|
||||
*
|
||||
* @author MTGfan
|
||||
*/
|
||||
public class RemoveAllCountersPermanentTargetEffect extends OneShotEffect {
|
||||
|
||||
private final CounterType counterType; // If not null, remove counters of that type only.
|
||||
|
||||
public RemoveAllCountersPermanentTargetEffect() {
|
||||
this((CounterType) null);
|
||||
}
|
||||
|
||||
public RemoveAllCountersPermanentTargetEffect(CounterType counterType) {
|
||||
super(Outcome.Neutral);
|
||||
this.counterType = counterType;
|
||||
staticText = "remove all " + (counterType == null ? "" : counterType.getName() + " ") + "counters from it.";
|
||||
}
|
||||
|
||||
public RemoveAllCountersPermanentTargetEffect(RemoveAllCountersPermanentTargetEffect effect) {
|
||||
super(effect);
|
||||
this.counterType = effect.counterType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (permanent != null) {
|
||||
if (counterType == null) {
|
||||
permanent.removeAllCounters(source, game);
|
||||
} else {
|
||||
permanent.removeAllCounters(counterType.getName(), source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoveAllCountersPermanentTargetEffect copy() {
|
||||
return new RemoveAllCountersPermanentTargetEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
package mage.abilities.effects.common.counter;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.constants.Outcome;
|
||||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author MTGfan
|
||||
*/
|
||||
public class RemoveAllCountersTargetEffect extends OneShotEffect {
|
||||
|
||||
private final CounterType counterType;
|
||||
|
||||
public RemoveAllCountersTargetEffect(CounterType counterType) {
|
||||
super(Outcome.Neutral);
|
||||
this.counterType = counterType;
|
||||
staticText = "remove all " + counterType.getName() + " counters from it.";
|
||||
}
|
||||
|
||||
public RemoveAllCountersTargetEffect(RemoveAllCountersTargetEffect effect) {
|
||||
super(effect);
|
||||
this.counterType = effect.counterType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if(permanent != null) {
|
||||
int count = permanent.getCounters(game).getCount(counterType);
|
||||
permanent.removeCounters(counterType.getName(), count, source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoveAllCountersTargetEffect copy() {
|
||||
return new RemoveAllCountersTargetEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -88,11 +88,13 @@ public interface Card extends MageObject, Ownerable {
|
|||
|
||||
/**
|
||||
* Is this an extra deck card? (such as contraptions and attractions)
|
||||
*
|
||||
* @return true if this is an extra deck card, false otherwise
|
||||
*/
|
||||
default boolean isExtraDeckCard() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void assignNewId();
|
||||
|
||||
void addInfo(String key, String value, Game game);
|
||||
|
|
@ -168,17 +170,64 @@ public interface Card extends MageObject, Ownerable {
|
|||
|
||||
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters);
|
||||
|
||||
default void removeCounters(String name, int amount, Ability source, Game game){
|
||||
removeCounters(name, amount, source, game, false);
|
||||
/**
|
||||
* Remove {@param amount} counters of the specified kind.
|
||||
*/
|
||||
default void removeCounters(String counterName, int amount, Ability source, Game game) {
|
||||
removeCounters(counterName, amount, source, game, false);
|
||||
}
|
||||
|
||||
void removeCounters(String name, int amount, Ability source, Game game, boolean damage);
|
||||
/**
|
||||
* Remove {@param amount} counters of the specified kind.
|
||||
*
|
||||
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
|
||||
*/
|
||||
void removeCounters(String counterName, int amount, Ability source, Game game, boolean isDamage);
|
||||
|
||||
default void removeCounters(Counter counter, Ability source, Game game) {
|
||||
removeCounters(counter, source, game, false);
|
||||
}
|
||||
|
||||
void removeCounters(Counter counter, Ability source, Game game, boolean damage);
|
||||
/**
|
||||
* Remove all counters of any kind.
|
||||
*
|
||||
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
|
||||
*/
|
||||
void removeCounters(Counter counter, Ability source, Game game, boolean isDamage);
|
||||
|
||||
/**
|
||||
* Remove all counters of any kind.
|
||||
*
|
||||
* @return the amount of counters removed this way.
|
||||
*/
|
||||
default int removeAllCounters(Ability source, Game game) {
|
||||
return removeAllCounters(source, game, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all counters of any kind.
|
||||
*
|
||||
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
|
||||
* @return the amount of counters removed this way.
|
||||
*/
|
||||
int removeAllCounters(Ability source, Game game, boolean isDamage);
|
||||
|
||||
/**
|
||||
* Remove all counters of a specific kind. Return the amount of counters removed this way.
|
||||
*
|
||||
* @return the amount of counters removed this way.
|
||||
*/
|
||||
default int removeAllCounters(String counterName, Ability source, Game game) {
|
||||
return removeAllCounters(counterName, source, game, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all counters of a specific kind. Return the amount of counters removed this way.
|
||||
*
|
||||
* @param isDamage if the counter removal is a result of being damaged (e.g. for Deification to work)
|
||||
* @return the amount of counters removed this way.
|
||||
*/
|
||||
int removeAllCounters(String counterName, Ability source, Game game, boolean isDamage);
|
||||
|
||||
@Override
|
||||
Card copy();
|
||||
|
|
|
|||
|
|
@ -803,39 +803,40 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeCounters(String name, int amount, Ability source, Game game, boolean isDamage) {
|
||||
public void removeCounters(String counterName, int amount, Ability source, Game game, boolean isDamage) {
|
||||
|
||||
if (amount <= 0){
|
||||
if (amount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getCounters(game).getCount(name) <= 0){
|
||||
if (getCounters(game).getCount(counterName) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameEvent removeCountersEvent = new RemoveCountersEvent(name, this, source, amount, isDamage);
|
||||
if (game.replaceEvent(removeCountersEvent)){
|
||||
GameEvent removeCountersEvent = new RemoveCountersEvent(counterName, this, source, amount, isDamage);
|
||||
if (game.replaceEvent(removeCountersEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int finalAmount = 0;
|
||||
for (int i = 0; i < removeCountersEvent.getAmount(); i++) {
|
||||
|
||||
GameEvent event = new RemoveCounterEvent(name, this, source, isDamage);
|
||||
if (game.replaceEvent(event)){
|
||||
GameEvent event = new RemoveCounterEvent(counterName, this, source, isDamage);
|
||||
if (game.replaceEvent(event)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!getCounters(game).removeCounter(name, 1)) {
|
||||
if (!getCounters(game).removeCounter(counterName, 1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
event = new CounterRemovedEvent(name, this, source, isDamage);
|
||||
event = new CounterRemovedEvent(counterName, this, source, isDamage);
|
||||
game.fireEvent(event);
|
||||
|
||||
finalAmount++;
|
||||
}
|
||||
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, isDamage);
|
||||
|
||||
GameEvent event = new CountersRemovedEvent(counterName, this, source, finalAmount, isDamage);
|
||||
game.fireEvent(event);
|
||||
}
|
||||
|
||||
|
|
@ -846,6 +847,24 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeAllCounters(Ability source, Game game, boolean isDamage) {
|
||||
int amountBefore = getCounters(game).getTotalCount();
|
||||
for (Counter counter : getCounters(game).copy().values()) {
|
||||
removeCounters(counter.getName(), counter.getCount(), source, game, isDamage);
|
||||
}
|
||||
int amountAfter = getCounters(game).getTotalCount();
|
||||
return Math.max(0, amountBefore - amountAfter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeAllCounters(String counterName, Ability source, Game game, boolean isDamage) {
|
||||
int amountBefore = getCounters(game).getCount(counterName);
|
||||
removeCounters(counterName, amountBefore, source, game, isDamage);
|
||||
int amountAfter = getCounters(game).getCount(counterName);
|
||||
return Math.max(0, amountBefore - amountAfter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
if (name.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -223,8 +223,8 @@ public abstract class ModalDoubleFacedCard extends CardImpl implements CardWithH
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeCounters(String name, int amount, Ability source, Game game) {
|
||||
leftHalfCard.removeCounters(name, amount, source, game);
|
||||
public void removeCounters(String counterName, int amount, Ability source, Game game) {
|
||||
leftHalfCard.removeCounters(counterName, amount, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -27,35 +27,17 @@ public class Counters extends HashMap<String, Counter> implements Serializable,
|
|||
return new Counters(this);
|
||||
}
|
||||
|
||||
public Counters addCounter(String name, int amount) {
|
||||
putIfAbsent(name, new Counter(name));
|
||||
this.get(name).add(amount);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Counters addCounter(Counter counter) {
|
||||
if (!containsKey(counter.name)) {
|
||||
put(counter.name, counter);
|
||||
} else {
|
||||
|
||||
get(counter.name).add(counter.getCount());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean removeCounter(String name) {
|
||||
return removeCounter(name, 1);
|
||||
}
|
||||
|
||||
public boolean removeCounter(CounterType counterType, int amount) {
|
||||
if (this.containsKey(counterType.getName())) {
|
||||
get(counterType.getName()).remove(amount);
|
||||
if (get(counterType.getName()).count == 0) {
|
||||
this.remove(counterType.getName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return removeCounter(counterType.getName(), amount);
|
||||
}
|
||||
|
||||
public boolean removeCounter(String name, int amount) {
|
||||
|
|
@ -69,17 +51,6 @@ public class Counters extends HashMap<String, Counter> implements Serializable,
|
|||
return false;
|
||||
}
|
||||
|
||||
public void removeAllCounters(CounterType counterType) {
|
||||
removeAllCounters(counterType.getName());
|
||||
}
|
||||
|
||||
public void removeAllCounters(String name) {
|
||||
if (this.containsKey(name)) {
|
||||
this.remove(name);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public int getCount(String name) {
|
||||
if (this.containsKey(name)) {
|
||||
return this.get(name).getCount();
|
||||
|
|
@ -91,6 +62,10 @@ public class Counters extends HashMap<String, Counter> implements Serializable,
|
|||
return getCount(counterType) > 0;
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
return this.values().stream().mapToInt(Counter::getCount).sum();
|
||||
}
|
||||
|
||||
public int getCount(CounterType type) {
|
||||
if (this.containsKey(type.getName())) {
|
||||
return this.get(type.getName()).getCount();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public class FilterPermanentOrPlayerWithCounter extends FilterPermanentOrPlayer
|
|||
public boolean match(MageItem o, Game game) {
|
||||
if (super.match(o, game)) {
|
||||
if (o instanceof Player) {
|
||||
return !((Player) o).getCounters().isEmpty();
|
||||
return ((Player) o).getCountersTotalCount() > 0;
|
||||
} else if (o instanceof Permanent) {
|
||||
return !((Permanent) o).getCounters(game).isEmpty();
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ public class FilterPermanentOrPlayerWithCounter extends FilterPermanentOrPlayer
|
|||
public boolean match(MageItem o, UUID playerId, Ability source, Game game) {
|
||||
if (super.match(o, playerId, source, game)) { // same as parent class, so can call with full params
|
||||
if (o instanceof Player) {
|
||||
return !((Player) o).getCounters().isEmpty();
|
||||
return ((Player) o).getCountersTotalCount() > 0;
|
||||
} else if (o instanceof Permanent) {
|
||||
return !((Permanent) o).getCounters(game).isEmpty();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2195,7 +2195,7 @@ public abstract class GameImpl implements Game {
|
|||
public UUID fireReflexiveTriggeredAbility(ReflexiveTriggeredAbility reflexiveAbility, Ability source) {
|
||||
return fireReflexiveTriggeredAbility(reflexiveAbility, source, false);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UUID fireReflexiveTriggeredAbility(ReflexiveTriggeredAbility reflexiveAbility, Ability source, boolean fireAsSimultaneousEvent) {
|
||||
UUID uuid = this.addDelayedTriggeredAbility(reflexiveAbility, source);
|
||||
|
|
@ -2300,7 +2300,7 @@ public abstract class GameImpl implements Game {
|
|||
if (!player.hasLost()
|
||||
&& ((player.getLife() <= 0 && player.canLoseByZeroOrLessLife())
|
||||
|| player.getLibrary().isEmptyDraw()
|
||||
|| player.getCounters().getCount(CounterType.POISON) >= 10)) {
|
||||
|| player.getCountersCount(CounterType.POISON) >= 10)) {
|
||||
player.lost(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ enum RadiationCondition implements Condition {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
return player != null && player.getCounters().getCount(CounterType.RAD) > 0;
|
||||
return player != null && player.getCountersCount(CounterType.RAD) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,13 +102,13 @@ class RadiationEffect extends OneShotEffect {
|
|||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
int amount = player.getCounters().getCount(CounterType.RAD);
|
||||
int amount = player.getCountersCount(CounterType.RAD);
|
||||
Cards milled = player.millCards(amount, source, game);
|
||||
int countNonLand = milled.count(StaticFilters.FILTER_CARD_NON_LAND, player.getId(), source, game);
|
||||
if (countNonLand > 0) {
|
||||
// TODO: support gaining life instead with [[Strong, the Brutish Thespian]]
|
||||
player.loseLife(countNonLand, game, source, false);
|
||||
player.removeCounters(CounterType.RAD.getName(), countNonLand, source, game);
|
||||
player.loseCounters(CounterType.RAD.getName(), countNonLand, source, game);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -548,8 +548,8 @@ public class GameEvent implements Serializable {
|
|||
amount number of counters being removed
|
||||
data name of the counter(s) being removed
|
||||
*/
|
||||
REMOVE_COUNTER, REMOVE_COUNTERS,
|
||||
COUNTER_REMOVED, COUNTERS_REMOVED,
|
||||
REMOVE_COUNTER, COUNTER_REMOVED,
|
||||
REMOVE_COUNTERS, COUNTERS_REMOVED,
|
||||
LOSE_CONTROL,
|
||||
/* LOST_CONTROL
|
||||
targetId id of the creature that lost control
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class DaxosSpiritSetPTEffect extends ContinuousEffectImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
int amount = controller.getCounters().getCount(CounterType.EXPERIENCE);
|
||||
int amount = controller.getCountersCount(CounterType.EXPERIENCE);
|
||||
permanent.getPower().setModifiedBaseValue(amount);
|
||||
permanent.getToughness().setModifiedBaseValue(amount);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1090,8 +1090,8 @@ public class Spell extends StackObjectImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeCounters(String name, int amount, Ability source, Game game, boolean isDamage) {
|
||||
card.removeCounters(name, amount, source, game, isDamage);
|
||||
public void removeCounters(String counterName, int amount, Ability source, Game game, boolean isDamage) {
|
||||
card.removeCounters(counterName, amount, source, game, isDamage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1099,6 +1099,16 @@ public class Spell extends StackObjectImpl implements Card {
|
|||
card.removeCounters(counter, source, game, isDamage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeAllCounters(Ability source, Game game, boolean isDamage) {
|
||||
return card.removeAllCounters(source, game, isDamage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeAllCounters(String counterName, Ability source, Game game, boolean isDamage) {
|
||||
return card.removeAllCounters(counterName, source, game, isDamage);
|
||||
}
|
||||
|
||||
public Card getCard() {
|
||||
return card;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ public class Turn implements Serializable {
|
|||
int delimiter = game.getPlayers().size() - 1;
|
||||
for (Player gamePlayer : game.getPlayers().values()) {
|
||||
sb.append(gamePlayer.getLife());
|
||||
int poison = gamePlayer.getCounters().getCount(CounterType.POISON);
|
||||
int poison = gamePlayer.getCountersCount(CounterType.POISON);
|
||||
if (poison > 0) {
|
||||
sb.append("[P:").append(poison).append(']');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import mage.cards.decks.Deck;
|
|||
import mage.choices.Choice;
|
||||
import mage.constants.*;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.CounterType;
|
||||
import mage.counters.Counters;
|
||||
import mage.designations.Designation;
|
||||
import mage.designations.DesignationType;
|
||||
|
|
@ -105,7 +106,11 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
|
||||
void addAbility(Ability ability);
|
||||
|
||||
Counters getCounters();
|
||||
/**
|
||||
* The counters should be manipulated (adding or removing counters) with the appropriate addCounters/removeCounters/getCounterCount methods.
|
||||
* This returns a copy for specific usage, to make sure the Player's counters are not altered from there.
|
||||
*/
|
||||
Counters getCountersAsCopy();
|
||||
|
||||
int getLife();
|
||||
|
||||
|
|
@ -832,9 +837,44 @@ public interface Player extends MageItem, Copyable<Player> {
|
|||
|
||||
Map<UUID, ActivatedAbility> getPlayableActivatedAbilities(MageObject object, Zone zone, Game originalGame);
|
||||
|
||||
/**
|
||||
* add counter to the player (action verb is `get`, but not using that one to avoid ambiguity with getters)
|
||||
*/
|
||||
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game);
|
||||
|
||||
void removeCounters(String name, int amount, Ability source, Game game);
|
||||
/**
|
||||
* lose {@param amount} counters of the specified kind.
|
||||
*/
|
||||
void loseCounters(String counterName, int amount, Ability source, Game game);
|
||||
|
||||
/**
|
||||
* lose all counters of any kind.
|
||||
*
|
||||
* @return the amount of counters removed this way.
|
||||
*/
|
||||
int loseAllCounters(Ability source, Game game);
|
||||
|
||||
/**
|
||||
* lose all counters of a specific kind.
|
||||
*
|
||||
* @return the amount of counters removed this way.
|
||||
*/
|
||||
int loseAllCounters(String counterName, Ability source, Game game);
|
||||
|
||||
/**
|
||||
* @return the amount of counters of the specified kind the player has
|
||||
*/
|
||||
int getCountersCount(CounterType counterType);
|
||||
|
||||
/**
|
||||
* @return the amount of counters of the specified kind the player has
|
||||
*/
|
||||
int getCountersCount(String counterName);
|
||||
|
||||
/**
|
||||
* @return the amount of counters in total of any kind the player has
|
||||
*/
|
||||
int getCountersTotalCount();
|
||||
|
||||
List<UUID> getAttachments();
|
||||
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
this.commandersIds = new HashSet<>(player.getCommandersIds());
|
||||
|
||||
this.abilities = player.getAbilities().copy();
|
||||
this.counters = player.getCounters().copy();
|
||||
this.counters = player.getCountersAsCopy();
|
||||
|
||||
this.landsPlayed = player.getLandsPlayed();
|
||||
this.landsPerTurn = player.getLandsPerTurn();
|
||||
|
|
@ -531,8 +531,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Counters getCounters() {
|
||||
return counters;
|
||||
public Counters getCountersAsCopy() {
|
||||
return counters.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2369,7 +2369,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
);
|
||||
addingOneEvent.setFlag(isEffectFlag);
|
||||
if (!game.replaceEvent(addingOneEvent)) {
|
||||
getCounters().addCounter(eventCounter);
|
||||
counters.addCounter(eventCounter);
|
||||
GameEvent addedOneEvent = GameEvent.getEvent(
|
||||
GameEvent.EventType.COUNTER_ADDED, playerId, source,
|
||||
playerAddingCounters, counter.getName(), 1
|
||||
|
|
@ -2396,9 +2396,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeCounters(String name, int amount, Ability source, Game game) {
|
||||
public void loseCounters(String counterName, int amount, Ability source, Game game) {
|
||||
|
||||
GameEvent removeCountersEvent = new RemoveCountersEvent(name, this, source, amount, false);
|
||||
GameEvent removeCountersEvent = new RemoveCountersEvent(counterName, this, source, amount, false);
|
||||
if (game.replaceEvent(removeCountersEvent)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -2406,22 +2406,56 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
int finalAmount = 0;
|
||||
for (int i = 0; i < amount; i++) {
|
||||
|
||||
GameEvent event = new RemoveCounterEvent(name, this, source, false);
|
||||
GameEvent event = new RemoveCounterEvent(counterName, this, source, false);
|
||||
if (game.replaceEvent(event)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!counters.removeCounter(name, 1)) {
|
||||
if (!counters.removeCounter(counterName, 1)) {
|
||||
break;
|
||||
}
|
||||
event = new CounterRemovedEvent(name, this, source, false);
|
||||
event = new CounterRemovedEvent(counterName, this, source, false);
|
||||
game.fireEvent(event);
|
||||
finalAmount++;
|
||||
}
|
||||
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, false);
|
||||
|
||||
GameEvent event = new CountersRemovedEvent(counterName, this, source, finalAmount, false);
|
||||
game.fireEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int loseAllCounters(Ability source, Game game) {
|
||||
int amountBefore = getCountersTotalCount();
|
||||
for (Counter counter : getCountersAsCopy().values()) {
|
||||
loseCounters(counter.getName(), counter.getCount(), source, game);
|
||||
}
|
||||
int amountAfter = getCountersTotalCount();
|
||||
return Math.max(0, amountBefore - amountAfter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int loseAllCounters(String counterName, Ability source, Game game) {
|
||||
int amountBefore = getCountersCount(counterName);
|
||||
loseCounters(counterName, amountBefore, source, game);
|
||||
int amountAfter = getCountersCount(counterName);
|
||||
return Math.max(0, amountBefore - amountAfter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCountersCount(CounterType counterType) {
|
||||
return counters.getCount(counterType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCountersCount(String counterName) {
|
||||
return counters.getCount(counterName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCountersTotalCount() {
|
||||
return counters.getTotalCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Abilities<Ability> getAbilities() {
|
||||
return this.abilities;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ public class CountersTest {
|
|||
@Test
|
||||
public void testCopyCounter() {
|
||||
// given
|
||||
counters.addCounter("test", 4);
|
||||
counters.addCounter(new Counter("test", 5));
|
||||
|
||||
// when
|
||||
Counters copy = counters.copy();
|
||||
|
|
@ -29,8 +29,8 @@ public class CountersTest {
|
|||
@Test
|
||||
public void testRemoveCounter() {
|
||||
// given
|
||||
counters.addCounter("test1", 5);
|
||||
counters.addCounter("test2", 5);
|
||||
counters.addCounter(new Counter("test1", 5));
|
||||
counters.addCounter(new Counter("test2", 5));
|
||||
|
||||
// when
|
||||
|
||||
|
|
@ -45,35 +45,23 @@ public class CountersTest {
|
|||
@Test
|
||||
public void testAddCounterWithNewCounter() {
|
||||
// given
|
||||
counters.addCounter("test1", 5);
|
||||
counters.addCounter(new Counter("test1", 5));
|
||||
|
||||
// when
|
||||
counters.addCounter("test1", 10);
|
||||
counters.addCounter("test2", 5);
|
||||
counters.addCounter(new Counter("test1", 10));
|
||||
counters.addCounter(new Counter("test2", 5));
|
||||
|
||||
// then
|
||||
assertNotEquals(15, counters.getCount("test1"));
|
||||
assertEquals(16, counters.getCount("test1"));
|
||||
assertTrue(counters.containsKey("test1"));
|
||||
assertEquals(15, counters.getCount("test1"));
|
||||
assertTrue(counters.containsKey("test2"));
|
||||
assertEquals(6, counters.getCount("test2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAllCounter() {
|
||||
// given
|
||||
counters.addCounter("test", 10);
|
||||
|
||||
// when
|
||||
counters.removeAllCounters("test");
|
||||
|
||||
// then
|
||||
assertFalse(counters.containsKey("test"));
|
||||
assertEquals(5, counters.getCount("test2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCount() {
|
||||
// given
|
||||
counters.addCounter("test1", 5);
|
||||
counters.addCounter(new Counter("test1", 5));
|
||||
|
||||
// when
|
||||
int count1 = counters.getCount("test1");
|
||||
|
|
@ -81,13 +69,13 @@ public class CountersTest {
|
|||
|
||||
// then
|
||||
assertEquals(0, count2);
|
||||
assertEquals(6, count1);
|
||||
assertEquals(5, count1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContainsKey() {
|
||||
// given
|
||||
counters.addCounter("test1", 5);
|
||||
counters.addCounter(new Counter("test1", 5));
|
||||
|
||||
// when
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue