refactor: added counter removal events (#11989)

This commit is contained in:
jimga150 2024-05-02 09:32:55 -04:00 committed by GitHub
parent 860a767cca
commit 52ddcac59d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 385 additions and 36 deletions

View file

@ -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);
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
Card copy();

View file

@ -815,35 +815,46 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
}
@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;
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)) {
break;
}
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTER_REMOVED, objectId, source, getControllerOrOwnerId());
if (source != null
&& source.getControllerId() != null) {
event.setPlayerId(source.getControllerId()); // player who controls the source ability that removed the counter
}
event.setData(name);
event = new CounterRemovedEvent(name, this, source, isDamage);
game.fireEvent(event);
finalAmount++;
}
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTERS_REMOVED, objectId, source, getControllerOrOwnerId());
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);
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, isDamage);
game.fireEvent(event);
}
@Override
public void removeCounters(Counter counter, Ability source, Game game) {
public void removeCounters(Counter counter, Ability source, Game game, boolean isDamage) {
if (counter != null) {
removeCounters(counter.getName(), counter.getCount(), source, game);
removeCounters(counter.getName(), counter.getCount(), source, game, isDamage);
}
}

View 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;
}
}

View file

@ -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;
}
}

View file

@ -541,6 +541,14 @@ public class GameEvent implements Serializable {
STAY_ATTACHED,
ADD_COUNTER, COUNTER_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,
LOSE_CONTROL,
/* LOST_CONTROL

View 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;
}
}

View 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;
}
}

View file

@ -1059,7 +1059,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
if (attacker != null && markDamage) {
markDamage(CounterType.LOYALTY.createInstance(countersToRemove), attacker, false);
} else {
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, source, game);
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, source, game, true);
}
}
if (this.isBattle(game)) {
@ -1068,7 +1068,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
if (attacker != null && markDamage) {
markDamage(CounterType.DEFENSE.createInstance(countersToRemove), attacker, false);
} 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);
@ -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
* can trace the source back to an object/controller.
*/
source = new SpellAbility(null, ((PermanentToken) mdi.sourceObject).name);
source.setSourceId(((PermanentToken) mdi.sourceObject).objectId);
PermanentToken sourceToken = (PermanentToken) mdi.sourceObject;
source = new SpellAbility(null, sourceToken.name);
source.setSourceId(sourceToken.objectId);
source.setControllerId(sourceToken.controllerId);
} else if (mdi.sourceObject instanceof Permanent) {
source = ((Permanent) mdi.sourceObject).getSpellAbility();
}
if (mdi.addCounters) {
addCounters(mdi.counter, game.getControllerId(mdi.sourceObject.getId()), source, game);
} else {
removeCounters(mdi.counter, source, game);
removeCounters(mdi.counter, source, game, true);
}
}
markedDamage.clear();

View file

@ -1090,13 +1090,13 @@ public class Spell extends StackObjectImpl implements Card {
}
@Override
public void removeCounters(String name, int amount, Ability source, Game game) {
card.removeCounters(name, amount, source, game);
public void removeCounters(String name, int amount, Ability source, Game game, boolean isDamage) {
card.removeCounters(name, amount, source, game, isDamage);
}
@Override
public void removeCounters(Counter counter, Ability source, Game game) {
card.removeCounters(counter, source, game);
public void removeCounters(Counter counter, Ability source, Game game, boolean isDamage) {
card.removeCounters(counter, source, game, isDamage);
}
public Card getCard() {

View file

@ -2398,22 +2398,28 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
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;
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)) {
break;
}
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTER_REMOVED,
getId(), source, (source == null ? null : source.getControllerId()));
event.setData(name);
event.setAmount(1);
event = new CounterRemovedEvent(name, this, source, false);
game.fireEvent(event);
finalAmount++;
}
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTERS_REMOVED,
getId(), source, (source == null ? null : source.getControllerId()));
event.setData(name);
event.setAmount(finalAmount);
GameEvent event = new CountersRemovedEvent(name, this, source, finalAmount, false);
game.fireEvent(event);
}