forked from External/mage
Refactor: replaced sourceId by source and introduced source param in some methods;
This commit is contained in:
parent
2bb472607b
commit
db239a1055
3205 changed files with 7080 additions and 6795 deletions
|
|
@ -361,7 +361,12 @@ public interface Game extends MageItem, Serializable {
|
|||
|
||||
void undo(UUID playerId);
|
||||
|
||||
void emptyManaPools();
|
||||
/**
|
||||
* Empty mana pool with mana burn and life lose checks
|
||||
*
|
||||
* @param source must be null for default game events
|
||||
*/
|
||||
void emptyManaPools(Ability source);
|
||||
|
||||
void addEffect(ContinuousEffect continuousEffect, Ability source);
|
||||
|
||||
|
|
@ -420,7 +425,7 @@ public interface Game extends MageItem, Serializable {
|
|||
|
||||
boolean endTurn(Ability source);
|
||||
|
||||
int doAction(MageAction action, UUID sourceId);
|
||||
int doAction(Ability source, MageAction action);
|
||||
|
||||
//game transaction methods
|
||||
void saveState(boolean bookmark);
|
||||
|
|
@ -448,7 +453,7 @@ public interface Game extends MageItem, Serializable {
|
|||
// game cheats (for tests only)
|
||||
void cheat(UUID ownerId, Map<Zone, String> commands);
|
||||
|
||||
void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command);
|
||||
void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command);
|
||||
|
||||
// controlling the behaviour of replacement effects while permanents entering the battlefield
|
||||
void setScopeRelevant(boolean scopeRelevant);
|
||||
|
|
@ -486,9 +491,9 @@ public interface Game extends MageItem, Serializable {
|
|||
|
||||
void setMonarchId(Ability source, UUID monarchId);
|
||||
|
||||
int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable);
|
||||
int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID attackerId, Ability source, Game game, boolean combatDamage, boolean preventable);
|
||||
|
||||
int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects);
|
||||
int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID attackerId, Ability source, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects);
|
||||
|
||||
Mulligan getMulligan();
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,14 @@ import mage.abilities.*;
|
|||
import mage.abilities.common.AttachableToRestrictedAbility;
|
||||
import mage.abilities.common.CantHaveMoreThanAmountCountersSourceAbility;
|
||||
import mage.abilities.common.SagaAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousEffects;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.PreventionEffectData;
|
||||
import mage.abilities.effects.common.CopyEffect;
|
||||
import mage.abilities.effects.common.InfoEffect;
|
||||
import mage.abilities.keyword.BestowAbility;
|
||||
import mage.abilities.keyword.CompanionAbility;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
|
|
@ -1069,7 +1071,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
Player player = getPlayer(playerId);
|
||||
Cards cardsWithOpeningAction = new CardsImpl();
|
||||
for (Card card : player.getHand().getCards(this)) {
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(this)) {
|
||||
if (ability instanceof OpeningHandAction) {
|
||||
OpeningHandAction action = (OpeningHandAction) ability;
|
||||
if (action.isOpeningHandActionAllowed(card, player, this)) {
|
||||
|
|
@ -1088,7 +1090,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
card = cardsWithOpeningAction.getRandom(this);
|
||||
}
|
||||
if (card != null) {
|
||||
for (Ability ability : card.getAbilities()) {
|
||||
for (Ability ability : card.getAbilities(this)) {
|
||||
if (ability instanceof OpeningHandAction) {
|
||||
OpeningHandAction action = (OpeningHandAction) ability;
|
||||
if (action.askUseOpeningHandAction(card, player, this)) {
|
||||
|
|
@ -1541,11 +1543,11 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void emptyManaPools() {
|
||||
public void emptyManaPools(Ability source) {
|
||||
for (Player player : getPlayers().values()) {
|
||||
int amount = player.getManaPool().emptyPool(this);
|
||||
if (state.isManaBurn() && amount > 0) {
|
||||
player.loseLife(amount, this, false);
|
||||
player.loseLife(amount, this, source, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1783,7 +1785,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
@Override
|
||||
public UUID fireReflexiveTriggeredAbility(ReflexiveTriggeredAbility reflexiveAbility, Ability source) {
|
||||
UUID uuid = this.addDelayedTriggeredAbility(reflexiveAbility, source);
|
||||
this.fireEvent(GameEvent.getEvent(GameEvent.EventType.OPTION_USED, source.getOriginalId(), source.getSourceId(), source.getControllerId()));
|
||||
this.fireEvent(GameEvent.getEvent(GameEvent.EventType.OPTION_USED, source.getOriginalId(), source, source.getControllerId()));
|
||||
return uuid;
|
||||
}
|
||||
|
||||
|
|
@ -2088,8 +2090,8 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
Card card = this.getCard(perm.getId());
|
||||
if (card != null && card.isCreature()) {
|
||||
UUID wasAttachedTo = perm.getAttachedTo();
|
||||
perm.attachTo(null, this);
|
||||
fireEvent(new GameEvent(GameEvent.EventType.UNATTACHED, wasAttachedTo, perm.getId(), perm.getControllerId()));
|
||||
perm.attachTo(null, null, this);
|
||||
fireEvent(new UnattachedEvent(wasAttachedTo, perm.getId(), perm, null));
|
||||
} else if (movePermanentToGraveyardWithInfo(perm)) {
|
||||
somethingHappened = true;
|
||||
}
|
||||
|
|
@ -2097,19 +2099,19 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
Filter auraFilter = spellAbility.getTargets().get(0).getFilter();
|
||||
if (auraFilter instanceof FilterControlledPermanent) {
|
||||
if (!((FilterControlledPermanent) auraFilter).match(attachedTo, perm.getId(), perm.getControllerId(), this)
|
||||
|| attachedTo.cantBeAttachedBy(perm, this, true)) {
|
||||
|| attachedTo.cantBeAttachedBy(perm, null, this, true)) {
|
||||
if (movePermanentToGraveyardWithInfo(perm)) {
|
||||
somethingHappened = true;
|
||||
}
|
||||
}
|
||||
} else if (!auraFilter.match(attachedTo, this) || attachedTo.cantBeAttachedBy(perm, this, true)) {
|
||||
} else if (!auraFilter.match(attachedTo, this) || attachedTo.cantBeAttachedBy(perm, null, this, true)) {
|
||||
// handle bestow unattachment
|
||||
Card card = this.getCard(perm.getId());
|
||||
if (card != null && card.isCreature()) {
|
||||
UUID wasAttachedTo = perm.getAttachedTo();
|
||||
perm.attachTo(null, this);
|
||||
perm.attachTo(null, null, this);
|
||||
BestowAbility.becomeCreature(perm, this);
|
||||
fireEvent(new GameEvent(GameEvent.EventType.UNATTACHED, wasAttachedTo, perm.getId(), perm.getControllerId()));
|
||||
fireEvent(new UnattachedEvent(wasAttachedTo, perm.getId(), perm, null));
|
||||
} else if (movePermanentToGraveyardWithInfo(perm)) {
|
||||
somethingHappened = true;
|
||||
}
|
||||
|
|
@ -2135,7 +2137,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|| !(spellAbility.getTargets().get(0)).canTarget(perm.getControllerId(), perm.getAttachedTo(), spellAbility, this)) {
|
||||
if (movePermanentToGraveyardWithInfo(perm)) {
|
||||
if (attachedTo != null) {
|
||||
attachedTo.removeAttachment(perm.getId(), this);
|
||||
attachedTo.removeAttachment(perm.getId(), null, this);
|
||||
}
|
||||
somethingHappened = true;
|
||||
}
|
||||
|
|
@ -2169,7 +2171,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
if (noChapterAbilityTriggeredOrOnStack) {
|
||||
// After the last chapter ability has left the stack, you'll sacrifice the Saga
|
||||
perm.sacrifice(perm.getId(), this);
|
||||
perm.sacrifice(null, this);
|
||||
somethingHappened = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2196,10 +2198,10 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
if (attachedTo == null || !attachedTo.getAttachments().contains(perm.getId())) {
|
||||
UUID wasAttachedTo = perm.getAttachedTo();
|
||||
perm.attachTo(null, this);
|
||||
fireEvent(new GameEvent(GameEvent.EventType.UNATTACHED, wasAttachedTo, perm.getId(), perm.getControllerId()));
|
||||
perm.attachTo(null, null, this);
|
||||
fireEvent(new UnattachedEvent(wasAttachedTo, perm.getId(), perm, null));
|
||||
} else if (!attachedTo.isCreature() || attachedTo.hasProtectionFrom(perm, this)) {
|
||||
if (attachedTo.removeAttachment(perm.getId(), this)) {
|
||||
if (attachedTo.removeAttachment(perm.getId(), null, this)) {
|
||||
somethingHappened = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2209,9 +2211,9 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (perm.getAttachedTo() != null) {
|
||||
Permanent land = getPermanent(perm.getAttachedTo());
|
||||
if (land == null || !land.getAttachments().contains(perm.getId())) {
|
||||
perm.attachTo(null, this);
|
||||
perm.attachTo(null, null, this);
|
||||
} else if (!land.isLand() || land.hasProtectionFrom(perm, this)) {
|
||||
if (land.removeAttachment(perm.getId(), this)) {
|
||||
if (land.removeAttachment(perm.getId(), null, this)) {
|
||||
somethingHappened = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2228,7 +2230,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|| !(attachment.getSubtype(this).contains(SubType.AURA)
|
||||
|| attachment.getSubtype(this).contains(SubType.EQUIPMENT)
|
||||
|| attachment.getSubtype(this).contains(SubType.FORTIFICATION)))) {
|
||||
if (perm.removeAttachment(attachment.getId(), this)) {
|
||||
if (perm.removeAttachment(attachment.getId(), null, this)) {
|
||||
somethingHappened = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2253,7 +2255,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
CantHaveMoreThanAmountCountersSourceAbility counterAbility = (CantHaveMoreThanAmountCountersSourceAbility) ability;
|
||||
int count = perm.getCounters(this).getCount(counterAbility.getCounterType());
|
||||
if (count > counterAbility.getAmount()) {
|
||||
perm.removeCounters(counterAbility.getCounterType().getName(), count - counterAbility.getAmount(), this);
|
||||
perm.removeCounters(counterAbility.getCounterType().getName(), count - counterAbility.getAmount(), counterAbility, this);
|
||||
somethingHappened = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2638,11 +2640,11 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (perm.getAttachedTo() != null) {
|
||||
Permanent attachedTo = getPermanent(perm.getAttachedTo());
|
||||
if (attachedTo != null) {
|
||||
attachedTo.removeAttachment(perm.getId(), this);
|
||||
attachedTo.removeAttachment(perm.getId(), null, this);
|
||||
} else {
|
||||
Player attachedToPlayer = getPlayer(perm.getAttachedTo());
|
||||
if (attachedToPlayer != null) {
|
||||
attachedToPlayer.removeAttachment(perm, this);
|
||||
attachedToPlayer.removeAttachment(perm, null, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2814,7 +2816,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
return result;
|
||||
}
|
||||
DamageEvent damageEvent = (DamageEvent) event;
|
||||
GameEvent preventEvent = new PreventDamageEvent(damageEvent.getTargetId(), damageEvent.getSourceId(), source.getControllerId(), damageEvent.getAmount(), damageEvent.isCombatDamage());
|
||||
GameEvent preventEvent = new PreventDamageEvent(damageEvent.getTargetId(), damageEvent.getSourceId(), source, source.getControllerId(), damageEvent.getAmount(), damageEvent.isCombatDamage());
|
||||
if (game.replaceEvent(preventEvent)) {
|
||||
result.setReplaced(true);
|
||||
return result;
|
||||
|
|
@ -2855,7 +2857,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
game.informPlayers(message.toString());
|
||||
}
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, damageEvent.getTargetId(), source.getSourceId(), source.getControllerId(), result.getPreventedDamage()));
|
||||
game.fireEvent(new PreventedDamageEvent(damageEvent.getTargetId(), source.getSourceId(), source, source.getControllerId(), result.getPreventedDamage()));
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
@ -3039,7 +3041,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (s.length == 2) {
|
||||
try {
|
||||
Integer amount = Integer.parseInt(s[1]);
|
||||
player.setLife(amount, this, ownerId);
|
||||
player.setLife(amount, this, null);
|
||||
logger.debug("Setting player's life: ");
|
||||
} catch (NumberFormatException e) {
|
||||
logger.fatal("error setting life", e);
|
||||
|
|
@ -3060,7 +3062,11 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void cheat(UUID ownerId, UUID activePlayerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command) {
|
||||
public void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command) {
|
||||
// fake test ability for triggers and events
|
||||
Ability fakeSourceAbility = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards"));
|
||||
fakeSourceAbility.setControllerId(ownerId);
|
||||
|
||||
Player player = getPlayer(ownerId);
|
||||
if (player != null) {
|
||||
loadCards(ownerId, library);
|
||||
|
|
@ -3094,7 +3100,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
for (PermanentCard permanentCard : battlefield) {
|
||||
CardUtil.putCardOntoBattlefieldWithEffects(this, permanentCard, player);
|
||||
CardUtil.putCardOntoBattlefieldWithEffects(fakeSourceAbility, this, permanentCard, player);
|
||||
}
|
||||
|
||||
applyEffects();
|
||||
|
|
@ -3116,11 +3122,8 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int doAction(MageAction action, UUID sourceId) {
|
||||
//actions.add(action);
|
||||
int value = action.doAction(sourceId, this);
|
||||
// score += action.getScore(scorePlayer);
|
||||
return value;
|
||||
public int doAction(Ability source, MageAction action) {
|
||||
return action.doAction(source, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -3370,10 +3373,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (monarchId.equals(getMonarchId())) { // Nothing happens if you're already the monarch
|
||||
return;
|
||||
}
|
||||
if (replaceEvent(GameEvent.getEvent(
|
||||
GameEvent.EventType.BECOME_MONARCH,
|
||||
monarchId, source.getSourceId(), monarchId
|
||||
))) {
|
||||
if (replaceEvent(GameEvent.getEvent(GameEvent.EventType.BECOME_MONARCH, monarchId, source, monarchId))) {
|
||||
return;
|
||||
}
|
||||
Player newMonarch = getPlayer(monarchId);
|
||||
|
|
@ -3383,24 +3383,24 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (newMonarch != null) {
|
||||
getState().setMonarchId(monarchId);
|
||||
informPlayers(newMonarch.getLogName() + " is the monarch");
|
||||
fireEvent(new GameEvent(GameEvent.EventType.BECOMES_MONARCH, monarchId, source == null ? null : source.getSourceId(), monarchId));
|
||||
fireEvent(new GameEvent(GameEvent.EventType.BECOMES_MONARCH, monarchId, source, monarchId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable) {
|
||||
return damagePlayerOrPlaneswalker(playerOrWalker, damage, sourceId, game, combatDamage, preventable, null);
|
||||
public int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID attackerId, Ability source, Game game, boolean combatDamage, boolean preventable) {
|
||||
return damagePlayerOrPlaneswalker(playerOrWalker, damage, attackerId, source, game, combatDamage, preventable, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
|
||||
public int damagePlayerOrPlaneswalker(UUID playerOrWalker, int damage, UUID attackerId, Ability source, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
|
||||
Player player = getPlayer(playerOrWalker);
|
||||
if (player != null) {
|
||||
return player.damage(damage, sourceId, game, combatDamage, preventable, appliedEffects);
|
||||
return player.damage(damage, attackerId, source, game, combatDamage, preventable, appliedEffects);
|
||||
}
|
||||
Permanent permanent = getPermanent(playerOrWalker);
|
||||
if (permanent != null) {
|
||||
return permanent.damage(damage, sourceId, game, combatDamage, preventable, appliedEffects);
|
||||
return permanent.damage(damage, attackerId, source, game, combatDamage, preventable, appliedEffects);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package mage.game;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.MeldCard;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.stack.Spell;
|
||||
|
|
@ -91,20 +93,24 @@ public class ZoneChangeInfo {
|
|||
public static class Battlefield extends ZoneChangeInfo {
|
||||
|
||||
public boolean tapped;
|
||||
public Ability source;
|
||||
|
||||
public Battlefield(ZoneChangeEvent event, boolean tapped) {
|
||||
public Battlefield(ZoneChangeEvent event, boolean tapped, Ability source) {
|
||||
super(event);
|
||||
this.tapped = tapped;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public Battlefield(ZoneChangeEvent event, boolean faceDown, boolean tapped) {
|
||||
public Battlefield(ZoneChangeEvent event, boolean faceDown, boolean tapped, Ability source) {
|
||||
super(event, faceDown);
|
||||
this.tapped = tapped;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public Battlefield(final Battlefield info) {
|
||||
super(info);
|
||||
this.tapped = info.tapped;
|
||||
this.source = info.source;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -147,14 +153,14 @@ public class ZoneChangeInfo {
|
|||
MeldCard meld = game.getMeldCard(info.event.getTargetId());
|
||||
if (meld != null) {
|
||||
if (meld.hasTopHalf(game)) {
|
||||
ZoneChangeEvent topEvent = new ZoneChangeEvent(meld.getTopHalfCard().getId(), event.getSourceId(),
|
||||
ZoneChangeEvent topEvent = new ZoneChangeEvent(meld.getTopHalfCard().getId(), event.getSource(),
|
||||
event.getPlayerId(), event.getFromZone(), event.getToZone(), event.getAppliedEffects());
|
||||
ZoneChangeInfo topInfo = info.copy();
|
||||
topInfo.event = topEvent;
|
||||
subInfo.add(topInfo);
|
||||
}
|
||||
if (meld.hasBottomHalf(game)) {
|
||||
ZoneChangeEvent bottomEvent = new ZoneChangeEvent(meld.getBottomHalfCard().getId(), event.getSourceId(),
|
||||
ZoneChangeEvent bottomEvent = new ZoneChangeEvent(meld.getBottomHalfCard().getId(), event.getSource(),
|
||||
event.getPlayerId(), event.getFromZone(), event.getToZone(), event.getAppliedEffects());
|
||||
ZoneChangeInfo bottomInfo = info.copy();
|
||||
bottomInfo.event = bottomEvent;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.game;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.keyword.TransformAbility;
|
||||
import mage.cards.*;
|
||||
import mage.constants.Outcome;
|
||||
|
|
@ -23,8 +24,8 @@ import java.util.*;
|
|||
*/
|
||||
public final class ZonesHandler {
|
||||
|
||||
public static boolean cast(ZoneChangeInfo info, Game game) {
|
||||
if (maybeRemoveFromSourceZone(info, game)) {
|
||||
public static boolean cast(ZoneChangeInfo info, Game game, Ability source) {
|
||||
if (maybeRemoveFromSourceZone(info, game, source)) {
|
||||
placeInDestinationZone(info, game, 0);
|
||||
// create a group zone change event if a card is moved to stack for casting (it's always only one card, but some effects check for group events (one or more xxx))
|
||||
Set<Card> cards = new HashSet<>();
|
||||
|
|
@ -43,13 +44,13 @@ public final class ZonesHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static boolean moveCard(ZoneChangeInfo info, Game game) {
|
||||
public static boolean moveCard(ZoneChangeInfo info, Game game, Ability source) {
|
||||
List<ZoneChangeInfo> list = new ArrayList<>();
|
||||
list.add(info);
|
||||
return !moveCards(list, game).isEmpty();
|
||||
return !moveCards(list, game, source).isEmpty();
|
||||
}
|
||||
|
||||
public static List<ZoneChangeInfo> moveCards(List<ZoneChangeInfo> zoneChangeInfos, Game game) {
|
||||
public static List<ZoneChangeInfo> moveCards(List<ZoneChangeInfo> zoneChangeInfos, Game game, Ability source) {
|
||||
// Handle Unmelded Meld Cards
|
||||
for (ListIterator<ZoneChangeInfo> itr = zoneChangeInfos.listIterator(); itr.hasNext(); ) {
|
||||
ZoneChangeInfo info = itr.next();
|
||||
|
|
@ -75,13 +76,17 @@ public final class ZonesHandler {
|
|||
ZoneChangeInfo info = itr.next();
|
||||
if (info.event.getToZone().equals(Zone.BATTLEFIELD)) {
|
||||
Card card = game.getCard(info.event.getTargetId());
|
||||
if (card instanceof ModalDoubleFacesCard || card instanceof ModalDoubleFacesCardHalf) {
|
||||
System.out.println("!"); // TODO: remove after mdf test fixes
|
||||
}
|
||||
|
||||
if (card instanceof ModalDoubleFacesCard) {
|
||||
info.event.setTargetId(((ModalDoubleFacesCard) card).getLeftHalfCard().getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zoneChangeInfos.removeIf(zoneChangeInfo -> !maybeRemoveFromSourceZone(zoneChangeInfo, game));
|
||||
zoneChangeInfos.removeIf(zoneChangeInfo -> !maybeRemoveFromSourceZone(zoneChangeInfo, game, source));
|
||||
int createOrder = 0;
|
||||
for (ZoneChangeInfo zoneChangeInfo : zoneChangeInfos) {
|
||||
if (createOrder == 0 && Zone.BATTLEFIELD.equals(zoneChangeInfo.event.getToZone())) {
|
||||
|
|
@ -270,14 +275,16 @@ public final class ZonesHandler {
|
|||
return game.getPermanent(targetId);
|
||||
}
|
||||
|
||||
private static boolean maybeRemoveFromSourceZone(ZoneChangeInfo info, Game game) {
|
||||
private static boolean maybeRemoveFromSourceZone(ZoneChangeInfo info, Game game, Ability source) {
|
||||
ZoneChangeEvent event = info.event;
|
||||
|
||||
// Handle Unmelded Cards
|
||||
if (info instanceof ZoneChangeInfo.Unmelded) {
|
||||
ZoneChangeInfo.Unmelded unmelded = (ZoneChangeInfo.Unmelded) info;
|
||||
MeldCard meld = game.getMeldCard(info.event.getTargetId());
|
||||
MeldCard meld = game.getMeldCard(event.getTargetId());
|
||||
for (Iterator<ZoneChangeInfo> itr = unmelded.subInfo.iterator(); itr.hasNext(); ) {
|
||||
ZoneChangeInfo subInfo = itr.next();
|
||||
if (!maybeRemoveFromSourceZone(subInfo, game)) {
|
||||
if (!maybeRemoveFromSourceZone(subInfo, game, source)) {
|
||||
itr.remove();
|
||||
} else if (Objects.equals(subInfo.event.getTargetId(), meld.getTopHalfCard().getId())) {
|
||||
meld.setTopLastZoneChangeCounter(meld.getTopHalfCard().getZoneChangeCounter(game));
|
||||
|
|
@ -294,7 +301,6 @@ public final class ZonesHandler {
|
|||
}
|
||||
|
||||
// Handle all normal cases
|
||||
ZoneChangeEvent event = info.event;
|
||||
Card card = getTargetCard(game, event.getTargetId());
|
||||
if (card == null) {
|
||||
// If we can't find the card we can't remove it.
|
||||
|
|
@ -304,7 +310,7 @@ public final class ZonesHandler {
|
|||
boolean success = false;
|
||||
if (info.faceDown) {
|
||||
card.setFaceDown(true, game);
|
||||
} else if (info.event.getToZone().equals(Zone.BATTLEFIELD)) {
|
||||
} else if (event.getToZone().equals(Zone.BATTLEFIELD)) {
|
||||
if (!card.isPermanent()
|
||||
&& (!card.isTransformable() || Boolean.FALSE.equals(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId())))) {
|
||||
// Non permanents (Instants, Sorceries, ... stay in the zone they are if an abilty/effect tries to move it to the battlefield
|
||||
|
|
@ -332,7 +338,7 @@ public final class ZonesHandler {
|
|||
|
||||
// put onto battlefield with possible counters
|
||||
game.getPermanentsEntering().put(permanent.getId(), permanent);
|
||||
card.checkForCountersToAdd(permanent, game);
|
||||
card.checkForCountersToAdd(permanent, source, game);
|
||||
permanent.setTapped(info instanceof ZoneChangeInfo.Battlefield
|
||||
&& ((ZoneChangeInfo.Battlefield) info).tapped);
|
||||
|
||||
|
|
@ -344,8 +350,8 @@ public final class ZonesHandler {
|
|||
// make sure the controller of all continuous effects of this card are switched to the current controller
|
||||
game.setScopeRelevant(true);
|
||||
game.getContinuousEffects().setController(permanent.getId(), permanent.getControllerId());
|
||||
if (permanent.entersBattlefield(event.getSourceId(), game, fromZone, true)
|
||||
&& card.removeFromZone(game, fromZone, event.getSourceId())) {
|
||||
if (permanent.entersBattlefield(source, game, fromZone, true)
|
||||
&& card.removeFromZone(game, fromZone, source)) {
|
||||
success = true;
|
||||
event.setTarget(permanent);
|
||||
} else {
|
||||
|
|
@ -357,11 +363,11 @@ public final class ZonesHandler {
|
|||
} else if (event.getTarget() != null) {
|
||||
card.setFaceDown(info.faceDown, game);
|
||||
Permanent target = event.getTarget();
|
||||
success = game.getPlayer(target.getControllerId()).removeFromBattlefield(target, game)
|
||||
&& target.removeFromZone(game, fromZone, event.getSourceId());
|
||||
success = game.getPlayer(target.getControllerId()).removeFromBattlefield(target, source, game)
|
||||
&& target.removeFromZone(game, fromZone, source);
|
||||
} else {
|
||||
card.setFaceDown(info.faceDown, game);
|
||||
success = card.removeFromZone(game, fromZone, event.getSourceId());
|
||||
success = card.removeFromZone(game, fromZone, source);
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ import mage.filter.predicate.mageobject.NamePredicate;
|
|||
import mage.filter.predicate.permanent.AttackingSameNotBandedPredicate;
|
||||
import mage.filter.predicate.permanent.PermanentIdPredicate;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.AttackerDeclaredEvent;
|
||||
import mage.game.events.DeclareAttackerEvent;
|
||||
import mage.game.events.DeclareBlockerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -272,13 +275,13 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
Permanent attackingPermanent = game.getPermanent(attacker);
|
||||
if (attackingPermanent != null) {
|
||||
attackingPermanent.setTapped(false);
|
||||
attackingPermanent.tap(true, game); // to tap with event finally here is needed to prevent abusing of Vampire Envoy like cards
|
||||
attackingPermanent.tap(true, null, game); // to tap with event finally here is needed to prevent abusing of Vampire Envoy like cards
|
||||
}
|
||||
}
|
||||
handleBanding(attacker, game);
|
||||
// This can only be used to modify the event, the attack can't be replaced here
|
||||
game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.ATTACKER_DECLARED, group.defenderId, attacker, attackingPlayerId));
|
||||
game.addSimultaneousEvent(GameEvent.getEvent(GameEvent.EventType.ATTACKER_DECLARED, group.defenderId, attacker, attackingPlayerId));
|
||||
game.replaceEvent(new AttackerDeclaredEvent(group.defenderId, attacker, attackingPlayerId));
|
||||
game.addSimultaneousEvent(new AttackerDeclaredEvent(group.defenderId, attacker, attackingPlayerId));
|
||||
}
|
||||
}
|
||||
attackersTappedByAttack.clear();
|
||||
|
|
@ -452,8 +455,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
Set<UUID> defendersCostlessAttackable = new HashSet<>(defenders);
|
||||
for (UUID defenderId : defenders) {
|
||||
if (game.getContinuousEffects().checkIfThereArePayCostToAttackBlockEffects(
|
||||
GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKER,
|
||||
defenderId, creature.getId(), creature.getControllerId()), game)) {
|
||||
new DeclareAttackerEvent(defenderId, creature.getId(), creature.getControllerId()), game)) {
|
||||
defendersCostlessAttackable.remove(defenderId);
|
||||
defendersForcedToAttack.remove(defenderId);
|
||||
}
|
||||
|
|
@ -550,13 +552,13 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
|
||||
public void selectBlockers(Game game) {
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_BLOCKERS, attackingPlayerId, attackingPlayerId))) {
|
||||
game.getCombat().selectBlockers(null, game);
|
||||
game.getCombat().selectBlockers(null, null, game);
|
||||
}
|
||||
for (UUID attackingCreatureID : game.getCombat().getAttackers()) {
|
||||
Permanent permanent = game.getPermanent(attackingCreatureID);
|
||||
CombatGroup group = game.getCombat().findGroup(attackingCreatureID);
|
||||
if (permanent != null && group != null && !group.getBlocked()) {
|
||||
game.fireEvent(GameEvent.getEvent(EventType.UNBLOCKED_ATTACKER, attackingCreatureID, attackingPlayerId));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.UNBLOCKED_ATTACKER, attackingCreatureID, attackingPlayerId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -568,7 +570,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
* defender is the controller
|
||||
* @param game
|
||||
*/
|
||||
public void selectBlockers(Player blockController, Game game) {
|
||||
public void selectBlockers(Player blockController, Ability source, Game game) {
|
||||
Player attacker = game.getPlayer(attackingPlayerId);
|
||||
//20101001 - 509.1c
|
||||
game.getCombat().retrieveMustBlockAttackerRequirements(attacker, game);
|
||||
|
|
@ -583,7 +585,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
controller = blockController;
|
||||
}
|
||||
while (choose) {
|
||||
controller.selectBlockers(game, defenderId);
|
||||
controller.selectBlockers(source, game, defenderId);
|
||||
if (game.isPaused() || game.checkIfGameIsOver() || game.executingRollback()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -719,7 +721,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
// check if the possible blocker has to pay cost to block, if so don't force
|
||||
if (game.getContinuousEffects().checkIfThereArePayCostToAttackBlockEffects(
|
||||
GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKER, attackingCreatureId, possibleBlocker.getId(), possibleBlocker.getControllerId()), game)) {
|
||||
new DeclareBlockerEvent(attackingCreatureId, possibleBlocker.getId(), possibleBlocker.getControllerId()), game)) {
|
||||
// has cost to block to pay so remove this attacker
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1291,7 +1293,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
public boolean declareAttacker(UUID creatureId, UUID defenderId, UUID playerId, Game game) {
|
||||
Permanent attacker = game.getPermanent(creatureId);
|
||||
if (attacker != null) {
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_ATTACKER, defenderId, creatureId, playerId))) {
|
||||
if (!game.replaceEvent(new DeclareAttackerEvent(defenderId, creatureId, playerId))) {
|
||||
if (addAttackerToCombat(creatureId, defenderId, game)) {
|
||||
if (!attacker.hasAbility(VigilanceAbility.getInstance(), game)
|
||||
&& !attacker.hasAbility(JohanVigilanceAbility.getInstance(), game)) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import mage.constants.Outcome;
|
|||
import mage.filter.StaticFilters;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.BlockerDeclaredEvent;
|
||||
import mage.game.events.DeclareBlockerEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
|
@ -266,23 +268,23 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
if (hasTrample(attacker)) {
|
||||
int lethalDamage = getLethalDamage(blocker, attacker, game);
|
||||
if (lethalDamage >= damage) {
|
||||
blocker.markDamage(damage, attacker.getId(), game, true, true);
|
||||
blocker.markDamage(damage, attacker.getId(), null, game, true, true);
|
||||
} else {
|
||||
int damageAssigned = player.getAmount(lethalDamage, damage, "Assign damage to " + blocker.getName(), game);
|
||||
blocker.markDamage(damageAssigned, attacker.getId(), game, true, true);
|
||||
blocker.markDamage(damageAssigned, attacker.getId(), null, game, true, true);
|
||||
damage -= damageAssigned;
|
||||
if (damage > 0) {
|
||||
defenderDamage(attacker, damage, game);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
blocker.markDamage(damage, attacker.getId(), game, true, true);
|
||||
blocker.markDamage(damage, attacker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
if (canDamage(blocker, first)) {
|
||||
if (checkSoleBlockerAfter(blocker, game)) { // blocking several creatures handled separately
|
||||
if (!assignsDefendingPlayerAndOrDefendingCreaturesDividedDamage(blocker, blocker.getControllerId(), first, game, false)) {
|
||||
attacker.markDamage(blockerDamage, blocker.getId(), game, true, true);
|
||||
attacker.markDamage(blockerDamage, blocker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -349,20 +351,20 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
// might be missing canDamage condition?
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
if (!assignsDefendingPlayerAndOrDefendingCreaturesDividedDamage(blocker, blocker.getControllerId(), first, game, false)) {
|
||||
attacker.markDamage(power, blockerId, game, true, true);
|
||||
attacker.markDamage(power, blockerId, null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
||||
Permanent blocker = game.getPermanent(entry.getKey());
|
||||
blocker.markDamage(entry.getValue(), attacker.getId(), game, true, true);
|
||||
blocker.markDamage(entry.getValue(), attacker.getId(), null, game, true, true);
|
||||
}
|
||||
} else {
|
||||
for (UUID blockerId : blockerOrder) {
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
if (canDamage(blocker, first)) {
|
||||
if (!assignsDefendingPlayerAndOrDefendingCreaturesDividedDamage(blocker, blocker.getControllerId(), first, game, false)) {
|
||||
attacker.markDamage(getDamageValueFromPermanent(blocker, game), blocker.getId(), game, true, true);
|
||||
attacker.markDamage(getDamageValueFromPermanent(blocker, game), blocker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -402,7 +404,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
if (damage > 0) {
|
||||
Player defendingPlayer = game.getPlayer(defendingPlayerId);
|
||||
if (defendingPlayer != null) {
|
||||
defendingPlayer.damage(damage, attacker.getId(), game, true, true);
|
||||
defendingPlayer.damage(damage, attacker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
if (isAttacking) {
|
||||
|
|
@ -412,14 +414,14 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
// might be missing canDamage condition?
|
||||
Permanent blocker = game.getPermanent(blockerId);
|
||||
if (!assignsDefendingPlayerAndOrDefendingCreaturesDividedDamage(blocker, blocker.getControllerId(), first, game, false)) {
|
||||
attacker.markDamage(power, blockerId, game, true, true);
|
||||
attacker.markDamage(power, blockerId, null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
||||
Permanent defendingCreature = game.getPermanent(entry.getKey());
|
||||
defendingCreature.markDamage(entry.getValue(), attacker.getId(), game, true, true);
|
||||
defendingCreature.markDamage(entry.getValue(), attacker.getId(), null, game, true, true);
|
||||
}
|
||||
} else {
|
||||
if (isAttacking) {
|
||||
|
|
@ -427,7 +429,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
Permanent blocker = game.getPermanent(blockerId);
|
||||
if (canDamage(blocker, first)) {
|
||||
if (!assignsDefendingPlayerAndOrDefendingCreaturesDividedDamage(blocker, blocker.getControllerId(), first, game, false)) {
|
||||
attacker.markDamage(getDamageValueFromPermanent(blocker, game), blocker.getId(), game, true, true);
|
||||
attacker.markDamage(getDamageValueFromPermanent(blocker, game), blocker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -475,7 +477,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
if (blocker != null && attacker != null) {
|
||||
if (canDamage(blocker, first)) {
|
||||
int damage = getDamageValueFromPermanent(blocker, game);
|
||||
attacker.markDamage(damage, blocker.getId(), game, true, true);
|
||||
attacker.markDamage(damage, blocker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -531,7 +533,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
|
||||
for (Map.Entry<UUID, Integer> entry : assigned.entrySet()) {
|
||||
Permanent attacker = game.getPermanent(entry.getKey());
|
||||
attacker.markDamage(entry.getValue(), blocker.getId(), game, true, true);
|
||||
attacker.markDamage(entry.getValue(), blocker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -540,12 +542,12 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
if (this.defenderIsPlaneswalker) {
|
||||
Permanent defender = game.getPermanent(defenderId);
|
||||
if (defender != null) {
|
||||
defender.markDamage(amount, attacker.getId(), game, true, true);
|
||||
defender.markDamage(amount, attacker.getId(), null, game, true, true);
|
||||
}
|
||||
} else {
|
||||
Player defender = game.getPlayer(defenderId);
|
||||
if (defender != null) {
|
||||
defender.damage(amount, attacker.getId(), game, true, true);
|
||||
defender.damage(amount, attacker.getId(), null, game, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -570,7 +572,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
*/
|
||||
public void addBlocker(UUID blockerId, UUID playerId, Game game) {
|
||||
for (UUID attackerId : attackers) {
|
||||
if (game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARE_BLOCKER, attackerId, blockerId, playerId))) {
|
||||
if (game.replaceEvent(new DeclareBlockerEvent(attackerId, blockerId, playerId))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -690,7 +692,7 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
|
|||
}
|
||||
for (UUID blockerId : blockers) {
|
||||
for (UUID attackerId : attackers) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BLOCKER_DECLARED, attackerId, blockerId, players.get(blockerId)));
|
||||
game.fireEvent(new BlockerDeclaredEvent(attackerId, blockerId, players.get(blockerId)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class DackFaydenEmblemTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.SPELL_CAST;
|
||||
return event.getType() == GameEvent.EventType.SPELL_CAST;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -137,7 +137,7 @@ class DackFaydenEmblemEffect extends ContinuousEffectImpl {
|
|||
for (UUID permanentId : fixedTargets.getTargets(game, source)) {
|
||||
Permanent permanent = game.getPermanent(permanentId);
|
||||
if (permanent != null) {
|
||||
permanent.changeControllerId(source.getControllerId(), game);
|
||||
permanent.changeControllerId(source.getControllerId(), game, source);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class DarettiScrapSavantTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.ZONE_CHANGE;
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -103,8 +103,7 @@ class JayaBallardReplacementEffect extends ReplacementEffectImpl {
|
|||
if (controller != null) {
|
||||
Card card = (Card) game.getState().getValue("JayaBallard");
|
||||
if (card != null) {
|
||||
controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.STACK, true);
|
||||
return true;
|
||||
((ZoneChangeEvent) event).setToZone(Zone.EXILED);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -112,7 +111,7 @@ class JayaBallardReplacementEffect extends ReplacementEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.ZONE_CHANGE;
|
||||
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ class MomirEffect extends OneShotEffect {
|
|||
}
|
||||
}
|
||||
if (token != null) {
|
||||
token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId(), false, false);
|
||||
token.putOntoBattlefield(1, game, source, source.getControllerId(), false, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class ObNixilisEmblemTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.DREW_CARD;
|
||||
return event.getType() == GameEvent.EventType.DREW_CARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class VenserTheSojournerSpellCastTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.SPELL_CAST;
|
||||
return event.getType() == GameEvent.EventType.SPELL_CAST;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ class DrawCardsActivePlayerEffect extends OneShotEffect {
|
|||
}
|
||||
Player player = game.getPlayer(game.getActivePlayerId());
|
||||
if (player != null) {
|
||||
player.drawCards(amount.calculate(game, source, this), source.getSourceId(), game);
|
||||
player.drawCards(amount.calculate(game, source, this), source, game);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class EdgeOfMalacolEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.UNTAP;
|
||||
return event.getType() == GameEvent.EventType.UNTAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class PanopticonTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.PLANESWALKED;
|
||||
return event.getType() == GameEvent.EventType.PLANESWALKED;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class UndercityReachesTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == EventType.DAMAGED_PLAYER;
|
||||
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
17
Mage/src/main/java/mage/game/events/AttachEvent.java
Normal file
17
Mage/src/main/java/mage/game/events/AttachEvent.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class AttachEvent extends GameEvent {
|
||||
|
||||
public AttachEvent(UUID targetPermanentId, Permanent attachment, Ability source) {
|
||||
super(GameEvent.EventType.ATTACH, targetPermanentId, null, attachment.getControllerId());
|
||||
this.setSourceId(attachment.getId());
|
||||
}
|
||||
}
|
||||
17
Mage/src/main/java/mage/game/events/AttachedEvent.java
Normal file
17
Mage/src/main/java/mage/game/events/AttachedEvent.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class AttachedEvent extends GameEvent {
|
||||
|
||||
public AttachedEvent(UUID targetPermanentId, Permanent attachment, Ability source) {
|
||||
super(GameEvent.EventType.ATTACHED, targetPermanentId, null, attachment.getControllerId());
|
||||
this.setSourceId(attachment.getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class AttackerDeclaredEvent extends GameEvent {
|
||||
|
||||
public AttackerDeclaredEvent(UUID targetId, UUID attackerId, UUID attackerControllerId) {
|
||||
super(GameEvent.EventType.ATTACKER_DECLARED, targetId, null, attackerControllerId);
|
||||
this.setSourceId(attackerId);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class BlockerDeclaredEvent extends GameEvent {
|
||||
|
||||
public BlockerDeclaredEvent(UUID attackerId, UUID blockerId, UUID blockerControllerId) {
|
||||
super(GameEvent.EventType.BLOCKER_DECLARED, attackerId, null, blockerControllerId);
|
||||
this.setSourceId(blockerId);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,15 +8,17 @@ import java.util.UUID;
|
|||
* @author TheElk801
|
||||
**/
|
||||
public class CoinFlippedEvent extends GameEvent {
|
||||
|
||||
private final boolean result;
|
||||
private final boolean chosen;
|
||||
private final boolean winnable;
|
||||
|
||||
CoinFlippedEvent(UUID playerId, UUID sourceId, boolean result, boolean chosen, boolean winnable) {
|
||||
super(EventType.COIN_FLIPPED, playerId, sourceId, playerId);
|
||||
super(GameEvent.EventType.COIN_FLIPPED, playerId, null, playerId);
|
||||
this.result = result;
|
||||
this.chosen = chosen;
|
||||
this.winnable = winnable;
|
||||
this.setSourceId(sourceId);
|
||||
}
|
||||
|
||||
public boolean getResult() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.MageObject;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CopiedStackObjectEvent extends GameEvent {
|
||||
|
||||
public CopiedStackObjectEvent(MageObject target, MageObject newCopy, UUID newControllerId) {
|
||||
super(GameEvent.EventType.COPIED_STACKOBJECT, newCopy.getId(), null, newControllerId);
|
||||
this.setSourceId(target.getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CopyStackObjectEvent extends GameEvent {
|
||||
|
||||
public CopyStackObjectEvent(Ability source, MageObject targetToCopy, UUID newControllerId, int amount) {
|
||||
super(GameEvent.EventType.COPY_STACKOBJECT, targetToCopy.getId(), source, newControllerId, amount, false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.costs.Cost;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class CostEvent extends GameEvent {
|
||||
|
||||
protected Cost cost;
|
||||
|
||||
public CostEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, Cost cost) {
|
||||
super(type, targetId, sourceId, playerId);
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
public Cost getCost() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
public void setCost(Cost cost) {
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +1,16 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.token.Token;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CreateTokenEvent extends GameEvent {
|
||||
|
||||
private Token token;
|
||||
|
||||
public CreateTokenEvent(UUID sourceId, UUID controllerId, int amount, Token token) {
|
||||
super(EventType.CREATE_TOKEN, null, sourceId, controllerId, amount, false);
|
||||
public CreateTokenEvent(Ability source, UUID controllerId, int amount, Token token) {
|
||||
super(GameEvent.EventType.CREATE_TOKEN, null, source, controllerId, amount, false);
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class CreatedTokenEvent extends GameEvent {
|
||||
|
||||
public CreatedTokenEvent(UUID sourceId, PermanentToken tokenPerm) {
|
||||
super(EventType.CREATED_TOKEN, tokenPerm.getId(), sourceId, tokenPerm.getControllerId());
|
||||
public CreatedTokenEvent(Ability source, PermanentToken tokenPerm) {
|
||||
super(GameEvent.EventType.CREATED_TOKEN, tokenPerm.getId(), source, tokenPerm.getControllerId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -10,8 +8,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public class DamageCreatureEvent extends DamageEvent {
|
||||
|
||||
public DamageCreatureEvent(UUID targetId, UUID sourceId, UUID playerId, int amount, boolean preventable, boolean combat) {
|
||||
super(EventType.DAMAGE_CREATURE, targetId, sourceId, playerId, amount, preventable, combat);
|
||||
public DamageCreatureEvent(UUID targetId, UUID damageSourceId, UUID targetControllerId, int amount, boolean preventable, boolean combat) {
|
||||
super(GameEvent.EventType.DAMAGE_CREATURE, targetId, damageSourceId, targetControllerId, amount, preventable, combat);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -12,9 +10,10 @@ public abstract class DamageEvent extends GameEvent {
|
|||
|
||||
protected boolean combat;
|
||||
|
||||
public DamageEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, int amount, boolean preventable, boolean combat) {
|
||||
super(type, targetId, sourceId, playerId, amount, preventable);
|
||||
public DamageEvent(EventType type, UUID targetId, UUID damageSourceId, UUID targetControllerId, int amount, boolean preventable, boolean combat) {
|
||||
super(type, targetId, null, targetControllerId, amount, preventable);
|
||||
this.combat = combat;
|
||||
this.setSourceId(damageSourceId);
|
||||
}
|
||||
|
||||
public boolean isCombatDamage() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -10,8 +8,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public class DamagePlaneswalkerEvent extends DamageEvent {
|
||||
|
||||
public DamagePlaneswalkerEvent(UUID targetId, UUID sourceId, UUID playerId, int amount, boolean preventable, boolean combat) {
|
||||
super(EventType.DAMAGE_PLANESWALKER, targetId, sourceId, playerId, amount, preventable, combat);
|
||||
public DamagePlaneswalkerEvent(UUID targetId, UUID damageSourceId, UUID targetControllerId, int amount, boolean preventable, boolean combat) {
|
||||
super(GameEvent.EventType.DAMAGE_PLANESWALKER, targetId, damageSourceId, targetControllerId, amount, preventable, combat);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -10,8 +8,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public class DamagePlayerEvent extends DamageEvent {
|
||||
|
||||
public DamagePlayerEvent(UUID targetId, UUID sourceId, UUID playerId, int amount, boolean preventable, boolean combat) {
|
||||
super(EventType.DAMAGE_PLAYER, targetId, sourceId, playerId, amount, preventable, combat);
|
||||
public DamagePlayerEvent(UUID targetId, UUID damageSourceId, UUID targetControllerId, int amount, boolean preventable, boolean combat) {
|
||||
super(GameEvent.EventType.DAMAGE_PLAYER, targetId, damageSourceId, targetControllerId, amount, preventable, combat);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public abstract class DamagedBatchEvent extends GameEvent {
|
|||
private final Set<DamagedEvent> events = new HashSet<>();
|
||||
|
||||
public DamagedBatchEvent(EventType type, Class<? extends DamagedEvent> damageClazz) {
|
||||
super(EventType.DAMAGED_PLAYER_BATCH, null, null, null);
|
||||
super(GameEvent.EventType.DAMAGED_PLAYER_BATCH, null, null, null);
|
||||
this.damageClazz = damageClazz;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ package mage.game.events;
|
|||
public class DamagedCreatureBatchEvent extends DamagedBatchEvent {
|
||||
|
||||
public DamagedCreatureBatchEvent() {
|
||||
super(EventType.DAMAGED_CREATURE_BATCH, DamagedCreatureEvent.class);
|
||||
super(GameEvent.EventType.DAMAGED_CREATURE_BATCH, DamagedCreatureEvent.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public class DamagedCreatureEvent extends DamagedEvent {
|
||||
|
||||
public DamagedCreatureEvent(UUID targetId, UUID sourceId, UUID playerId, int amount, boolean combat) {
|
||||
super(EventType.DAMAGED_CREATURE, targetId, sourceId, playerId, amount, combat);
|
||||
public DamagedCreatureEvent(UUID targetId, UUID attackerId, UUID playerId, int amount, boolean combat) {
|
||||
super(GameEvent.EventType.DAMAGED_CREATURE, targetId, attackerId, playerId, amount, combat);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ public abstract class DamagedEvent extends GameEvent {
|
|||
|
||||
protected boolean combat;
|
||||
|
||||
public DamagedEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, int amount, boolean combat) {
|
||||
super(type, targetId, sourceId, playerId, amount, false);
|
||||
public DamagedEvent(EventType type, UUID targetId, UUID attackerId, UUID playerId, int amount, boolean combat) {
|
||||
super(type, targetId, null, playerId, amount, false);
|
||||
this.combat = combat;
|
||||
this.setSourceId(attackerId);
|
||||
}
|
||||
|
||||
public boolean isCombatDamage() {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ package mage.game.events;
|
|||
public class DamagedPlaneswalkerBatchEvent extends DamagedBatchEvent {
|
||||
|
||||
public DamagedPlaneswalkerBatchEvent() {
|
||||
super(EventType.DAMAGED_PLANESWALKER_BATCH, DamagedPlaneswalkerEvent.class);
|
||||
super(GameEvent.EventType.DAMAGED_PLANESWALKER_BATCH, DamagedPlaneswalkerEvent.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -10,8 +8,9 @@ import java.util.UUID;
|
|||
*/
|
||||
public class DamagedPlaneswalkerEvent extends DamagedEvent {
|
||||
|
||||
public DamagedPlaneswalkerEvent(UUID targetId, UUID sourceId, UUID playerId, int amount, boolean combat) {
|
||||
super(EventType.DAMAGED_PLANESWALKER, targetId, sourceId, playerId, amount, combat);
|
||||
public DamagedPlaneswalkerEvent(UUID targetId, UUID attackerId, UUID playerId, int amount, boolean combat) {
|
||||
super(GameEvent.EventType.DAMAGED_PLANESWALKER, targetId, null, playerId, amount, combat);
|
||||
this.setSourceId(attackerId);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ package mage.game.events;
|
|||
public class DamagedPlayerBatchEvent extends DamagedBatchEvent {
|
||||
|
||||
public DamagedPlayerBatchEvent() {
|
||||
super(EventType.DAMAGED_PLAYER_BATCH, DamagedPlayerEvent.class);
|
||||
super(GameEvent.EventType.DAMAGED_PLAYER_BATCH, DamagedPlayerEvent.class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ import java.util.UUID;
|
|||
*/
|
||||
public class DamagedPlayerEvent extends DamagedEvent {
|
||||
|
||||
public DamagedPlayerEvent(UUID targetId, UUID sourceId, UUID playerId, int amount, boolean combat) {
|
||||
super(EventType.DAMAGED_PLAYER, targetId, sourceId, playerId, amount, combat);
|
||||
public DamagedPlayerEvent(UUID targetId, UUID attackerId, UUID playerId, int amount, boolean combat) {
|
||||
super(GameEvent.EventType.DAMAGED_PLAYER, targetId, attackerId, playerId, amount, combat);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class DeclareAttackerEvent extends GameEvent {
|
||||
|
||||
public DeclareAttackerEvent(UUID targetId, UUID attackerId, UUID attackerControllerId) {
|
||||
super(GameEvent.EventType.DECLARE_ATTACKER, targetId, null, attackerControllerId);
|
||||
this.setSourceId(attackerId);
|
||||
}
|
||||
}
|
||||
14
Mage/src/main/java/mage/game/events/DeclareBlockerEvent.java
Normal file
14
Mage/src/main/java/mage/game/events/DeclareBlockerEvent.java
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class DeclareBlockerEvent extends GameEvent {
|
||||
|
||||
public DeclareBlockerEvent(UUID attackerId, UUID blockerId, UUID blockerControllerId) {
|
||||
super(GameEvent.EventType.DECLARE_BLOCKER, attackerId, null, blockerControllerId);
|
||||
this.setSourceId(blockerId);
|
||||
}
|
||||
}
|
||||
21
Mage/src/main/java/mage/game/events/DrawCardEvent.java
Normal file
21
Mage/src/main/java/mage/game/events/DrawCardEvent.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class DrawCardEvent extends GameEvent {
|
||||
|
||||
public DrawCardEvent(UUID playerId, Ability source, GameEvent originalDrawEvent) {
|
||||
super(GameEvent.EventType.DRAW_CARD, playerId, source, playerId, 0, false);
|
||||
|
||||
// source of draw events must be kept between replacements, example: UnpredictableCycloneTest
|
||||
if (originalDrawEvent != null) {
|
||||
this.addAppliedEffects(originalDrawEvent.getAppliedEffects());
|
||||
this.setSourceId(originalDrawEvent.getSourceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Mage/src/main/java/mage/game/events/DrawCardsEvent.java
Normal file
21
Mage/src/main/java/mage/game/events/DrawCardsEvent.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class DrawCardsEvent extends GameEvent {
|
||||
|
||||
public DrawCardsEvent(UUID playerId, Ability source, GameEvent originalDrawEvent, int amount) {
|
||||
super(GameEvent.EventType.DRAW_CARDS, playerId, source, playerId, amount, false);
|
||||
|
||||
// source of draw events must be kept between replacements, example: UnpredictableCycloneTest
|
||||
if (originalDrawEvent != null) {
|
||||
this.addAppliedEffects(originalDrawEvent.getAppliedEffects());
|
||||
this.setSourceId(originalDrawEvent.getSourceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Mage/src/main/java/mage/game/events/DrewCardEvent.java
Normal file
21
Mage/src/main/java/mage/game/events/DrewCardEvent.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class DrewCardEvent extends GameEvent {
|
||||
|
||||
public DrewCardEvent(UUID cardId, UUID playerId, Ability source, GameEvent originalDrawEvent) {
|
||||
super(EventType.DREW_CARD, cardId, source, playerId, 0, false);
|
||||
|
||||
// source of draw events must be kept between replacements, example: UnpredictableCycloneTest
|
||||
if (originalDrawEvent != null) {
|
||||
//this.addAppliedEffects(originalDrawEvent.getAppliedEffects()); // event can't used for replace, so no needs in applied effects
|
||||
this.setSourceId(originalDrawEvent.getSourceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Mage/src/main/java/mage/game/events/EnchantPlayerEvent.java
Normal file
17
Mage/src/main/java/mage/game/events/EnchantPlayerEvent.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class EnchantPlayerEvent extends GameEvent {
|
||||
|
||||
public EnchantPlayerEvent(UUID targetId, Permanent attachment, Ability source) {
|
||||
super(GameEvent.EventType.ENCHANT_PLAYER, targetId, null, attachment.getControllerId());
|
||||
this.setSourceId(attachment.getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class EnchantedPlayerEvent extends GameEvent {
|
||||
|
||||
public EnchantedPlayerEvent(UUID targetId, Permanent attachment, Ability source) {
|
||||
super(GameEvent.EventType.ENCHANTED_PLAYER, targetId, null, attachment.getControllerId());
|
||||
this.setSourceId(attachment.getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
package mage.game.events;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.EnterEventType;
|
||||
import static mage.constants.EnterEventType.SELF;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -16,12 +18,20 @@ public class EntersTheBattlefieldEvent extends GameEvent {
|
|||
private final Zone fromZone;
|
||||
private Permanent target;
|
||||
|
||||
public EntersTheBattlefieldEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone) {
|
||||
this(target, sourceId, playerId, fromZone, EnterEventType.OTHER);
|
||||
public EntersTheBattlefieldEvent(Permanent target, Ability source, UUID playerId, Zone fromZone) {
|
||||
this(target, source, playerId, fromZone, EnterEventType.OTHER);
|
||||
}
|
||||
|
||||
public EntersTheBattlefieldEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, EnterEventType enterType) {
|
||||
super(EventType.ENTERS_THE_BATTLEFIELD, target.getId(), sourceId, playerId);
|
||||
/**
|
||||
*
|
||||
* @param target
|
||||
* @param source can be null for default game actions like cheats
|
||||
* @param playerId
|
||||
* @param fromZone
|
||||
* @param enterType
|
||||
*/
|
||||
public EntersTheBattlefieldEvent(Permanent target, Ability source, UUID playerId, Zone fromZone, EnterEventType enterType) {
|
||||
super(GameEvent.EventType.ENTERS_THE_BATTLEFIELD, target.getId(), source, playerId);
|
||||
switch (enterType) {
|
||||
case SELF:
|
||||
type = EventType.ENTERS_THE_BATTLEFIELD_SELF;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -13,8 +14,8 @@ public class FlipCoinEvent extends GameEvent {
|
|||
private final boolean winnable;
|
||||
private int flipCount = 1;
|
||||
|
||||
public FlipCoinEvent(UUID playerId, UUID sourceId, boolean result, boolean chosen, boolean winnable) {
|
||||
super(EventType.FLIP_COIN, playerId, sourceId, playerId);
|
||||
public FlipCoinEvent(UUID playerId, Ability source, boolean result, boolean chosen, boolean winnable) {
|
||||
super(GameEvent.EventType.FLIP_COIN, playerId, source, playerId);
|
||||
this.result = result;
|
||||
this.chosen = chosen;
|
||||
this.winnable = winnable;
|
||||
|
|
@ -52,7 +53,7 @@ public class FlipCoinEvent extends GameEvent {
|
|||
this.flipCount = flipCount;
|
||||
}
|
||||
|
||||
public CoinFlippedEvent getFlippedEvent() {
|
||||
public CoinFlippedEvent createFlippedEvent() {
|
||||
return new CoinFlippedEvent(playerId, sourceId, result, chosen, winnable);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package mage.game.events;
|
|||
|
||||
import mage.ApprovingObject;
|
||||
import mage.MageIdentifier;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Zone;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -17,7 +18,7 @@ public class GameEvent implements Serializable {
|
|||
protected EventType type;
|
||||
protected UUID id;
|
||||
protected UUID targetId;
|
||||
protected UUID sourceId;
|
||||
protected UUID sourceId; // TODO: check sourceId usage in all events, it must gets sourceId from source ability only, not other values
|
||||
protected UUID playerId;
|
||||
protected int amount;
|
||||
// flags:
|
||||
|
|
@ -25,6 +26,7 @@ public class GameEvent implements Serializable {
|
|||
// for combat damage: event is preventable damage
|
||||
// for discard: event is result of effect (1) or result of cost (0)
|
||||
// for prevent damage: try to prevent combat damage (1) or other damage (0)
|
||||
// for tapped: is it tapped for combat (1) or for another reason (0)
|
||||
protected boolean flag;
|
||||
protected String data;
|
||||
protected Zone zone;
|
||||
|
|
@ -70,11 +72,16 @@ public class GameEvent implements Serializable {
|
|||
*/
|
||||
ZONE_CHANGE,
|
||||
ZONE_CHANGE_GROUP,
|
||||
DRAW_CARDS, // applies to an instruction to draw more than one card before any replacement effects apply to individual cards drawn
|
||||
DRAW_CARDS, // event calls for multi draws only (if player draws 2+ cards at once)
|
||||
DRAW_CARD, DREW_CARD,
|
||||
EXPLORED,
|
||||
ECHO_PAID,
|
||||
MIRACLE_CARD_REVEALED,
|
||||
/* MADNESS_CARD_EXILED,
|
||||
targetId id of the card with madness
|
||||
sourceId original id of the madness ability
|
||||
playerId controller of the card
|
||||
*/
|
||||
MADNESS_CARD_EXILED,
|
||||
INVESTIGATED,
|
||||
KICKED,
|
||||
|
|
@ -84,6 +91,9 @@ public class GameEvent implements Serializable {
|
|||
playerId controller of the convoked spell
|
||||
*/
|
||||
CONVOKED,
|
||||
/* DISCARD_CARD
|
||||
flag event is result of effect (1) or result of cost (0)
|
||||
*/
|
||||
DISCARD_CARD,
|
||||
DISCARDED_CARD,
|
||||
DISCARDED_CARDS,
|
||||
|
|
@ -101,13 +111,20 @@ public class GameEvent implements Serializable {
|
|||
*/
|
||||
DAMAGED_PLAYER,
|
||||
DAMAGED_PLAYER_BATCH,
|
||||
/* DAMAGE_CAUSES_LIFE_LOSS,
|
||||
targetId the id of the damaged player
|
||||
sourceId sourceId of the ability which caused the damage, can be null for default events like combat
|
||||
playerId the id of the damged player
|
||||
amount amount of damage
|
||||
flag is it combat damage
|
||||
*/
|
||||
DAMAGE_CAUSES_LIFE_LOSS,
|
||||
PLAYER_LIFE_CHANGE,
|
||||
GAIN_LIFE, GAINED_LIFE,
|
||||
LOSE_LIFE, LOST_LIFE,
|
||||
/* LOSE_LIFE + LOST_LIFE
|
||||
targetId the id of the player loosing life
|
||||
sourceId the id of the player loosing life
|
||||
sourceId sourceId of the ability which caused the lose
|
||||
playerId the id of the player loosing life
|
||||
amount amount of life loss
|
||||
flag true = from comabat damage - other from non combat damage
|
||||
|
|
@ -172,7 +189,19 @@ public class GameEvent implements Serializable {
|
|||
*/
|
||||
TRIGGERED_ABILITY,
|
||||
RESOLVING_ABILITY,
|
||||
COPY_STACKOBJECT, COPIED_STACKOBJECT,
|
||||
/* COPY_STACKOBJECT
|
||||
targetId id of the spell/ability to copy
|
||||
sourceId id of the object with copy ability
|
||||
playerId id of the player who will be control new copied spell/ability
|
||||
amount number on copies
|
||||
*/
|
||||
COPY_STACKOBJECT,
|
||||
/* COPIED_STACKOBJECT, TODO: make same logic in params for COPY_STACKOBJECT and COPIED_STACKOBJECT
|
||||
targetId id of the new copied spell/ability
|
||||
sourceId id of the spell/ability to copy
|
||||
playerId id of the player who will be control new copied spell/ability
|
||||
*/
|
||||
COPIED_STACKOBJECT,
|
||||
/* ADD_MANA
|
||||
targetId id of the ability that added the mana
|
||||
sourceId sourceId of the ability that added the mana
|
||||
|
|
@ -192,11 +221,19 @@ public class GameEvent implements Serializable {
|
|||
sourceId sourceId of the mana source
|
||||
playerId controller of the ability the mana was paid for
|
||||
amount not used for this event
|
||||
flag indicates a special condition
|
||||
data originalId of the mana producing ability
|
||||
flag indicates a special condition of mana
|
||||
data originalId of the mana producing ability as string (converted from UUID)
|
||||
*/
|
||||
MANA_PAID,
|
||||
LOSES, LOST, WINS, DRAW_PLAYER,
|
||||
/* TARGET
|
||||
targetId id of the targeting card
|
||||
sourceId id of the ability's object that try to targeting
|
||||
playerId player who try to targeting (can be different from source ability's controller)
|
||||
TODO: BUT there is isLegal(Ability source, Game game) code and it uses only source ability's controller,
|
||||
so some abilities can be fizzled on resolve cause no legal targets?
|
||||
amount not used for this event
|
||||
*/
|
||||
TARGET, TARGETED,
|
||||
/* TARGETS_VALID
|
||||
targetId id of the spell or id of stack ability the targets were set to
|
||||
|
|
@ -239,11 +276,13 @@ public class GameEvent implements Serializable {
|
|||
*/
|
||||
DECLARING_BLOCKERS,
|
||||
DECLARED_BLOCKERS,
|
||||
/* DECLARING_BLOCKERS
|
||||
targetId id of the blocking player
|
||||
sourceId id of the blocking player
|
||||
DECLARE_BLOCKER,
|
||||
/* BLOCKER_DECLARED
|
||||
targetId attacker id
|
||||
sourceId blocker id
|
||||
playerId blocker controller id
|
||||
*/
|
||||
DECLARE_BLOCKER, BLOCKER_DECLARED,
|
||||
BLOCKER_DECLARED,
|
||||
CREATURE_BLOCKED,
|
||||
BATCH_BLOCK_NONCOMBAT,
|
||||
UNBLOCKED_ATTACKER,
|
||||
|
|
@ -268,7 +307,15 @@ public class GameEvent implements Serializable {
|
|||
ENTERS_THE_BATTLEFIELD_CONTROL, // 616.1b
|
||||
ENTERS_THE_BATTLEFIELD_COPY, // 616.1c
|
||||
ENTERS_THE_BATTLEFIELD, // 616.1d
|
||||
TAP, TAPPED,
|
||||
TAP,
|
||||
/* TAPPED,
|
||||
targetId tapped permanent
|
||||
sourceId id of the abilitity's source (can be null for standard tap actions like combat)
|
||||
playerId controller of the tapped permanent
|
||||
amount not used for this event
|
||||
flag is it tapped for combat
|
||||
*/
|
||||
TAPPED,
|
||||
TAPPED_FOR_MANA,
|
||||
/* TAPPED_FOR_MANA
|
||||
During calculation of the available mana for a player the "TappedForMana" event is fired to simulate triggered mana production.
|
||||
|
|
@ -281,14 +328,14 @@ public class GameEvent implements Serializable {
|
|||
TRANSFORM, TRANSFORMED,
|
||||
ADAPT,
|
||||
BECOMES_MONSTROUS,
|
||||
BECOMES_EXERTED,
|
||||
/* BECOMES_EXERTED
|
||||
targetId id of the exerted creature
|
||||
sourceId id of the exerted creature
|
||||
playerId playerId of the player that controlls the creature
|
||||
sourceId sourceId of the ability that triggered the event (do exert)
|
||||
playerId player who makes the exert (can be different from permanent's controller)
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
BECOMES_EXERTED,
|
||||
BECOMES_RENOWNED,
|
||||
/* BECOMES_MONARCH
|
||||
targetId playerId of the player that becomes the monarch
|
||||
|
|
@ -336,21 +383,44 @@ public class GameEvent implements Serializable {
|
|||
EMBALMED_CREATURE,
|
||||
ETERNALIZED_CREATURE,
|
||||
ATTACH, ATTACHED,
|
||||
STAY_ATTACHED,
|
||||
UNATTACH, UNATTACHED,
|
||||
/* ATTACH, ATTACHED,
|
||||
UNATTACH, UNATTACHED,
|
||||
targetId id of the permanent who get/lose attachment
|
||||
sourceId id of the attachment
|
||||
playerId player who control the attachment
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
STAY_ATTACHED,
|
||||
ADD_COUNTER, COUNTER_ADDED,
|
||||
ADD_COUNTERS, COUNTERS_ADDED,
|
||||
COUNTER_REMOVED, COUNTERS_REMOVED,
|
||||
LOSE_CONTROL,
|
||||
/* LOST_CONTROL
|
||||
targetId id of the creature that lost control
|
||||
sourceId id of the creature that lost control
|
||||
sourceId null
|
||||
playerId player that controlles the creature before
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
LOST_CONTROL,
|
||||
GAIN_CONTROL, GAINED_CONTROL,
|
||||
/* GAIN_CONTROL
|
||||
targetId id of the permanent that trying to get control
|
||||
sourceId null
|
||||
playerId new player that try to get control of permanent
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
GAIN_CONTROL,
|
||||
/* GAINED_CONTROL
|
||||
targetId id of the permanent that got control
|
||||
sourceId null
|
||||
playerId new player that got control of permanent
|
||||
amount not used for this event
|
||||
flag not used for this event
|
||||
*/
|
||||
GAINED_CONTROL,
|
||||
CREATE_TOKEN, CREATED_TOKEN,
|
||||
/* REGENERATE
|
||||
targetId id of the creature to regenerate
|
||||
|
|
@ -370,79 +440,69 @@ public class GameEvent implements Serializable {
|
|||
CUSTOM_EVENT
|
||||
}
|
||||
|
||||
public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId) {
|
||||
this(type, null, targetId, sourceId, playerId, 0, false);
|
||||
public GameEvent(EventType type, UUID targetId, Ability source, UUID playerId) {
|
||||
this(type, null, targetId, source, playerId, 0, false);
|
||||
}
|
||||
|
||||
public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, ApprovingObject approvingObject) {
|
||||
this(type, null, targetId, sourceId, playerId, 0, false, approvingObject);
|
||||
public GameEvent(EventType type, UUID targetId, Ability source, UUID playerId, ApprovingObject approvingObject) {
|
||||
this(type, null, targetId, source, playerId, 0, false, approvingObject);
|
||||
}
|
||||
|
||||
public GameEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag) {
|
||||
this(type, null, targetId, sourceId, playerId, amount, flag);
|
||||
public GameEvent(EventType type, UUID targetId, Ability source, UUID playerId, int amount, boolean flag) {
|
||||
this(type, null, targetId, source, playerId, amount, flag);
|
||||
}
|
||||
|
||||
public GameEvent(UUID customEventType, UUID targetId, UUID sourceId, UUID playerId) {
|
||||
this(EventType.CUSTOM_EVENT, customEventType, targetId, sourceId, playerId, 0, false);
|
||||
public GameEvent(UUID customEventType, UUID targetId, Ability source, UUID playerId) {
|
||||
this(EventType.CUSTOM_EVENT, customEventType, targetId, source, playerId, 0, false);
|
||||
}
|
||||
|
||||
public GameEvent(UUID customEventType, UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag) {
|
||||
this(EventType.CUSTOM_EVENT, customEventType, targetId, sourceId, playerId, amount, flag);
|
||||
public GameEvent(UUID customEventType, UUID targetId, Ability source, UUID playerId, int amount, boolean flag) {
|
||||
this(EventType.CUSTOM_EVENT, customEventType, targetId, source, playerId, amount, flag);
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, int amount) {
|
||||
return new GameEvent(type, targetId, sourceId, playerId, amount, false);
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, Ability source, UUID playerId, int amount) {
|
||||
return new GameEvent(type, targetId, source, playerId, amount, false);
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId) {
|
||||
return new GameEvent(type, targetId, sourceId, playerId);
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, Ability source, UUID playerId) {
|
||||
return new GameEvent(type, targetId, source, playerId);
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, ApprovingObject approvingObject) {
|
||||
return new GameEvent(type, targetId, sourceId, playerId, approvingObject);
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, Ability source, UUID playerId, ApprovingObject approvingObject) {
|
||||
return new GameEvent(type, targetId, source, playerId, approvingObject);
|
||||
}
|
||||
|
||||
@Deprecated // usage must be replaced by getEvent with source ability
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, UUID playerId) {
|
||||
return new GameEvent(type, targetId, null, playerId);
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, String data, int amount) {
|
||||
GameEvent event = getEvent(type, targetId, sourceId, playerId);
|
||||
public static GameEvent getEvent(EventType type, UUID targetId, Ability source, UUID playerId, String data, int amount) {
|
||||
GameEvent event = getEvent(type, targetId, source, playerId);
|
||||
event.setAmount(amount);
|
||||
event.setData(data);
|
||||
return event;
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(UUID customEventType, UUID targetId, UUID sourceId, UUID playerId, int amount) {
|
||||
return new GameEvent(customEventType, targetId, sourceId, playerId, amount, false);
|
||||
public static GameEvent getEvent(UUID customEventType, UUID targetId, Ability source, UUID playerId, int amount) {
|
||||
return new GameEvent(customEventType, targetId, source, playerId, amount, false);
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(UUID customEventType, UUID targetId, UUID sourceId, UUID playerId) {
|
||||
return new GameEvent(customEventType, targetId, sourceId, playerId);
|
||||
public static GameEvent getEvent(UUID customEventType, UUID targetId, Ability source, UUID playerId) {
|
||||
return new GameEvent(customEventType, targetId, source, playerId);
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(UUID customEventType, UUID targetId, UUID playerId) {
|
||||
return new GameEvent(customEventType, targetId, null, playerId);
|
||||
}
|
||||
|
||||
public static GameEvent getEvent(UUID customEventType, UUID targetId, UUID playerId, String data, int amount) {
|
||||
GameEvent event = getEvent(customEventType, targetId, playerId);
|
||||
event.setAmount(amount);
|
||||
event.setData(data);
|
||||
return event;
|
||||
private GameEvent(EventType type, UUID customEventType, UUID targetId, Ability source, UUID playerId, int amount, boolean flag)
|
||||
{
|
||||
this(type, customEventType, targetId, source, playerId, amount, flag, null);
|
||||
}
|
||||
|
||||
private GameEvent(EventType type, UUID customEventType,
|
||||
UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag) {
|
||||
this(type, customEventType, targetId, sourceId, playerId, amount, flag, null);
|
||||
}
|
||||
|
||||
private GameEvent(EventType type, UUID customEventType,
|
||||
UUID targetId, UUID sourceId, UUID playerId, int amount, boolean flag, ApprovingObject approvingObject) {
|
||||
UUID targetId, Ability source, UUID playerId, int amount, boolean flag, ApprovingObject approvingObject) {
|
||||
this.type = type;
|
||||
this.customEventType = customEventType;
|
||||
this.targetId = targetId;
|
||||
this.sourceId = sourceId;
|
||||
this.sourceId = source == null ? null : source.getSourceId();
|
||||
this.amount = amount;
|
||||
this.playerId = playerId;
|
||||
this.flag = flag;
|
||||
|
|
@ -585,4 +645,13 @@ public class GameEvent implements Serializable {
|
|||
}
|
||||
return identifier.equals(approvingObject.getApprovingAbility().getIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom sourceId setup for some events (use it in constructor). TODO: replace all custom sourceId to normal event classes
|
||||
*
|
||||
* @param sourceId
|
||||
*/
|
||||
protected void setSourceId(UUID sourceId) {
|
||||
this.sourceId = sourceId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.target.Target;
|
||||
|
||||
import java.util.UUID;
|
||||
|
|
@ -15,12 +16,12 @@ public class LibrarySearchedEvent extends GameEvent {
|
|||
* Searched library event (after library searching finished). Return false on replaceEvent to
|
||||
*
|
||||
* @param targetPlayerId whose library searched
|
||||
* @param sourceId source of the searching effect
|
||||
* @param source source ability of the searching effect
|
||||
* @param playerId who must search the library
|
||||
* @param searchedTarget founded cards (targets list can be changed by replace events, see Opposition Agent)
|
||||
*/
|
||||
public LibrarySearchedEvent(UUID targetPlayerId, UUID sourceId, UUID playerId, Target searchedTarget) {
|
||||
super(EventType.LIBRARY_SEARCHED, targetPlayerId, sourceId, playerId, searchedTarget.getTargets().size(), false);
|
||||
public LibrarySearchedEvent(UUID targetPlayerId, Ability source, UUID playerId, Target searchedTarget) {
|
||||
super(GameEvent.EventType.LIBRARY_SEARCHED, targetPlayerId, source, playerId, searchedTarget.getTargets().size(), false);
|
||||
this.searchedTarget = searchedTarget;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class MadnessCardExiledEvent extends GameEvent {
|
||||
|
||||
public MadnessCardExiledEvent(UUID cardId, Ability source, UUID controllerId) {
|
||||
super(GameEvent.EventType.MADNESS_CARD_EXILED, cardId, null, controllerId);
|
||||
this.setSourceId(source.getOriginalId()); // save ability's id
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ package mage.game.events;
|
|||
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
@ -13,8 +14,8 @@ public class ManaEvent extends GameEvent {
|
|||
|
||||
protected Mana mana;
|
||||
|
||||
public ManaEvent(EventType type, UUID targetId, UUID sourceId, UUID playerId, Mana mana) {
|
||||
super(type, targetId, sourceId, playerId);
|
||||
public ManaEvent(EventType type, UUID targetId, Ability source, UUID playerId, Mana mana) {
|
||||
super(type, targetId, source, playerId);
|
||||
this.mana = mana;
|
||||
}
|
||||
|
||||
|
|
|
|||
17
Mage/src/main/java/mage/game/events/ManaPaidEvent.java
Normal file
17
Mage/src/main/java/mage/game/events/ManaPaidEvent.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class ManaPaidEvent extends GameEvent {
|
||||
|
||||
public ManaPaidEvent(Ability abilityToPay, UUID manaSourceId, boolean manaFlag, UUID manaOriginalId) {
|
||||
super(GameEvent.EventType.MANA_PAID, abilityToPay.getId(), null, abilityToPay.getControllerId(), 0, manaFlag);
|
||||
this.setSourceId(manaSourceId);
|
||||
this.setData(manaOriginalId.toString());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
|
||||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -12,8 +12,8 @@ public class NumberOfTriggersEvent extends GameEvent {
|
|||
|
||||
private final GameEvent sourceEvent;
|
||||
|
||||
public NumberOfTriggersEvent(UUID controllerOfAbilityId, UUID sourceOfTrigger, GameEvent sourceEvent) {
|
||||
super(EventType.NUMBER_OF_TRIGGERS, null, sourceOfTrigger, controllerOfAbilityId);
|
||||
public NumberOfTriggersEvent(Ability triggeredAbility, GameEvent sourceEvent) {
|
||||
super(GameEvent.EventType.NUMBER_OF_TRIGGERS, null, triggeredAbility, triggeredAbility.getControllerId());
|
||||
this.sourceEvent = sourceEvent;
|
||||
this.amount = 1; // Number of times to trigger. Panharmonicon can change this.
|
||||
}
|
||||
|
|
|
|||
16
Mage/src/main/java/mage/game/events/PhaseChangedEvent.java
Normal file
16
Mage/src/main/java/mage/game/events/PhaseChangedEvent.java
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.game.turn.TurnMod;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class PhaseChangedEvent extends GameEvent {
|
||||
|
||||
public PhaseChangedEvent(UUID playerId, TurnMod extraTurnMode) {
|
||||
super(GameEvent.EventType.PHASE_CHANGED, playerId, null, playerId);
|
||||
this.setSourceId(extraTurnMode == null ? null : extraTurnMode.getId());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -7,8 +9,9 @@ import java.util.UUID;
|
|||
*/
|
||||
public class PreventDamageEvent extends GameEvent {
|
||||
|
||||
public PreventDamageEvent(UUID targetId, UUID sourceId, UUID playerId, int damageToPrevent, boolean isCombatDamage) {
|
||||
super(EventType.PREVENT_DAMAGE, targetId, sourceId, playerId, damageToPrevent, isCombatDamage);
|
||||
public PreventDamageEvent(UUID targetId, UUID attackerId, Ability source, UUID playerId, int damageToPrevent, boolean isCombatDamage) {
|
||||
super(GameEvent.EventType.PREVENT_DAMAGE, targetId, null, playerId, damageToPrevent, isCombatDamage);
|
||||
this.setSourceId(attackerId);
|
||||
}
|
||||
|
||||
public boolean isCombatDamage() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class PreventedDamageEvent extends GameEvent {
|
||||
|
||||
public PreventedDamageEvent(UUID targetId, UUID attackerId, Ability source, UUID playerId, int preventedDamage) {
|
||||
super(GameEvent.EventType.PREVENTED_DAMAGE, targetId, null, playerId, preventedDamage, false);
|
||||
this.setSourceId(attackerId);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -17,8 +19,8 @@ public class SearchLibraryEvent extends GameEvent {
|
|||
* @param playerId who must search the library (also see searchingControllerId)
|
||||
* @param amount cards amount to search
|
||||
*/
|
||||
public SearchLibraryEvent(UUID targetPlayerId, UUID sourceId, UUID playerId, int amount) {
|
||||
super(GameEvent.EventType.SEARCH_LIBRARY, targetPlayerId, sourceId, playerId, amount, false);
|
||||
public SearchLibraryEvent(UUID targetPlayerId, Ability source, UUID playerId, int amount) {
|
||||
super(GameEvent.EventType.SEARCH_LIBRARY, targetPlayerId, source, playerId, amount, false);
|
||||
this.searchingControllerId = playerId;
|
||||
}
|
||||
|
||||
|
|
|
|||
18
Mage/src/main/java/mage/game/events/StayAttachedEvent.java
Normal file
18
Mage/src/main/java/mage/game/events/StayAttachedEvent.java
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class StayAttachedEvent extends GameEvent {
|
||||
|
||||
public StayAttachedEvent(UUID targetId, UUID attachmentId, Ability source) {
|
||||
super(GameEvent.EventType.STAY_ATTACHED, targetId, null, null);
|
||||
this.setSourceId(attachmentId);
|
||||
}
|
||||
}
|
||||
30
Mage/src/main/java/mage/game/events/TargetEvent.java
Normal file
30
Mage/src/main/java/mage/game/events/TargetEvent.java
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class TargetEvent extends GameEvent {
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* @param sourceId
|
||||
* @param sourceControllerId can be different from real controller (example: ability instructs another player to targeting)
|
||||
*/
|
||||
public TargetEvent(Card target, UUID sourceId, UUID sourceControllerId) {
|
||||
super(GameEvent.EventType.TARGET, target.getId(), null, sourceControllerId);
|
||||
this.setSourceId(sourceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param targetId
|
||||
* @param source
|
||||
*/
|
||||
public TargetEvent(UUID targetId, Ability source) {
|
||||
super(GameEvent.EventType.TARGET, targetId, source, source.getControllerId());
|
||||
}
|
||||
}
|
||||
17
Mage/src/main/java/mage/game/events/UnattachEvent.java
Normal file
17
Mage/src/main/java/mage/game/events/UnattachEvent.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class UnattachEvent extends GameEvent {
|
||||
|
||||
public UnattachEvent(UUID targetId, UUID attachmentId, Permanent attachment, Ability source) {
|
||||
super(GameEvent.EventType.UNATTACH, targetId, null, attachment == null ? null : attachment.getControllerId());
|
||||
this.setSourceId(attachmentId);
|
||||
}
|
||||
}
|
||||
17
Mage/src/main/java/mage/game/events/UnattachedEvent.java
Normal file
17
Mage/src/main/java/mage/game/events/UnattachedEvent.java
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package mage.game.events;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class UnattachedEvent extends GameEvent {
|
||||
|
||||
public UnattachedEvent(UUID targetId, UUID attachmentId, Permanent attachment, Ability source) {
|
||||
super(GameEvent.EventType.UNATTACHED, targetId, null, attachment == null ? null : attachment.getControllerId());
|
||||
this.setSourceId(attachmentId);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@ package mage.game.events;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
|
|
@ -15,34 +17,39 @@ public class ZoneChangeEvent extends GameEvent {
|
|||
private Zone toZone;
|
||||
private Zone originalToZone;
|
||||
private Permanent target;
|
||||
private Ability source; // link to source ability, can be null in rare situations
|
||||
|
||||
public ZoneChangeEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone) {
|
||||
super(EventType.ZONE_CHANGE, target.getId(), sourceId, playerId);
|
||||
public ZoneChangeEvent(Permanent target, Ability source, UUID playerId, Zone fromZone, Zone toZone) {
|
||||
super(GameEvent.EventType.ZONE_CHANGE, target.getId(), source, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.setToZone(toZone);
|
||||
this.target = target;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public ZoneChangeEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
|
||||
super(EventType.ZONE_CHANGE, target.getId(), sourceId, playerId);
|
||||
public ZoneChangeEvent(Permanent target, Ability source, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
|
||||
super(GameEvent.EventType.ZONE_CHANGE, target.getId(), source, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.setToZone(toZone);
|
||||
this.target = target;
|
||||
this.source = source;
|
||||
if (appliedEffects != null) {
|
||||
this.appliedEffects = appliedEffects;
|
||||
}
|
||||
}
|
||||
|
||||
public ZoneChangeEvent(UUID targetId, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone) {
|
||||
super(EventType.ZONE_CHANGE, targetId, sourceId, playerId);
|
||||
public ZoneChangeEvent(UUID targetId, Ability source, UUID playerId, Zone fromZone, Zone toZone) {
|
||||
super(GameEvent.EventType.ZONE_CHANGE, targetId, source, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.setToZone(toZone);
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public ZoneChangeEvent(UUID targetId, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
|
||||
super(EventType.ZONE_CHANGE, targetId, sourceId, playerId);
|
||||
public ZoneChangeEvent(UUID targetId, Ability source, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
|
||||
super(GameEvent.EventType.ZONE_CHANGE, targetId, source, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.setToZone(toZone);
|
||||
this.source = source;
|
||||
if (appliedEffects != null) {
|
||||
this.appliedEffects = appliedEffects;
|
||||
}
|
||||
|
|
@ -87,4 +94,13 @@ public class ZoneChangeEvent extends GameEvent {
|
|||
return originalToZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source ability of the event, can be null in rare cases
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Ability getSource() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class ZoneChangeGroupEvent extends GameEvent {
|
|||
private final Set<PermanentToken> tokens;
|
||||
|
||||
public ZoneChangeGroupEvent(Set<Card> cards, Set<PermanentToken> tokens, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone) {
|
||||
super(EventType.ZONE_CHANGE_GROUP, null, sourceId, playerId);
|
||||
super(GameEvent.EventType.ZONE_CHANGE_GROUP, null, null, playerId);
|
||||
this.fromZone = fromZone;
|
||||
this.toZone = toZone;
|
||||
this.cards = cards;
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
boolean untap(Game game);
|
||||
|
||||
boolean tap(Game game);
|
||||
boolean tap(Ability source, Game game);
|
||||
|
||||
boolean tap(boolean forCombat, Game game);
|
||||
boolean tap(boolean forCombat, Ability source, Game game);
|
||||
|
||||
/**
|
||||
* use tap(game)
|
||||
|
|
@ -91,25 +91,23 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
int getAttachedToZoneChangeCounter();
|
||||
|
||||
void attachTo(UUID permanentId, Game game);
|
||||
void attachTo(UUID permanentId, Ability source, Game game);
|
||||
|
||||
void unattach(Game game);
|
||||
|
||||
// boolean addAttachment(UUID permanentId, Game game);
|
||||
//
|
||||
// boolean removeAttachment(UUID permanentId, Game game);
|
||||
boolean canBeTargetedBy(MageObject source, UUID controllerId, Game game);
|
||||
|
||||
boolean hasProtectionFrom(MageObject source, Game game);
|
||||
|
||||
/**
|
||||
* @param source
|
||||
* @param attachment
|
||||
* @param source can be null for default checks like state base
|
||||
* @param game
|
||||
* @param silentMode - use it to ignore warning message for users (e.g. for
|
||||
* checking only)
|
||||
* @return
|
||||
*/
|
||||
boolean cantBeAttachedBy(MageObject source, Game game, boolean silentMode);
|
||||
boolean cantBeAttachedBy(MageObject attachment, Ability source, Game game, boolean silentMode);
|
||||
|
||||
boolean wasControlledFromStartOfControllerTurn();
|
||||
|
||||
|
|
@ -117,23 +115,36 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
int getDamage();
|
||||
|
||||
int damage(int damage, UUID sourceId, Game game);
|
||||
int damage(int damage, UUID attackerId, Ability source, Game game);
|
||||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable);
|
||||
|
||||
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, List<UUID> appliedEffects);
|
||||
int damage(int damage, UUID attackerId, Ability source, Game game, boolean combat, boolean preventable);
|
||||
|
||||
/**
|
||||
* used in combat only to deal damage at the same time
|
||||
* Uses in replace events only
|
||||
*
|
||||
* @param damage
|
||||
* @param sourceId
|
||||
* @param attackerId id of the permanent or player who make damage (source.getSourceId() in most cases)
|
||||
* @param source can be null for default game actions like combat
|
||||
* @param game
|
||||
* @param combat
|
||||
* @param preventable
|
||||
* @param appliedEffects
|
||||
* @return
|
||||
*/
|
||||
int damage(int damage, UUID attackerId, Ability source, Game game, boolean combat, boolean preventable, List<UUID> appliedEffects);
|
||||
|
||||
/**
|
||||
* Uses in combat only to deal damage at the same time
|
||||
*
|
||||
* @param damage
|
||||
* @param attackerId id of the permanent or player who make damage (source.getSourceId() in most cases)
|
||||
* @param source can be null for default game actions like combat
|
||||
* @param game
|
||||
* @param preventable
|
||||
* @param combat
|
||||
* @return
|
||||
*/
|
||||
int markDamage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat);
|
||||
int markDamage(int damage, UUID attackerId, Ability source, Game game, boolean preventable, boolean combat);
|
||||
|
||||
void markLifelink(int damage);
|
||||
|
||||
|
|
@ -145,9 +156,15 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
MageObject getBasicMageObject(Game game);
|
||||
|
||||
boolean destroy(UUID sourceId, Game game, boolean noRegen);
|
||||
boolean destroy(Ability source, Game game, boolean noRegen);
|
||||
|
||||
boolean sacrifice(UUID sourceId, Game game);
|
||||
/**
|
||||
*
|
||||
* @param source can be null for state base actions
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
boolean sacrifice(Ability source, Game game);
|
||||
|
||||
boolean regenerate(Ability source, Game game);
|
||||
|
||||
|
|
@ -155,7 +172,7 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
boolean fight(Permanent fightTarget, Ability source, Game game, boolean batchTrigger);
|
||||
|
||||
boolean entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent);
|
||||
boolean entersBattlefield(Ability source, Game game, Zone fromZone, boolean fireEvent);
|
||||
|
||||
String getValue(GameState state);
|
||||
|
||||
|
|
@ -173,7 +190,7 @@ public interface Permanent extends Card, Controllable {
|
|||
|
||||
void resetControl();
|
||||
|
||||
boolean changeControllerId(UUID controllerId, Game game);
|
||||
boolean changeControllerId(UUID controllerId, Game game, Ability source);
|
||||
|
||||
boolean checkControlChanged(Game game);
|
||||
|
||||
|
|
|
|||
|
|
@ -163,8 +163,8 @@ public class PermanentCard extends PermanentImpl {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceUp(Game game, UUID playerId) {
|
||||
if (super.turnFaceUp(game, playerId)) {
|
||||
public boolean turnFaceUp(Ability source, Game game, UUID playerId) {
|
||||
if (super.turnFaceUp(source, game, playerId)) {
|
||||
power.modifyBaseValue(power.getBaseValue());
|
||||
toughness.modifyBaseValue(toughness.getBaseValue());
|
||||
setManifested(false);
|
||||
|
|
|
|||
|
|
@ -500,17 +500,17 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean tap(Game game) {
|
||||
return tap(false, game);
|
||||
public boolean tap(Ability source, Game game) {
|
||||
return tap(false, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tap(boolean forCombat, Game game) {
|
||||
public boolean tap(boolean forCombat, Ability source, Game game) {
|
||||
//20091005 - 701.15a
|
||||
if (!tapped) {
|
||||
if (!replaceEvent(EventType.TAP, game)) {
|
||||
this.tapped = true;
|
||||
game.fireEvent(new GameEvent(EventType.TAPPED, objectId, ownerId, controllerId, 0, forCombat));
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.TAPPED, objectId, source, controllerId, 0, forCombat));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -562,7 +562,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
if (!replaceEvent(EventType.TRANSFORM, game)) {
|
||||
setTransformed(!transformed);
|
||||
game.applyEffects();
|
||||
game.addSimultaneousEvent(GameEvent.getEvent(EventType.TRANSFORMED, getId(), getControllerId()));
|
||||
game.addSimultaneousEvent(GameEvent.getEvent(GameEvent.EventType.TRANSFORMED, getId(), getControllerId()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -701,27 +701,29 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean changeControllerId(UUID controllerId, Game game) {
|
||||
Player newController = game.getPlayer(controllerId);
|
||||
public boolean changeControllerId(UUID newControllerId, Game game, Ability source) {
|
||||
Player newController = game.getPlayer(newControllerId);
|
||||
if (newController == null || !newController.isInGame()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// For each control change compared to last controler send a GAIN_CONTROL replace event to be able to prevent the gain control (e.g. Guardian Beast)
|
||||
if (beforeResetControllerId != controllerId) {
|
||||
GameEvent gainControlEvent = GameEvent.getEvent(GameEvent.EventType.GAIN_CONTROL, this.getId(), null, controllerId);
|
||||
if (beforeResetControllerId != newControllerId) {
|
||||
GameEvent gainControlEvent = GameEvent.getEvent(GameEvent.EventType.GAIN_CONTROL, this.getId(), null, newControllerId);
|
||||
if (game.replaceEvent(gainControlEvent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GameEvent loseControlEvent = GameEvent.getEvent(GameEvent.EventType.LOSE_CONTROL, this.getId(), null, controllerId);
|
||||
|
||||
GameEvent loseControlEvent = GameEvent.getEvent(GameEvent.EventType.LOSE_CONTROL, this.getId(), null, newControllerId);
|
||||
if (game.replaceEvent(loseControlEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newController != null && (!newController.hasLeft() || !newController.hasLost())) {
|
||||
this.controllerId = controllerId;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
// must change abilities controller too
|
||||
this.controllerId = newControllerId;
|
||||
this.getAbilities().setControllerId(newControllerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -733,8 +735,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.getAbilities(game).setControllerId(controllerId);
|
||||
game.getContinuousEffects().setController(objectId, controllerId);
|
||||
// the controller of triggered abilites is always set/checked before the abilities triggers so not needed here
|
||||
game.fireEvent(new GameEvent(EventType.LOST_CONTROL, objectId, objectId, beforeResetControllerId));
|
||||
game.fireEvent(new GameEvent(EventType.GAINED_CONTROL, objectId, objectId, controllerId));
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.LOST_CONTROL, objectId, null, beforeResetControllerId));
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.GAINED_CONTROL, objectId, null, controllerId));
|
||||
|
||||
return true;
|
||||
} else if (isCopy()) {// Because the previous copied abilities can be from another controller - change controller in any case for abilities
|
||||
|
|
@ -784,15 +786,15 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void attachTo(UUID attachToObjectId, Game game) {
|
||||
public void attachTo(UUID attachToObjectId, Ability source, Game game) {
|
||||
if (this.attachedTo != null && !Objects.equals(this.attachedTo, attachToObjectId)) {
|
||||
Permanent attachedToUntilNowObject = game.getPermanent(this.attachedTo);
|
||||
if (attachedToUntilNowObject != null) {
|
||||
attachedToUntilNowObject.removeAttachment(this.objectId, game);
|
||||
attachedToUntilNowObject.removeAttachment(this.objectId, source, game);
|
||||
} else {
|
||||
Card attachedToUntilNowCard = game.getCard(this.attachedTo);
|
||||
if (attachedToUntilNowCard != null) {
|
||||
attachedToUntilNowCard.removeAttachment(this.objectId, game);
|
||||
attachedToUntilNowCard.removeAttachment(this.objectId, source, game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -835,72 +837,73 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int damage(int damage, UUID sourceId, Game game) {
|
||||
return damage(damage, sourceId, game, true, false, false, null);
|
||||
public int damage(int damage, UUID attackerId, Ability source, Game game) {
|
||||
return doDamage(damage, attackerId, source, game, true, false, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable) {
|
||||
return damage(damage, sourceId, game, preventable, combat, false, null);
|
||||
public int damage(int damage, UUID attackerId, Ability source, Game game, boolean combat, boolean preventable) {
|
||||
return doDamage(damage, attackerId, source, game, preventable, combat, false, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, List<UUID> appliedEffects) {
|
||||
return damage(damage, sourceId, game, preventable, combat, false, appliedEffects);
|
||||
public int damage(int damage, UUID attackerId, Ability source, Game game, boolean combat, boolean preventable, List<UUID> appliedEffects) {
|
||||
return doDamage(damage, attackerId, source, game, preventable, combat, false, appliedEffects);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param damageAmount
|
||||
* @param sourceId
|
||||
* @param attackerId id of the permanent or player who make damage (source.getSourceId() in most cases)
|
||||
* @param source
|
||||
* @param game
|
||||
* @param preventable
|
||||
* @param combat
|
||||
* @param markDamage If true, damage will be dealt later in applyDamage
|
||||
* method
|
||||
* method, uses only in inner markDamage.
|
||||
* @return
|
||||
*/
|
||||
private int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
private int doDamage(int damageAmount, UUID attackerId, Ability source, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
int damageDone = 0;
|
||||
if (damageAmount > 0 && canDamage(game.getObject(sourceId), game)) {
|
||||
if (damageAmount > 0 && canDamage(game.getObject(attackerId), game)) {
|
||||
if (this.isPlaneswalker()) {
|
||||
damageDone = damagePlaneswalker(damageAmount, sourceId, game, preventable, combat, markDamage, appliedEffects);
|
||||
damageDone = damagePlaneswalker(damageAmount, attackerId, source, game, preventable, combat, markDamage, appliedEffects);
|
||||
} else {
|
||||
damageDone = damageCreature(damageAmount, sourceId, game, preventable, combat, markDamage, appliedEffects);
|
||||
damageDone = damageCreature(damageAmount, attackerId, source, game, preventable, combat, markDamage, appliedEffects);
|
||||
}
|
||||
if (damageDone > 0) {
|
||||
UUID sourceControllerId = null;
|
||||
Abilities sourceAbilities = null;
|
||||
MageObject source = game.getPermanentOrLKIBattlefield(sourceId);
|
||||
if (source == null) {
|
||||
StackObject stackObject = game.getStack().getStackObject(sourceId);
|
||||
MageObject attacker = game.getPermanentOrLKIBattlefield(attackerId);
|
||||
if (attacker == null) {
|
||||
StackObject stackObject = game.getStack().getStackObject(attackerId);
|
||||
if (stackObject != null) {
|
||||
source = stackObject.getStackAbility().getSourceObject(game);
|
||||
attacker = stackObject.getStackAbility().getSourceObject(game);
|
||||
} else {
|
||||
source = game.getObject(sourceId);
|
||||
attacker = game.getObject(attackerId);
|
||||
}
|
||||
if (source instanceof Spell) {
|
||||
sourceAbilities = ((Spell) source).getAbilities(game);
|
||||
sourceControllerId = ((Spell) source).getControllerId();
|
||||
} else if (source instanceof Card) {
|
||||
sourceAbilities = ((Card) source).getAbilities(game);
|
||||
sourceControllerId = ((Card) source).getOwnerId();
|
||||
} else if (source instanceof CommandObject) {
|
||||
sourceControllerId = ((CommandObject) source).getControllerId();
|
||||
sourceAbilities = source.getAbilities();
|
||||
if (attacker instanceof Spell) {
|
||||
sourceAbilities = ((Spell) attacker).getAbilities(game);
|
||||
sourceControllerId = ((Spell) attacker).getControllerId();
|
||||
} else if (attacker instanceof Card) {
|
||||
sourceAbilities = ((Card) attacker).getAbilities(game);
|
||||
sourceControllerId = ((Card) attacker).getOwnerId();
|
||||
} else if (attacker instanceof CommandObject) {
|
||||
sourceControllerId = ((CommandObject) attacker).getControllerId();
|
||||
sourceAbilities = attacker.getAbilities();
|
||||
} else {
|
||||
source = null;
|
||||
attacker = null;
|
||||
}
|
||||
} else {
|
||||
sourceAbilities = ((Permanent) source).getAbilities(game);
|
||||
sourceControllerId = ((Permanent) source).getControllerId();
|
||||
sourceAbilities = ((Permanent) attacker).getAbilities(game);
|
||||
sourceControllerId = ((Permanent) attacker).getControllerId();
|
||||
}
|
||||
if (source != null && sourceAbilities != null) {
|
||||
if (attacker != null && sourceAbilities != null) {
|
||||
if (sourceAbilities.containsKey(LifelinkAbility.getInstance().getId())) {
|
||||
if (markDamage) {
|
||||
game.getPermanent(sourceId).markLifelink(damageDone);
|
||||
game.getPermanent(attackerId).markLifelink(damageDone);
|
||||
} else {
|
||||
Player player = game.getPlayer(sourceControllerId);
|
||||
player.gainLife(damageDone, game, sourceId);
|
||||
player.gainLife(damageDone, game, source);
|
||||
}
|
||||
}
|
||||
if (sourceAbilities.containsKey(DeathtouchAbility.getInstance().getId())) {
|
||||
|
|
@ -912,14 +915,14 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
// Unstable ability - Earl of Squirrel
|
||||
if (sourceAbilities.containsKey(SquirrellinkAbility.getInstance().getId())) {
|
||||
Player player = game.getPlayer(sourceControllerId);
|
||||
new SquirrelToken().putOntoBattlefield(damageDone, game, sourceId, player.getId());
|
||||
new SquirrelToken().putOntoBattlefield(damageDone, game, source, player.getId());
|
||||
}
|
||||
dealtDamageByThisTurn.add(new MageObjectReference(source, game));
|
||||
dealtDamageByThisTurn.add(new MageObjectReference(attacker, game));
|
||||
}
|
||||
if (source == null) {
|
||||
if (attacker == null) {
|
||||
game.informPlayers(getLogName() + " gets " + damageDone + " damage");
|
||||
} else {
|
||||
game.informPlayers(source.getLogName() + " deals " + damageDone + " damage to " + getLogName());
|
||||
game.informPlayers(attacker.getLogName() + " deals " + damageDone + " damage to " + getLogName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -932,15 +935,15 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int markDamage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat) {
|
||||
return damage(damageAmount, sourceId, game, preventable, combat, true, null);
|
||||
public int markDamage(int damageAmount, UUID attackerId, Ability source, Game game, boolean preventable, boolean combat) {
|
||||
return doDamage(damageAmount, attackerId, source, game, preventable, combat, true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int applyDamage(Game game) {
|
||||
if (markedLifelink > 0) {
|
||||
Player player = game.getPlayer(this.getControllerId());
|
||||
player.gainLife(markedLifelink, game, this.getId());
|
||||
player.gainLife(markedLifelink, game, null);
|
||||
markedLifelink = 0;
|
||||
}
|
||||
if (markedDamage == null) {
|
||||
|
|
@ -969,18 +972,18 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
deathtouched = false;
|
||||
}
|
||||
|
||||
protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
GameEvent event = new DamagePlaneswalkerEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
||||
protected int damagePlaneswalker(int damage, UUID attackerId, Ability source, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
GameEvent event = new DamagePlaneswalkerEvent(objectId, attackerId, controllerId, damage, preventable, combat);
|
||||
event.setAppliedEffects(appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
int actualDamage = checkProtectionAbilities(event, sourceId, game);
|
||||
int actualDamage = checkProtectionAbilities(event, attackerId, source, game);
|
||||
if (actualDamage > 0) {
|
||||
int countersToRemove = actualDamage;
|
||||
if (countersToRemove > getCounters(game).getCount(CounterType.LOYALTY)) {
|
||||
countersToRemove = getCounters(game).getCount(CounterType.LOYALTY);
|
||||
}
|
||||
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, game);
|
||||
DamagedEvent damagedEvent = new DamagedPlaneswalkerEvent(objectId, sourceId, controllerId, actualDamage, combat);
|
||||
removeCounters(CounterType.LOYALTY.getName(), countersToRemove, source, game);
|
||||
DamagedEvent damagedEvent = new DamagedPlaneswalkerEvent(objectId, attackerId, controllerId, actualDamage, combat);
|
||||
game.fireEvent(damagedEvent);
|
||||
game.getState().addSimultaneousDamage(damagedEvent, game);
|
||||
return actualDamage;
|
||||
|
|
@ -989,23 +992,22 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
return 0;
|
||||
}
|
||||
|
||||
protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
GameEvent event = new DamageCreatureEvent(objectId, sourceId, controllerId, damage, preventable, combat);
|
||||
protected int damageCreature(int damage, UUID attackerId, Ability source, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
|
||||
GameEvent event = new DamageCreatureEvent(this.getId(), attackerId, this.getControllerId(), damage, preventable, combat);
|
||||
event.setAppliedEffects(appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
int actualDamage = checkProtectionAbilities(event, sourceId, game);
|
||||
int actualDamage = checkProtectionAbilities(event, attackerId, source, game);
|
||||
if (actualDamage > 0) {
|
||||
//Permanent source = game.getPermanent(sourceId);
|
||||
MageObject source = game.getObject(sourceId);
|
||||
if (source != null && (source.getAbilities().containsKey(InfectAbility.getInstance().getId())
|
||||
|| source.getAbilities().containsKey(WitherAbility.getInstance().getId()))) {
|
||||
MageObject attacker = game.getObject(attackerId);
|
||||
if (attacker != null && (attacker.getAbilities().containsKey(InfectAbility.getInstance().getId())
|
||||
|| attacker.getAbilities().containsKey(WitherAbility.getInstance().getId()))) {
|
||||
if (markDamage) {
|
||||
// mark damage only
|
||||
markDamage(CounterType.M1M1.createInstance(actualDamage), source);
|
||||
markDamage(CounterType.M1M1.createInstance(actualDamage), attacker);
|
||||
} else {
|
||||
Ability damageSourceAbility = null;
|
||||
if (source instanceof Permanent) {
|
||||
damageSourceAbility = ((Permanent) source).getSpellAbility();
|
||||
if (attacker instanceof Permanent) {
|
||||
damageSourceAbility = ((Permanent) attacker).getSpellAbility();
|
||||
}
|
||||
// deal damage immediately
|
||||
addCounters(CounterType.M1M1.createInstance(actualDamage), damageSourceAbility, game);
|
||||
|
|
@ -1013,7 +1015,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
} else {
|
||||
this.damage = CardUtil.addWithOverflowCheck(this.damage, actualDamage);
|
||||
}
|
||||
DamagedEvent damagedEvent = new DamagedCreatureEvent(objectId, sourceId, controllerId, actualDamage, combat);
|
||||
DamagedEvent damagedEvent = new DamagedCreatureEvent(this.getId(), attackerId, this.getControllerId(), actualDamage, combat);
|
||||
game.fireEvent(damagedEvent);
|
||||
game.getState().addSimultaneousDamage(damagedEvent, game);
|
||||
return actualDamage;
|
||||
|
|
@ -1022,14 +1024,14 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
return 0;
|
||||
}
|
||||
|
||||
private int checkProtectionAbilities(GameEvent event, UUID sourceId, Game game) {
|
||||
MageObject source = game.getObject(sourceId);
|
||||
if (source != null && hasProtectionFrom(source, game)) {
|
||||
GameEvent preventEvent = new PreventDamageEvent(this.objectId, sourceId, this.controllerId, event.getAmount(), ((DamageEvent) event).isCombatDamage());
|
||||
private int checkProtectionAbilities(GameEvent event, UUID attackerId, Ability source, Game game) {
|
||||
MageObject attacker = game.getObject(attackerId);
|
||||
if (attacker != null && hasProtectionFrom(attacker, game)) {
|
||||
GameEvent preventEvent = new PreventDamageEvent(this.getId(), attackerId, source, this.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage());
|
||||
if (!game.replaceEvent(preventEvent)) {
|
||||
int preventedDamage = event.getAmount();
|
||||
event.setAmount(0);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, this.objectId, sourceId, this.controllerId, preventedDamage));
|
||||
game.fireEvent(new PreventedDamageEvent(this.getId(), attackerId, source, this.getControllerId(), preventedDamage));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1044,18 +1046,18 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent) {
|
||||
public boolean entersBattlefield(Ability source, Game game, Zone fromZone, boolean fireEvent) {
|
||||
controlledFromStartOfControllerTurn = false;
|
||||
if (this.isFaceDown(game)) {
|
||||
// remove some attributes here, because first apply effects comes later otherwise abilities (e.g. color related) will unintended trigger
|
||||
MorphAbility.setPermanentToFaceDownCreature(this);
|
||||
}
|
||||
|
||||
EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone, EnterEventType.SELF);
|
||||
EntersTheBattlefieldEvent event = new EntersTheBattlefieldEvent(this, source, getControllerId(), fromZone, EnterEventType.SELF);
|
||||
if (game.replaceEvent(event)) {
|
||||
return false;
|
||||
}
|
||||
event = new EntersTheBattlefieldEvent(this, sourceId, getControllerId(), fromZone);
|
||||
event = new EntersTheBattlefieldEvent(this, source, getControllerId(), fromZone);
|
||||
if (!game.replaceEvent(event)) {
|
||||
if (fireEvent) {
|
||||
game.addSimultaneousEvent(event);
|
||||
|
|
@ -1088,7 +1090,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
// needed to get the correct possible targets if target rule modification effects are active
|
||||
// e.g. Fiendslayer Paladin tried to target with Ultimate Price
|
||||
return !game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(EventType.TARGET, this.getId(), source.getId(), sourceControllerId), null, game, true);
|
||||
return !game.getContinuousEffects().preventedByRuleModification(new TargetEvent(this, source.getId(), sourceControllerId), null, game, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1105,19 +1107,19 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean cantBeAttachedBy(MageObject source, Game game, boolean silentMode) {
|
||||
public boolean cantBeAttachedBy(MageObject attachment, Ability source, Game game, boolean silentMode) {
|
||||
for (ProtectionAbility ability : this.getAbilities(game).getProtectionAbilities()) {
|
||||
if (!(source.hasSubtype(SubType.AURA, game)
|
||||
if (!(attachment.hasSubtype(SubType.AURA, game)
|
||||
&& !ability.removesAuras())
|
||||
&& !(source.hasSubtype(SubType.EQUIPMENT, game)
|
||||
&& !(attachment.hasSubtype(SubType.EQUIPMENT, game)
|
||||
&& !ability.removesEquipment())) {
|
||||
if (!source.getId().equals(ability.getAuraIdNotToBeRemoved())
|
||||
&& !ability.canTarget(source, game)) {
|
||||
return !ability.getDoesntRemoveControlled() || isControlledBy(game.getControllerId(source.getId()));
|
||||
if (!attachment.getId().equals(ability.getAuraIdNotToBeRemoved())
|
||||
&& !ability.canTarget(attachment, game)) {
|
||||
return !ability.getDoesntRemoveControlled() || isControlledBy(game.getControllerId(attachment.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return game.getContinuousEffects().preventedByRuleModification(GameEvent.getEvent(EventType.STAY_ATTACHED, objectId, source.getId(), null), null, game, silentMode);
|
||||
return game.getContinuousEffects().preventedByRuleModification(new StayAttachedEvent(this.getId(), attachment.getId(), source), null, game, silentMode);
|
||||
}
|
||||
|
||||
protected boolean canDamage(MageObject source, Game game) {
|
||||
|
|
@ -1128,7 +1130,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean destroy(UUID sourceId, Game game, boolean noRegen) {
|
||||
public boolean destroy(Ability source, Game game, boolean noRegen) {
|
||||
// Only permanets on the battlefield can be destroyed
|
||||
if (!game.getState().getZone(getId()).equals(Zone.BATTLEFIELD)) {
|
||||
return false;
|
||||
|
|
@ -1138,10 +1140,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!game.replaceEvent(GameEvent.getEvent(EventType.DESTROY_PERMANENT, objectId, sourceId, controllerId, noRegen ? 1 : 0))) {
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DESTROY_PERMANENT, objectId, source, controllerId, noRegen ? 1 : 0))) {
|
||||
// this means destroy was successful, if object movement to graveyard will be replaced (e.g. commander to command zone) it's still
|
||||
// handled as successful destroying (but not as sucessful "dies this way" for destroying).
|
||||
if (moveToZone(Zone.GRAVEYARD, sourceId, game, false)) {
|
||||
if (moveToZone(Zone.GRAVEYARD, source, game, false)) {
|
||||
if (!game.isSimulation()) {
|
||||
String logName;
|
||||
Card card = game.getCard(this.getId());
|
||||
|
|
@ -1156,7 +1158,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
game.informPlayers(logName + " was destroyed");
|
||||
}
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(EventType.DESTROYED_PERMANENT, objectId, sourceId, controllerId));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DESTROYED_PERMANENT, objectId, source, controllerId));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1164,17 +1166,17 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean sacrifice(UUID sourceId, Game game) {
|
||||
public boolean sacrifice(Ability source, Game game) {
|
||||
//20091005 - 701.13
|
||||
if (isPhasedIn() && !game.replaceEvent(GameEvent.getEvent(EventType.SACRIFICE_PERMANENT, objectId, sourceId, controllerId))) {
|
||||
if (isPhasedIn() && !game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.SACRIFICE_PERMANENT, objectId, source, controllerId))) {
|
||||
// Commander replacement effect or Rest in Peace (exile instead of graveyard) in play does not prevent successful sacrifice
|
||||
// so the return value of the moveToZone is not taken into account here
|
||||
moveToZone(Zone.GRAVEYARD, sourceId, game, false);
|
||||
moveToZone(Zone.GRAVEYARD, source, game, false);
|
||||
Player player = game.getPlayer(getControllerId());
|
||||
if (player != null && !game.isSimulation()) {
|
||||
game.informPlayers(player.getLogName() + " sacrificed " + this.getLogName());
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(EventType.SACRIFICED_PERMANENT, objectId, sourceId, controllerId));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.SACRIFICED_PERMANENT, objectId, source, controllerId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1183,15 +1185,15 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
@Override
|
||||
public boolean regenerate(Ability source, Game game) {
|
||||
//20110930 - 701.12
|
||||
if (!game.replaceEvent(GameEvent.getEvent(EventType.REGENERATE, objectId, source.getSourceId(), controllerId))) {
|
||||
this.tap(game);
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.REGENERATE, objectId, source, controllerId))) {
|
||||
this.tap(source, game);
|
||||
this.removeFromCombat(game);
|
||||
this.removeAllDamage(game);
|
||||
|
||||
// remove one regen shield
|
||||
RegenerateSourceEffect.decRegenerationShieldsAmount(game, this.getId());
|
||||
|
||||
game.fireEvent(GameEvent.getEvent(EventType.REGENERATED, objectId, source.getSourceId(), controllerId));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.REGENERATED, objectId, source, controllerId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1207,12 +1209,23 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.toughness.boostValue(toughness);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple event without source
|
||||
* @param eventType
|
||||
* @param game
|
||||
*/
|
||||
protected void fireEvent(EventType eventType, Game game) {
|
||||
game.fireEvent(GameEvent.getEvent(eventType, this.objectId, ownerId)); // controllerId seems to me more logical (LevelX2)
|
||||
game.fireEvent(GameEvent.getEvent(eventType, this.objectId, null, this.controllerId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple event without source
|
||||
* @param eventType
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
protected boolean replaceEvent(EventType eventType, Game game) {
|
||||
return game.replaceEvent(GameEvent.getEvent(eventType, this.objectId, ownerId));// controllerId seems to me more logical (LevelX2)
|
||||
return game.replaceEvent(GameEvent.getEvent(eventType, this.objectId, null, this.controllerId));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1580,19 +1593,21 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
|
||||
@Override
|
||||
public boolean fight(Permanent fightTarget, Ability source, Game game, boolean batchTrigger) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, fightTarget.getId(), getId(), source.getControllerId()));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, getId(), fightTarget.getId(), source.getControllerId()));
|
||||
damage(fightTarget.getPower().getValue(), fightTarget.getId(), game);
|
||||
fightTarget.damage(getPower().getValue(), getId(), game);
|
||||
if (!batchTrigger) {
|
||||
return true;
|
||||
// double fight events for each creature
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, fightTarget.getId(), source, source.getControllerId()));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, getId(), source, source.getControllerId()));
|
||||
damage(fightTarget.getPower().getValue(), fightTarget.getId(), source, game);
|
||||
fightTarget.damage(getPower().getValue(), getId(), source, game);
|
||||
|
||||
if (batchTrigger) {
|
||||
Set<MageObjectReference> morSet = new HashSet<>();
|
||||
morSet.add(new MageObjectReference(this, game));
|
||||
morSet.add(new MageObjectReference(fightTarget, game));
|
||||
String data = UUID.randomUUID().toString();
|
||||
game.getState().setValue("batchFight_" + data, morSet);
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BATCH_FIGHT, getId(), source, source.getControllerId(), data, 0));
|
||||
}
|
||||
Set<MageObjectReference> morSet = new HashSet<>();
|
||||
morSet.add(new MageObjectReference(this, game));
|
||||
morSet.add(new MageObjectReference(fightTarget, game));
|
||||
String data = UUID.randomUUID().toString();
|
||||
game.getState().setValue("batchFight_" + data, morSet);
|
||||
game.fireEvent(GameEvent.getEvent(EventType.BATCH_FIGHT, getId(), getId(), source.getControllerId(), data, 0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1630,18 +1645,18 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
public boolean moveToZone(Zone toZone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null) {
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone, appliedEffects);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, source, controllerId, fromZone, toZone, appliedEffects);
|
||||
ZoneChangeInfo zoneChangeInfo;
|
||||
if (toZone == Zone.LIBRARY) {
|
||||
zoneChangeInfo = new ZoneChangeInfo.Library(event, flag /* put on top */);
|
||||
} else {
|
||||
zoneChangeInfo = new ZoneChangeInfo(event);
|
||||
}
|
||||
boolean successfullyMoved = ZonesHandler.moveCard(zoneChangeInfo, game);
|
||||
boolean successfullyMoved = ZonesHandler.moveCard(zoneChangeInfo, game, source);
|
||||
//20180810 - 701.3d
|
||||
detachAllAttachments(game);
|
||||
return successfullyMoved;
|
||||
|
|
@ -1650,12 +1665,12 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
Zone fromZone = game.getState().getZone(objectId);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, source, ownerId, fromZone, Zone.EXILED, appliedEffects);
|
||||
ZoneChangeInfo.Exile zcInfo = new ZoneChangeInfo.Exile(event, exileId, name);
|
||||
|
||||
boolean successfullyMoved = ZonesHandler.moveCard(zcInfo, game);
|
||||
boolean successfullyMoved = ZonesHandler.moveCard(zcInfo, game, source);
|
||||
//20180810 - 701.3d
|
||||
detachAllAttachments(game);
|
||||
return successfullyMoved;
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class BelzenlokDemonTokenEffect extends OneShotEffect {
|
|||
} else {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
controller.damage(6, source.getSourceId(), game);
|
||||
controller.damage(6, source.getSourceId(), source, game);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class ReturnSengirNosferatuEffect extends OneShotEffect {
|
|||
player.chooseTarget(Outcome.PutCreatureInPlay, target, source, game);
|
||||
Card card = game.getCard(target.getTargets().get(0));
|
||||
if (card != null) {
|
||||
return card.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false);
|
||||
return card.moveToZone(Zone.BATTLEFIELD, source, game, false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -27,13 +27,13 @@ public interface Token extends MageObject {
|
|||
|
||||
void addAbility(Ability ability);
|
||||
|
||||
boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId);
|
||||
boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId);
|
||||
|
||||
boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId, boolean tapped, boolean attacking);
|
||||
boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId, boolean tapped, boolean attacking);
|
||||
|
||||
boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer);
|
||||
boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer);
|
||||
|
||||
boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer, boolean created);
|
||||
boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer, boolean created);
|
||||
|
||||
void setPower(int power);
|
||||
|
||||
|
|
|
|||
|
|
@ -123,13 +123,13 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId) {
|
||||
return this.putOntoBattlefield(amount, game, sourceId, controllerId, false, false);
|
||||
public boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId) {
|
||||
return this.putOntoBattlefield(amount, game, source, controllerId, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId, boolean tapped, boolean attacking) {
|
||||
return putOntoBattlefield(amount, game, sourceId, controllerId, tapped, attacking, null);
|
||||
public boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId, boolean tapped, boolean attacking) {
|
||||
return putOntoBattlefield(amount, game, source, controllerId, tapped, attacking, null);
|
||||
}
|
||||
|
||||
private String getSetCode(Game game, UUID sourceId) {
|
||||
|
|
@ -158,12 +158,12 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer) {
|
||||
return putOntoBattlefield(amount, game, sourceId, controllerId, tapped, attacking, attackedPlayer, true);
|
||||
public boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer) {
|
||||
return putOntoBattlefield(amount, game, source, controllerId, tapped, attacking, attackedPlayer, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(int amount, Game game, UUID sourceId, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer, boolean created) {
|
||||
public boolean putOntoBattlefield(int amount, Game game, Ability source, UUID controllerId, boolean tapped, boolean attacking, UUID attackedPlayer, boolean created) {
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller == null) {
|
||||
return false;
|
||||
|
|
@ -173,16 +173,20 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
|||
}
|
||||
lastAddedTokenIds.clear();
|
||||
|
||||
CreateTokenEvent event = new CreateTokenEvent(sourceId, controllerId, amount, this);
|
||||
CreateTokenEvent event = new CreateTokenEvent(source, controllerId, amount, this);
|
||||
if (!created || !game.replaceEvent(event)) {
|
||||
putOntoBattlefieldHelper(event, game, tapped, attacking, attackedPlayer, created);
|
||||
putOntoBattlefieldHelper(event, game, source, tapped, attacking, attackedPlayer, created);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void putOntoBattlefieldHelper(CreateTokenEvent event, Game game, boolean tapped, boolean attacking, UUID attackedPlayer, boolean created) {
|
||||
private static void putOntoBattlefieldHelper(CreateTokenEvent event, Game game, Ability source, boolean tapped, boolean attacking, UUID attackedPlayer, boolean created) {
|
||||
Player controller = game.getPlayer(event.getPlayerId());
|
||||
if (controller == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Token token = event.getToken();
|
||||
int amount = event.getAmount();
|
||||
|
||||
|
|
@ -200,7 +204,7 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
|||
}
|
||||
game.setScopeRelevant(true);
|
||||
for (Permanent permanent : permanents) {
|
||||
if (permanent.entersBattlefield(event.getSourceId(), game, Zone.OUTSIDE, true)) {
|
||||
if (permanent.entersBattlefield(source, game, Zone.OUTSIDE, true)) {
|
||||
permanentsEntered.add(permanent);
|
||||
} else {
|
||||
game.getPermanentsEntering().remove(permanent.getId());
|
||||
|
|
@ -219,7 +223,7 @@ public abstract class TokenImpl extends MageObjectImpl implements Token {
|
|||
}
|
||||
game.addSimultaneousEvent(new ZoneChangeEvent(permanent, permanent.getControllerId(), Zone.OUTSIDE, Zone.BATTLEFIELD));
|
||||
if (permanent instanceof PermanentToken && created) {
|
||||
game.addSimultaneousEvent(new CreatedTokenEvent(event.getSourceId(), (PermanentToken) permanent));
|
||||
game.addSimultaneousEvent(new CreatedTokenEvent(source, (PermanentToken) permanent));
|
||||
}
|
||||
if (attacking && game.getCombat() != null && game.getActivePlayerId().equals(permanent.getControllerId())) {
|
||||
game.getCombat().addAttackingCreature(permanent.getId(), game, attackedPlayer);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import mage.counters.Counters;
|
|||
import mage.filter.FilterMana;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameState;
|
||||
import mage.game.events.CopiedStackObjectEvent;
|
||||
import mage.game.events.CopyStackObjectEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
|
|
@ -243,7 +245,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
if (!game.isSimulation()) {
|
||||
game.informPlayers(getName() + " has been fizzled.");
|
||||
}
|
||||
counter(null, game);
|
||||
counter(null, /*this.getSpellAbility()*/ game);
|
||||
return false;
|
||||
} else if (this.isEnchantment() && this.hasSubtype(SubType.AURA, game)) {
|
||||
if (ability.getTargets().stillLegal(ability, game)) {
|
||||
|
|
@ -265,7 +267,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
EmptyToken token = new EmptyToken();
|
||||
CardUtil.copyTo(token).from(card);
|
||||
// The token that a resolving copy of a spell becomes isn’t said to have been “created.” (2020-09-25)
|
||||
if (token.putOntoBattlefield(1, game, ability.getSourceId(), getControllerId(), false, false, null, false)) {
|
||||
if (token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false)) {
|
||||
permId = token.getLastAddedToken();
|
||||
flag = true;
|
||||
}
|
||||
|
|
@ -318,14 +320,14 @@ public class Spell extends StackObjImpl implements Card {
|
|||
if (!game.isSimulation()) {
|
||||
game.informPlayers(getName() + " has been fizzled.");
|
||||
}
|
||||
counter(null, game);
|
||||
counter(null, /*this.getSpellAbility()*/ game);
|
||||
return false;
|
||||
}
|
||||
} else if (isCopy()) {
|
||||
EmptyToken token = new EmptyToken();
|
||||
CardUtil.copyTo(token).from(card);
|
||||
// The token that a resolving copy of a spell becomes isn’t said to have been “created.” (2020-09-25)
|
||||
token.putOntoBattlefield(1, game, ability.getSourceId(), getControllerId(), false, false, null, false);
|
||||
token.putOntoBattlefield(1, game, ability, getControllerId(), false, false, null, false);
|
||||
return true;
|
||||
} else {
|
||||
return controller.moveCards(card, Zone.BATTLEFIELD, ability, game, false, faceDown, false, null);
|
||||
|
|
@ -394,21 +396,25 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void counter(UUID sourceId, Game game) {
|
||||
this.counter(sourceId, game, Zone.GRAVEYARD, false, ZoneDetail.NONE);
|
||||
public void counter(Ability source, Game game) {
|
||||
this.counter(source, game, Zone.GRAVEYARD, false, ZoneDetail.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void counter(UUID sourceId, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
||||
public void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
||||
// source can be null for fizzled spells, found only one place with that usage -- Rebound Ability:
|
||||
// event.getSourceId().equals(source.getSourceId())
|
||||
// TODO: so later it must be replaced to another technics with non null source
|
||||
UUID counteringSourceId = (source == null ? null : source.getSourceId());
|
||||
this.countered = true;
|
||||
if (!isCopy()) {
|
||||
Player player = game.getPlayer(game.getControllerId(sourceId));
|
||||
Player player = game.getPlayer(game.getControllerId(counteringSourceId));
|
||||
if (player == null) {
|
||||
player = game.getPlayer(getControllerId());
|
||||
}
|
||||
if (player != null) {
|
||||
Ability counteringAbility = null;
|
||||
MageObject counteringObject = game.getObject(sourceId);
|
||||
MageObject counteringObject = game.getObject(counteringSourceId);
|
||||
if (counteringObject instanceof StackObject) {
|
||||
counteringAbility = ((StackObject) counteringObject).getStackAbility();
|
||||
}
|
||||
|
|
@ -692,13 +698,13 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceUp(Game game, UUID playerId) {
|
||||
public boolean turnFaceUp(Ability source, Game game, UUID playerId) {
|
||||
setFaceDown(false, game);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceDown(Game game, UUID playerId) {
|
||||
public boolean turnFaceDown(Ability source, Game game, UUID playerId) {
|
||||
setFaceDown(true, game);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -770,57 +776,57 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromZone(Game game, Zone fromZone, UUID sourceId) {
|
||||
return card.removeFromZone(game, fromZone, sourceId);
|
||||
public boolean removeFromZone(Game game, Zone fromZone, Ability source) {
|
||||
return card.removeFromZone(game, fromZone, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag) {
|
||||
return moveToZone(zone, sourceId, game, flag, null);
|
||||
public boolean moveToZone(Zone zone, Ability source, Game game, boolean flag) {
|
||||
return moveToZone(zone, source, game, flag, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
public boolean moveToZone(Zone zone, Ability source, Game game, boolean flag, List<UUID> appliedEffects) {
|
||||
// 706.10a If a copy of a spell is in a zone other than the stack, it ceases to exist.
|
||||
// If a copy of a card is in any zone other than the stack or the battlefield, it ceases to exist.
|
||||
// These are state-based actions. See rule 704.
|
||||
if (this.isCopy() && zone != Zone.STACK) {
|
||||
return true;
|
||||
}
|
||||
return card.moveToZone(zone, sourceId, game, flag, appliedEffects);
|
||||
return card.moveToZone(zone, source, game, flag, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) {
|
||||
return moveToExile(exileId, name, sourceId, game, null);
|
||||
public boolean moveToExile(UUID exileId, String name, Ability source, Game game) {
|
||||
return moveToExile(exileId, name, source, game, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
|
||||
public boolean moveToExile(UUID exileId, String name, Ability source, Game game, List<UUID> appliedEffects) {
|
||||
if (this.isCopy()) {
|
||||
game.getStack().remove(this, game);
|
||||
return true;
|
||||
}
|
||||
return this.card.moveToExile(exileId, name, sourceId, game, appliedEffects);
|
||||
return this.card.moveToExile(exileId, name, source, game, appliedEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId) {
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped) {
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId, boolean tapped) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown) {
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId, boolean tapped, boolean facedown) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, List<UUID> appliedEffects) {
|
||||
public boolean putOntoBattlefield(Game game, Zone fromZone, Ability source, UUID controllerId, boolean tapped, boolean facedown, List<UUID> appliedEffects) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
|
|
@ -930,13 +936,13 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeCounters(String name, int amount, Game game) {
|
||||
card.removeCounters(name, amount, game);
|
||||
public void removeCounters(String name, int amount, Ability source, Game game) {
|
||||
card.removeCounters(name, amount, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCounters(Counter counter, Game game) {
|
||||
card.removeCounters(counter, game);
|
||||
public void removeCounters(Counter counter, Ability source, Game game) {
|
||||
card.removeCounters(counter, source, game);
|
||||
}
|
||||
|
||||
public Card getCard() {
|
||||
|
|
@ -1025,8 +1031,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void checkForCountersToAdd(Permanent permanent, Game game) {
|
||||
card.checkForCountersToAdd(permanent, game);
|
||||
public void checkForCountersToAdd(Permanent permanent, Ability source, Game game) {
|
||||
card.checkForCountersToAdd(permanent, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1037,7 +1043,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
@Override
|
||||
public StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets, int amount) {
|
||||
Spell spellCopy = null;
|
||||
GameEvent gameEvent = GameEvent.getEvent(EventType.COPY_STACKOBJECT, this.getId(), source.getSourceId(), newControllerId, amount);
|
||||
GameEvent gameEvent = new CopyStackObjectEvent(source, this, newControllerId, amount);
|
||||
if (game.replaceEvent(gameEvent)) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1048,7 +1054,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
if (chooseNewTargets) {
|
||||
spellCopy.chooseNewTargets(game, newControllerId);
|
||||
}
|
||||
game.fireEvent(new GameEvent(EventType.COPIED_STACKOBJECT, spellCopy.getId(), this.getId(), newControllerId));
|
||||
game.fireEvent(new CopiedStackObjectEvent(this, spellCopy, newControllerId));
|
||||
}
|
||||
return spellCopy;
|
||||
}
|
||||
|
|
@ -1078,12 +1084,12 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean addAttachment(UUID permanentId, Game game) {
|
||||
public boolean addAttachment(UUID permanentId, Ability source, Game game) {
|
||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAttachment(UUID permanentId, Game game) {
|
||||
public boolean removeAttachment(UUID permanentId, Ability source, Game game) {
|
||||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import java.util.ArrayDeque;
|
|||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.constants.Zone;
|
||||
import mage.constants.ZoneDetail;
|
||||
import mage.game.Game;
|
||||
|
|
@ -58,16 +59,16 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean counter(UUID objectId, UUID sourceId, Game game) {
|
||||
return counter(objectId, sourceId, game, Zone.GRAVEYARD, false, ZoneDetail.TOP);
|
||||
public boolean counter(UUID objectId, Ability source, Game game) {
|
||||
return counter(objectId, source, game, Zone.GRAVEYARD, false, ZoneDetail.TOP);
|
||||
}
|
||||
|
||||
public boolean counter(UUID objectId, UUID sourceId, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
||||
public boolean counter(UUID objectId, Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
||||
// the counter logic is copied by some spells to handle replacement effects of the countered spell
|
||||
// so if logic is changed here check those spells for needed changes too
|
||||
// Concerned cards to check: Hinder, Spell Crumple
|
||||
StackObject stackObject = getStackObject(objectId);
|
||||
MageObject sourceObject = game.getObject(sourceId);
|
||||
MageObject sourceObject = game.getObject(source.getSourceId());
|
||||
if (stackObject != null && sourceObject != null) {
|
||||
MageObject targetSourceObject = game.getObject(stackObject.getSourceId());
|
||||
String counteredObjectName, targetSourceName;
|
||||
|
|
@ -81,15 +82,15 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
} else {
|
||||
counteredObjectName = "Ability (" + stackObject.getStackAbility().getRule(targetSourceName) + ") of " + targetSourceName;
|
||||
}
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, sourceId, stackObject.getControllerId()))) {
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, source, stackObject.getControllerId()))) {
|
||||
if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement
|
||||
this.remove(stackObject, game);
|
||||
}
|
||||
stackObject.counter(sourceId, game, zone, owner, zoneDetail);
|
||||
stackObject.counter(source, game, zone, owner, zoneDetail);
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(counteredObjectName + " is countered by " + sourceObject.getLogName());
|
||||
}
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, sourceId, stackObject.getControllerId()));
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTERED, objectId, source, stackObject.getControllerId()));
|
||||
return true;
|
||||
} else if (!game.isSimulation()) {
|
||||
game.informPlayers(counteredObjectName + " could not be countered by " + sourceObject.getLogName());
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import mage.cards.Card;
|
|||
import mage.cards.FrameStyle;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.CopiedStackObjectEvent;
|
||||
import mage.game.events.CopyStackObjectEvent;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
|
@ -90,7 +92,7 @@ public class StackAbility extends StackObjImpl implements Ability {
|
|||
if (!game.isSimulation()) {
|
||||
game.informPlayers("Ability has been fizzled: " + getRule());
|
||||
}
|
||||
counter(null, game);
|
||||
counter(null, /*this*/ game);
|
||||
game.getStack().remove(this, game);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -100,13 +102,13 @@ public class StackAbility extends StackObjImpl implements Ability {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void counter(UUID sourceId, Game game) {
|
||||
public void counter(Ability source, Game game) {
|
||||
// zone, owner, top ignored
|
||||
this.counter(sourceId, game, Zone.GRAVEYARD, true, ZoneDetail.TOP);
|
||||
this.counter(source, game, Zone.GRAVEYARD, true, ZoneDetail.TOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void counter(UUID sourceId, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
||||
public void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
|
||||
//20100716 - 603.8
|
||||
if (ability instanceof StateTriggeredAbility) {
|
||||
((StateTriggeredAbility) ability).counter(game);
|
||||
|
|
@ -579,7 +581,7 @@ public class StackAbility extends StackObjImpl implements Ability {
|
|||
|
||||
public StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets, int amount) {
|
||||
StackAbility newStackAbility = null;
|
||||
GameEvent gameEvent = GameEvent.getEvent(GameEvent.EventType.COPY_STACKOBJECT, this.getId(), source.getSourceId(), newControllerId, amount);
|
||||
GameEvent gameEvent = new CopyStackObjectEvent(source, this, newControllerId, amount);
|
||||
if (game.replaceEvent(gameEvent)) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -596,7 +598,7 @@ public class StackAbility extends StackObjImpl implements Ability {
|
|||
newAbility.getTargets().chooseTargets(outcome, newControllerId, newAbility, false, game, false);
|
||||
}
|
||||
}
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.COPIED_STACKOBJECT, newStackAbility.getId(), this.getId(), newControllerId));
|
||||
game.fireEvent(new CopiedStackObjectEvent(this, newStackAbility, newControllerId));
|
||||
}
|
||||
return newStackAbility;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,13 +16,17 @@ public interface StackObject extends MageObject, Controllable {
|
|||
|
||||
UUID getSourceId();
|
||||
|
||||
void counter(UUID sourceId, Game game);
|
||||
/**
|
||||
*
|
||||
* @param source null for fizzled events (sourceId will be null)
|
||||
* @param game
|
||||
*/
|
||||
void counter(Ability source, Game game);
|
||||
|
||||
void counter(UUID sourceId, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail);
|
||||
void counter(Ability source, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail);
|
||||
|
||||
Ability getStackAbility();
|
||||
|
||||
// int getConvertedManaCost();
|
||||
boolean chooseNewTargets(Game game, UUID playerId, boolean forceChange, boolean onlyOneTarget, FilterPermanent filterNewTarget);
|
||||
|
||||
StackObject createCopyOnStack(Game game, Ability source, UUID newControllerId, boolean chooseNewTargets);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public class CombatDamageStep extends Step {
|
|||
|
||||
@Override
|
||||
public void priority(Game game, UUID activePlayerId, boolean resuming) {
|
||||
game.fireEvent(new GameEvent(EventType.COMBAT_DAMAGE_STEP_PRIORITY, null, null, activePlayerId));
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.COMBAT_DAMAGE_STEP_PRIORITY, null, null, activePlayerId));
|
||||
super.priority(game, activePlayerId, resuming);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ public class DrawStep extends Step {
|
|||
Player activePlayer = game.getPlayer(activePlayerId);
|
||||
//20091005 - 504.1/703.4c
|
||||
activePlayer.drawCards(1, null, game);
|
||||
// game.saveState();
|
||||
game.applyEffects();
|
||||
super.beginStep(game, activePlayerId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public class FirstCombatDamageStep extends Step {
|
|||
|
||||
@Override
|
||||
public void priority(Game game, UUID activePlayerId, boolean resuming) {
|
||||
game.fireEvent(new GameEvent(EventType.COMBAT_DAMAGE_STEP_PRIORITY, null, null, activePlayerId));
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.COMBAT_DAMAGE_STEP_PRIORITY, null, null, activePlayerId));
|
||||
super.priority(game, activePlayerId, resuming);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ public abstract class Phase implements Serializable {
|
|||
public void postPriority(Game game, UUID activePlayerId) {
|
||||
currentStep.endStep(game, activePlayerId);
|
||||
//20091005 - 500.4/703.4n
|
||||
game.emptyManaPools();
|
||||
game.emptyManaPools(null);
|
||||
//20091005 - 500.9
|
||||
playExtraSteps(game, currentStep.getType());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import mage.constants.TurnPhase;
|
|||
import mage.counters.CounterType;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.PhaseChangedEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
|
|
@ -121,14 +122,14 @@ public class Turn implements Serializable {
|
|||
}
|
||||
if (!isEndTurnRequested() || phase.getType() == TurnPhase.END) {
|
||||
currentPhase = phase;
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.PHASE_CHANGED, activePlayer.getId(), null, activePlayer.getId()));
|
||||
game.fireEvent(new PhaseChangedEvent(activePlayer.getId(), null));
|
||||
if (!game.getState().getTurnMods().skipPhase(activePlayer.getId(), currentPhase.getType())) {
|
||||
if (phase.play(game, activePlayer.getId())) {
|
||||
if (game.executingRollback()) {
|
||||
return false;
|
||||
}
|
||||
//20091005 - 500.4/703.4n
|
||||
game.emptyManaPools();
|
||||
game.emptyManaPools(null);
|
||||
game.saveState(false);
|
||||
|
||||
//20091005 - 500.8
|
||||
|
|
@ -155,7 +156,7 @@ public class Turn implements Serializable {
|
|||
} while (phase.type != phaseType);
|
||||
if (phase.resumePlay(game, stepType, wasPaused)) {
|
||||
//20091005 - 500.4/703.4n
|
||||
game.emptyManaPools();
|
||||
game.emptyManaPools(null);
|
||||
//game.saveState();
|
||||
//20091005 - 500.8
|
||||
playExtraPhases(game, phase.getType());
|
||||
|
|
@ -169,14 +170,14 @@ public class Turn implements Serializable {
|
|||
if (!game.getState().getTurnMods().skipPhase(activePlayerId, currentPhase.getType())) {
|
||||
if (phase.play(game, activePlayerId)) {
|
||||
//20091005 - 500.4/703.4n
|
||||
game.emptyManaPools();
|
||||
game.emptyManaPools(null);
|
||||
//game.saveState();
|
||||
//20091005 - 500.8
|
||||
playExtraPhases(game, phase.getType());
|
||||
}
|
||||
}
|
||||
if (!currentPhase.equals(phase)) { // phase was changed from the card
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.PHASE_CHANGED, activePlayerId, null, activePlayerId));
|
||||
game.fireEvent(new PhaseChangedEvent(activePlayerId, null));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -223,7 +224,7 @@ public class Turn implements Serializable {
|
|||
phase = new EndPhase();
|
||||
}
|
||||
currentPhase = phase;
|
||||
game.fireEvent(new GameEvent(GameEvent.EventType.PHASE_CHANGED, activePlayerId, extraPhaseTurnMod.getId(), activePlayerId));
|
||||
game.fireEvent(new PhaseChangedEvent(activePlayerId, extraPhaseTurnMod));
|
||||
Player activePlayer = game.getPlayer(activePlayerId);
|
||||
if (activePlayer != null && !game.isSimulation()) {
|
||||
game.informPlayers(activePlayer.getLogName() + " starts an additional " + phase.getType().toString() + " phase");
|
||||
|
|
@ -256,7 +257,7 @@ public class Turn implements Serializable {
|
|||
while (!game.hasEnded() && !game.getStack().isEmpty()) {
|
||||
StackObject stackObject = game.getStack().peekFirst();
|
||||
if (stackObject instanceof Spell) {
|
||||
((Spell) stackObject).moveToExile(null, "", source.getSourceId(), game);
|
||||
((Spell) stackObject).moveToExile(null, "", source, game);
|
||||
} else {
|
||||
game.getStack().remove(stackObject, game); // stack ability
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue