forked from External/mage
refactor: added counter removal events (#11989)
This commit is contained in:
parent
860a767cca
commit
52ddcac59d
11 changed files with 385 additions and 36 deletions
|
|
@ -0,0 +1,194 @@
|
||||||
|
package org.mage.test.cards.triggers;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.ReplacementEffectImpl;
|
||||||
|
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersPlayersEffect;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestCommander4Players;
|
||||||
|
|
||||||
|
public class CounterRemovalTests extends CardTestCommander4Players {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void CounterRemovalTest(){
|
||||||
|
|
||||||
|
int nCountersToAdd = 3;
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, "Basri's Solidarity", nCountersToAdd);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||||
|
|
||||||
|
// Remove all counters from all permanents and exile all tokens.
|
||||||
|
addCard(Zone.HAND, playerA, "Aether Snap");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
|
||||||
|
|
||||||
|
Ability ability = new MultiCountersRemovedTriggeredAbility();
|
||||||
|
addCustomCardWithAbility("multicountertrigdcard", playerA, ability, null, CardType.CREATURE, "", Zone.BATTLEFIELD);
|
||||||
|
|
||||||
|
ability = new SingleCounterRemovedTriggeredAbility();
|
||||||
|
addCustomCardWithAbility("singlecountertrigdcard", playerA, ability, null, CardType.CREATURE, "", Zone.BATTLEFIELD);
|
||||||
|
|
||||||
|
ability = new SimpleStaticAbility(new MultiCountersRemoveReplacementEffect());
|
||||||
|
addCustomCardWithAbility("multicounterreplcard", playerA, ability, null, CardType.CREATURE, "", Zone.BATTLEFIELD);
|
||||||
|
|
||||||
|
ability = new SimpleStaticAbility(new SingleCounterRemoveReplacementEffect());
|
||||||
|
addCustomCardWithAbility("singlecounterreplcard", playerA, ability, null, CardType.CREATURE, "", Zone.BATTLEFIELD);
|
||||||
|
|
||||||
|
for (int i = 0; i < nCountersToAdd; ++i){
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Basri's Solidarity", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aether Snap", true);
|
||||||
|
|
||||||
|
//choose the <nCountersToAdd> single counter triggers to go on the stack first
|
||||||
|
setChoice(playerA, "When a counter", nCountersToAdd);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, currentGame.getStartingLife() - 1);
|
||||||
|
assertCounterCount(playerA, CounterType.ENERGY, nCountersToAdd);
|
||||||
|
assertCounterCount("multicounterreplcard", CounterType.P1P1, 1);
|
||||||
|
assertCounterCount("singlecounterreplcard", CounterType.P1P1, 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SingleCounterRemoveReplacementEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
|
SingleCounterRemoveReplacementEffect() {
|
||||||
|
super(Duration.Custom, Outcome.Benefit);
|
||||||
|
this.setText("When a counter would be removed from {this} that would bring it to less than 2 of that counter, that counter is not removed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private SingleCounterRemoveReplacementEffect(final SingleCounterRemoveReplacementEffect ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
|
if (event.getTargetId().equals(source.getSourceId())) {
|
||||||
|
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||||
|
if (sourcePermanent != null) {
|
||||||
|
int countersCount = sourcePermanent.getCounters(game).getCount(event.getData());
|
||||||
|
return countersCount - 1 < 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.REMOVE_COUNTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SingleCounterRemoveReplacementEffect copy() {
|
||||||
|
return new SingleCounterRemoveReplacementEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiCountersRemoveReplacementEffect extends ReplacementEffectImpl {
|
||||||
|
|
||||||
|
MultiCountersRemoveReplacementEffect() {
|
||||||
|
super(Duration.Custom, Outcome.Benefit);
|
||||||
|
this.setText("When any number of counters would be removed from {this}, one less counter is removed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiCountersRemoveReplacementEffect(final MultiCountersRemoveReplacementEffect ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checksEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.REMOVE_COUNTERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
if (event.getTargetId().equals(source.getSourceId())) {
|
||||||
|
event.setAmount(event.getAmount() - 1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultiCountersRemoveReplacementEffect copy() {
|
||||||
|
return new MultiCountersRemoveReplacementEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiCountersRemovedTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
MultiCountersRemovedTriggeredAbility() {
|
||||||
|
super(Zone.BATTLEFIELD, new LoseLifeSourceControllerEffect(1));
|
||||||
|
this.setTriggerPhrase("When any number of counters are removed from {this}, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiCountersRemovedTriggeredAbility(final MultiCountersRemovedTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultiCountersRemovedTriggeredAbility copy() {
|
||||||
|
return new MultiCountersRemovedTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.COUNTERS_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
return event.getTargetId().equals(this.getSourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SingleCounterRemovedTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
|
|
||||||
|
SingleCounterRemovedTriggeredAbility() {
|
||||||
|
super(Zone.BATTLEFIELD, new AddCountersPlayersEffect(CounterType.ENERGY.createInstance(), TargetController.YOU));
|
||||||
|
this.setTriggerPhrase("When a counter is removed from {this}, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private SingleCounterRemovedTriggeredAbility(final SingleCounterRemovedTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SingleCounterRemovedTriggeredAbility copy() {
|
||||||
|
return new SingleCounterRemovedTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkEventType(GameEvent event, Game game) {
|
||||||
|
return event.getType() == GameEvent.EventType.COUNTER_REMOVED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
return event.getTargetId().equals(this.getSourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -175,9 +175,17 @@ public interface Card extends MageObject, Ownerable {
|
||||||
|
|
||||||
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters);
|
boolean addCounters(Counter counter, UUID playerAddingCounters, Ability source, Game game, List<UUID> appliedEffects, boolean isEffect, int maxCounters);
|
||||||
|
|
||||||
void removeCounters(String name, int amount, Ability source, Game game);
|
default void removeCounters(String name, int amount, Ability source, Game game){
|
||||||
|
removeCounters(name, amount, source, game, false);
|
||||||
|
}
|
||||||
|
|
||||||
void removeCounters(Counter counter, Ability source, Game game);
|
void removeCounters(String name, int amount, Ability source, Game game, boolean damage);
|
||||||
|
|
||||||
|
default void removeCounters(Counter counter, Ability source, Game game) {
|
||||||
|
removeCounters(counter, source, game, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeCounters(Counter counter, Ability source, Game game, boolean damage);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Card copy();
|
Card copy();
|
||||||
|
|
|
||||||
|
|
@ -815,35 +815,46 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCounters(String name, int amount, Ability source, Game game) {
|
public void removeCounters(String name, int amount, Ability source, Game game, boolean isDamage) {
|
||||||
|
|
||||||
|
if (amount <= 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCounters(game).getCount(name) <= 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEvent removeCountersEvent = new RemoveCountersEvent(name, this, source, amount, isDamage);
|
||||||
|
if (game.replaceEvent(removeCountersEvent)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int finalAmount = 0;
|
int finalAmount = 0;
|
||||||
for (int i = 0; i < amount; i++) {
|
for (int i = 0; i < removeCountersEvent.getAmount(); i++) {
|
||||||
|
|
||||||
|
GameEvent event = new RemoveCounterEvent(name, this, source, isDamage);
|
||||||
|
if (game.replaceEvent(event)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!getCounters(game).removeCounter(name, 1)) {
|
if (!getCounters(game).removeCounter(name, 1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTER_REMOVED, objectId, source, getControllerOrOwnerId());
|
|
||||||
if (source != null
|
event = new CounterRemovedEvent(name, this, source, isDamage);
|
||||||
&& source.getControllerId() != null) {
|
|
||||||
event.setPlayerId(source.getControllerId()); // player who controls the source ability that removed the counter
|
|
||||||
}
|
|
||||||
event.setData(name);
|
|
||||||
game.fireEvent(event);
|
game.fireEvent(event);
|
||||||
|
|
||||||
finalAmount++;
|
finalAmount++;
|
||||||
}
|
}
|
||||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTERS_REMOVED, objectId, source, getControllerOrOwnerId());
|
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, isDamage);
|
||||||
if (source != null
|
|
||||||
&& source.getControllerId() != null) {
|
|
||||||
event.setPlayerId(source.getControllerId()); // player who controls the source ability that removed the counter
|
|
||||||
}
|
|
||||||
event.setData(name);
|
|
||||||
event.setAmount(finalAmount);
|
|
||||||
game.fireEvent(event);
|
game.fireEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCounters(Counter counter, Ability source, Game game) {
|
public void removeCounters(Counter counter, Ability source, Game game, boolean isDamage) {
|
||||||
if (counter != null) {
|
if (counter != null) {
|
||||||
removeCounters(counter.getName(), counter.getCount(), source, game);
|
removeCounters(counter.getName(), counter.getCount(), source, game, isDamage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
29
Mage/src/main/java/mage/game/events/CounterRemovedEvent.java
Normal file
29
Mage/src/main/java/mage/game/events/CounterRemovedEvent.java
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package mage.game.events;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
public class CounterRemovedEvent extends GameEvent {
|
||||||
|
|
||||||
|
boolean isDamage;
|
||||||
|
|
||||||
|
public CounterRemovedEvent(String name, Card targetCard, Ability source, boolean isDamage){
|
||||||
|
super(EventType.COUNTER_REMOVED, targetCard.getId(), source,
|
||||||
|
(source == null ? null : source.getControllerId()));
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CounterRemovedEvent(String name, Player targetPlayer, Ability source, boolean isDamage){
|
||||||
|
super(EventType.COUNTER_REMOVED, targetPlayer.getId(), source,
|
||||||
|
(source == null ? null : source.getControllerId()));
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean counterRemovedDueToDamage(){
|
||||||
|
return this.isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package mage.game.events;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
public class CountersRemovedEvent extends GameEvent {
|
||||||
|
|
||||||
|
boolean isDamage;
|
||||||
|
|
||||||
|
public CountersRemovedEvent(String name, Card targetCard, Ability source, int amount, boolean isDamage){
|
||||||
|
super(EventType.COUNTERS_REMOVED, targetCard.getId(), source,
|
||||||
|
(source == null ? null : source.getControllerId()), amount, false);
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CountersRemovedEvent(String name, Player targetPlayer, Ability source, int amount, boolean isDamage){
|
||||||
|
super(EventType.COUNTERS_REMOVED, targetPlayer.getId(), source,
|
||||||
|
(source == null ? null : source.getControllerId()), amount, false);
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean counterRemovedDueToDamage(){
|
||||||
|
return this.isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -541,6 +541,14 @@ public class GameEvent implements Serializable {
|
||||||
STAY_ATTACHED,
|
STAY_ATTACHED,
|
||||||
ADD_COUNTER, COUNTER_ADDED,
|
ADD_COUNTER, COUNTER_ADDED,
|
||||||
ADD_COUNTERS, COUNTERS_ADDED,
|
ADD_COUNTERS, COUNTERS_ADDED,
|
||||||
|
/* REMOVE_COUNTER, REMOVE_COUNTERS, COUNTER_REMOVED, COUNTERS_REMOVED
|
||||||
|
targetId id of the permanent or player losing counter(s)
|
||||||
|
sourceId id of the ability removing them
|
||||||
|
playerId player who controls the ability removing the counters
|
||||||
|
amount number of counters being removed
|
||||||
|
data name of the counter(s) being removed
|
||||||
|
*/
|
||||||
|
REMOVE_COUNTER, REMOVE_COUNTERS,
|
||||||
COUNTER_REMOVED, COUNTERS_REMOVED,
|
COUNTER_REMOVED, COUNTERS_REMOVED,
|
||||||
LOSE_CONTROL,
|
LOSE_CONTROL,
|
||||||
/* LOST_CONTROL
|
/* LOST_CONTROL
|
||||||
|
|
|
||||||
29
Mage/src/main/java/mage/game/events/RemoveCounterEvent.java
Normal file
29
Mage/src/main/java/mage/game/events/RemoveCounterEvent.java
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
package mage.game.events;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
public class RemoveCounterEvent extends GameEvent {
|
||||||
|
|
||||||
|
boolean isDamage;
|
||||||
|
|
||||||
|
public RemoveCounterEvent(String name, Card targetCard, Ability source, boolean isDamage){
|
||||||
|
super(GameEvent.EventType.REMOVE_COUNTER, targetCard.getId(), source,
|
||||||
|
(source == null ? null : source.getControllerId()));
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoveCounterEvent(String name, Player targetPlayer, Ability source, boolean isDamage){
|
||||||
|
super(GameEvent.EventType.REMOVE_COUNTER, targetPlayer.getId(), source,
|
||||||
|
(source == null ? null : source.getControllerId()));
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean counterRemovedDueToDamage(){
|
||||||
|
return this.isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
Mage/src/main/java/mage/game/events/RemoveCountersEvent.java
Normal file
33
Mage/src/main/java/mage/game/events/RemoveCountersEvent.java
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package mage.game.events;
|
||||||
|
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.players.Player;
|
||||||
|
|
||||||
|
public class RemoveCountersEvent extends GameEvent {
|
||||||
|
|
||||||
|
boolean isDamage;
|
||||||
|
|
||||||
|
public RemoveCountersEvent(String name, Card targetCard, Ability source, int amount, boolean isDamage){
|
||||||
|
super(EventType.REMOVE_COUNTERS, targetCard.getId(), source,
|
||||||
|
targetCard.getControllerOrOwnerId(), amount, false);
|
||||||
|
|
||||||
|
if (source != null && source.getControllerId() != null) {
|
||||||
|
setPlayerId(source.getControllerId()); // player who controls the source ability that removed the counters
|
||||||
|
}
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RemoveCountersEvent(String name, Player targetPlayer, Ability source, int amount, boolean isDamage){
|
||||||
|
super(EventType.REMOVE_COUNTERS, targetPlayer.getId(), source,
|
||||||
|
(source == null ? null : source.getControllerId()), amount, false);
|
||||||
|
setData(name);
|
||||||
|
this.isDamage = isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean counterRemovedDueToDamage(){
|
||||||
|
return this.isDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1059,7 +1059,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
if (attacker != null && markDamage) {
|
if (attacker != null && markDamage) {
|
||||||
markDamage(CounterType.LOYALTY.createInstance(countersToRemove), attacker, false);
|
markDamage(CounterType.LOYALTY.createInstance(countersToRemove), attacker, false);
|
||||||
} else {
|
} else {
|
||||||
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, source, game);
|
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, source, game, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.isBattle(game)) {
|
if (this.isBattle(game)) {
|
||||||
|
|
@ -1068,7 +1068,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
if (attacker != null && markDamage) {
|
if (attacker != null && markDamage) {
|
||||||
markDamage(CounterType.DEFENSE.createInstance(countersToRemove), attacker, false);
|
markDamage(CounterType.DEFENSE.createInstance(countersToRemove), attacker, false);
|
||||||
} else {
|
} else {
|
||||||
removeCounters(CounterType.DEFENSE.getName(), countersToRemove, source, game);
|
removeCounters(CounterType.DEFENSE.getName(), countersToRemove, source, game, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DamagedEvent damagedEvent = new DamagedPermanentEvent(this.getId(), attackerId, this.getControllerId(), actualDamageDone, combat);
|
DamagedEvent damagedEvent = new DamagedPermanentEvent(this.getId(), attackerId, this.getControllerId(), actualDamageDone, combat);
|
||||||
|
|
@ -1174,15 +1174,17 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
||||||
/* Tokens don't have a spellAbility. We must make a phony one as the source so the events in addCounters
|
/* Tokens don't have a spellAbility. We must make a phony one as the source so the events in addCounters
|
||||||
* can trace the source back to an object/controller.
|
* can trace the source back to an object/controller.
|
||||||
*/
|
*/
|
||||||
source = new SpellAbility(null, ((PermanentToken) mdi.sourceObject).name);
|
PermanentToken sourceToken = (PermanentToken) mdi.sourceObject;
|
||||||
source.setSourceId(((PermanentToken) mdi.sourceObject).objectId);
|
source = new SpellAbility(null, sourceToken.name);
|
||||||
|
source.setSourceId(sourceToken.objectId);
|
||||||
|
source.setControllerId(sourceToken.controllerId);
|
||||||
} else if (mdi.sourceObject instanceof Permanent) {
|
} else if (mdi.sourceObject instanceof Permanent) {
|
||||||
source = ((Permanent) mdi.sourceObject).getSpellAbility();
|
source = ((Permanent) mdi.sourceObject).getSpellAbility();
|
||||||
}
|
}
|
||||||
if (mdi.addCounters) {
|
if (mdi.addCounters) {
|
||||||
addCounters(mdi.counter, game.getControllerId(mdi.sourceObject.getId()), source, game);
|
addCounters(mdi.counter, game.getControllerId(mdi.sourceObject.getId()), source, game);
|
||||||
} else {
|
} else {
|
||||||
removeCounters(mdi.counter, source, game);
|
removeCounters(mdi.counter, source, game, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
markedDamage.clear();
|
markedDamage.clear();
|
||||||
|
|
|
||||||
|
|
@ -1090,13 +1090,13 @@ public class Spell extends StackObjectImpl implements Card {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCounters(String name, int amount, Ability source, Game game) {
|
public void removeCounters(String name, int amount, Ability source, Game game, boolean isDamage) {
|
||||||
card.removeCounters(name, amount, source, game);
|
card.removeCounters(name, amount, source, game, isDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCounters(Counter counter, Ability source, Game game) {
|
public void removeCounters(Counter counter, Ability source, Game game, boolean isDamage) {
|
||||||
card.removeCounters(counter, source, game);
|
card.removeCounters(counter, source, game, isDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Card getCard() {
|
public Card getCard() {
|
||||||
|
|
|
||||||
|
|
@ -2398,22 +2398,28 @@ public abstract class PlayerImpl implements Player, Serializable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeCounters(String name, int amount, Ability source, Game game) {
|
public void removeCounters(String name, int amount, Ability source, Game game) {
|
||||||
|
|
||||||
|
GameEvent removeCountersEvent = new RemoveCountersEvent(name, this, source, amount, false);
|
||||||
|
if (game.replaceEvent(removeCountersEvent)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int finalAmount = 0;
|
int finalAmount = 0;
|
||||||
for (int i = 0; i < amount; i++) {
|
for (int i = 0; i < amount; i++) {
|
||||||
|
|
||||||
|
GameEvent event = new RemoveCounterEvent(name, this, source, false);
|
||||||
|
if (game.replaceEvent(event)){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!counters.removeCounter(name, 1)) {
|
if (!counters.removeCounter(name, 1)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTER_REMOVED,
|
event = new CounterRemovedEvent(name, this, source, false);
|
||||||
getId(), source, (source == null ? null : source.getControllerId()));
|
|
||||||
event.setData(name);
|
|
||||||
event.setAmount(1);
|
|
||||||
game.fireEvent(event);
|
game.fireEvent(event);
|
||||||
finalAmount++;
|
finalAmount++;
|
||||||
}
|
}
|
||||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTERS_REMOVED,
|
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, false);
|
||||||
getId(), source, (source == null ? null : source.getControllerId()));
|
|
||||||
event.setData(name);
|
|
||||||
event.setAmount(finalAmount);
|
|
||||||
game.fireEvent(event);
|
game.fireEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue