forked from External/mage
move zoneChangeCounter to GameState - Card is now immutable
This commit is contained in:
parent
45aa5f675c
commit
6405c8d2f0
101 changed files with 899 additions and 257 deletions
|
|
@ -108,7 +108,7 @@ class DayEffect extends ContinuousEffectImpl {
|
|||
if (this.affectedObjectsSet) {
|
||||
List<Permanent> creatures = game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getFirstTarget(), game);
|
||||
for (Permanent creature : creatures) {
|
||||
affectedObjectList.add(new MageObjectReference(creature));
|
||||
affectedObjectList.add(new MageObjectReference(creature, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ class AggravateRequirementEffect extends RequirementEffect {
|
|||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId());
|
||||
if (watcher != null) {
|
||||
return watcher.wasDamaged(permanent);
|
||||
return watcher.wasDamaged(permanent, game);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ class SecondSpellPredicate implements Predicate<Spell> {
|
|||
public boolean apply(Spell input, Game game) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
|
||||
if (watcher.getSpellOrder(input) == 2) {
|
||||
if (watcher.getSpellOrder(input, game) == 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ class KumanosBlessingEffect extends ReplacementEffectImpl {
|
|||
if (zce.isDiesEvent()) {
|
||||
DamagedByEnchantedWatcher watcher = (DamagedByEnchantedWatcher) game.getState().getWatchers().get("DamagedByEnchantedWatcher", source.getSourceId());
|
||||
if (watcher != null) {
|
||||
return watcher.wasDamaged(zce.getTarget());
|
||||
return watcher.wasDamaged(zce.getTarget(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -177,7 +177,7 @@ class DamagedByEnchantedWatcher extends Watcher {
|
|||
damagedCreatures.clear();
|
||||
}
|
||||
|
||||
public boolean wasDamaged(Permanent permanent) {
|
||||
return damagedCreatures.contains(new MageObjectReference(permanent));
|
||||
public boolean wasDamaged(Permanent permanent, Game game) {
|
||||
return damagedCreatures.contains(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,12 +85,12 @@ class BileBlightEffect extends BoostAllEffect {
|
|||
Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (target != null) {
|
||||
if (target.getName().isEmpty()) { // face down creature
|
||||
affectedObjectList.add(new MageObjectReference(target));
|
||||
affectedObjectList.add(new MageObjectReference(target, game));
|
||||
} else {
|
||||
String name = target.getLogName();
|
||||
for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
|
||||
if (perm.getLogName().equals(name)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class GainProtectionFromColorSourceEffect extends GainAbilitySourceEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && new MageObjectReference(permanent).refersTo(source.getSourceObject(game))) {
|
||||
if (permanent != null && new MageObjectReference(permanent, game).refersTo(source.getSourceObject(game), game)) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
} else {
|
||||
// the source permanent is no longer on the battlefield, effect can be discarded
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class TakenoSamuraiGeneralEffect extends ContinuousEffectImpl {
|
|||
if (!perm.getId().equals(source.getSourceId())) {
|
||||
for (Ability ability : perm.getAbilities()) {
|
||||
if (ability instanceof BushidoAbility) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ class BroodingSaurianControlEffect extends ContinuousEffectImpl {
|
|||
FilterPermanent playerFilter = filter.copy();
|
||||
playerFilter.add(new OwnerIdPredicate(playerId));
|
||||
for (Permanent permanent :game.getBattlefield().getActivePermanents(playerFilter, playerId, game)) {
|
||||
affectedObjectList.add(new MageObjectReference(permanent));
|
||||
affectedObjectList.add(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class HomewardPathControlEffect extends ContinuousEffectImpl {
|
|||
FilterPermanent playerFilter = filter.copy();
|
||||
playerFilter.add(new OwnerIdPredicate(playerId));
|
||||
for (Permanent permanent :game.getBattlefield().getActivePermanents(playerFilter, playerId, game)) {
|
||||
affectedObjectList.add(new MageObjectReference(permanent));
|
||||
affectedObjectList.add(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class JelevaNephaliasScourgeEffect extends OneShotEffect {
|
|||
if (controller != null && sourceCard != null) {
|
||||
JelevaNephaliasWatcher watcher = (JelevaNephaliasWatcher) game.getState().getWatchers().get("ManaPaidToCastJelevaNephalias", source.getSourceId());
|
||||
if (watcher != null) {
|
||||
int xValue = watcher.getManaSpentToCastLastTime(sourceCard.getZoneChangeCounter() - 1);
|
||||
int xValue = watcher.getManaSpentToCastLastTime(sourceCard.getZoneChangeCounter(game) - 1);
|
||||
if (xValue > 0) {
|
||||
for (UUID playerId : controller.getInRange()) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
|
|
@ -195,8 +195,8 @@ class JelevaNephaliasWatcher extends Watcher {
|
|||
for (StackObject stackObject : game.getStack()) {
|
||||
if (stackObject instanceof Spell && ((Spell)stackObject).getSourceId().equals(sourceId)) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (!manaSpendToCast.containsValue(card.getZoneChangeCounter())) {
|
||||
manaSpendToCast.put(new Integer(card.getZoneChangeCounter()), new Integer(((Spell)stackObject).getSpellAbility().getManaCostsToPay().convertedManaCost()));
|
||||
if (!manaSpendToCast.containsValue(card.getZoneChangeCounter(game))) {
|
||||
manaSpendToCast.put(new Integer(card.getZoneChangeCounter(game)), new Integer(((Spell)stackObject).getSpellAbility().getManaCostsToPay().convertedManaCost()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class LivingLoreSetPowerToughnessSourceEffect extends ContinuousEffectImpl {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
MageObject mageObject = source.getSourceObject(game);
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && mageObject == null && new MageObjectReference(permanent).refersTo(mageObject)) {
|
||||
if (permanent != null && mageObject == null && new MageObjectReference(permanent, game).refersTo(mageObject, game)) {
|
||||
discard();
|
||||
return false;
|
||||
}
|
||||
|
|
@ -190,7 +190,7 @@ class LivingLoreSacrificeEffect extends OneShotEffect {
|
|||
if (controller != null) {
|
||||
MageObject mageObject = source.getSourceObject(game);
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && mageObject != null && new MageObjectReference(permanent).refersTo(mageObject)) {
|
||||
if (permanent != null && mageObject != null && new MageObjectReference(permanent, game).refersTo(mageObject, game)) {
|
||||
if (permanent.sacrifice(source.getSourceId(), game)) {
|
||||
UUID exileId = CardUtil.getObjectExileZoneId(game, mageObject);
|
||||
if (exileId != null) {
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class MythRealizedSetPTEffect extends ContinuousEffectImpl {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && new MageObjectReference(source.getSourceObject(game)).refersTo(permanent)) {
|
||||
if (permanent != null && new MageObjectReference(source.getSourceObject(game), game).refersTo(permanent, game)) {
|
||||
int amount = permanent.getCounters().getCount(CounterType.LORE);
|
||||
permanent.getPower().setValue(amount);
|
||||
permanent.getToughness().setValue(amount);
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ class GainProtectionFromColorSourceEffect extends GainAbilitySourceEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && new MageObjectReference(permanent).refersTo(source.getSourceObject(game))) {
|
||||
if (permanent != null && new MageObjectReference(permanent, game).refersTo(source.getSourceObject(game), game)) {
|
||||
permanent.addAbility(ability, source.getSourceId(), game);
|
||||
} else {
|
||||
// the source permanent is no longer on the battlefield, effect can be discarded
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class GhastlyConscriptionEffect extends OneShotEffect {
|
|||
manaCosts = new ManaCostsImpl("{0}");
|
||||
}
|
||||
}
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game);
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter(game) +1, game);
|
||||
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource);
|
||||
if (controller.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId(), false, true)) {
|
||||
game.informPlayers(new StringBuilder(controller.getName())
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ class JeskaiInfiltratorEffect extends OneShotEffect {
|
|||
manaCosts = new ManaCostsImpl("{0}");
|
||||
}
|
||||
}
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game);
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter(game) +1, game);
|
||||
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource);
|
||||
if (player.putOntoBattlefieldWithInfo(card, game, Zone.EXILED, source.getSourceId(), false, true)) {
|
||||
game.informPlayers(new StringBuilder(player.getName())
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class UnboostCreaturesTargetPlayerEffect extends ContinuousEffectImpl {
|
|||
super.init(source, game);
|
||||
if (this.affectedObjectsSet) {
|
||||
for (Permanent creature : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), getTargetPointer().getFirst(game, source), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(creature));
|
||||
affectedObjectList.add(new MageObjectReference(creature, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,9 +123,9 @@ class SoulflayerEffect extends ContinuousEffectImpl implements SourceEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null) {
|
||||
if (objectReference == null || !objectReference.refersTo(permanent)) {
|
||||
if (objectReference == null || !objectReference.refersTo(permanent, game)) {
|
||||
abilitiesToAdd = new HashSet<>();
|
||||
this.objectReference = new MageObjectReference(permanent);
|
||||
this.objectReference = new MageObjectReference(permanent, game);
|
||||
String keyString = CardUtil.getCardZoneString("delvedCards", source.getSourceId(), game, true);
|
||||
List<Card> delvedCards = (List<Card>) game.getState().getValue(keyString);
|
||||
if (delvedCards != null) {
|
||||
|
|
|
|||
|
|
@ -132,9 +132,9 @@ class JuxtaposeEffect extends ContinuousEffectImpl {
|
|||
return;
|
||||
}
|
||||
this.lockedControllers.put(permanent1.getId(), permanent2.getControllerId());
|
||||
this.zoneChangeCounter.put(permanent1.getId(), permanent1.getZoneChangeCounter());
|
||||
this.zoneChangeCounter.put(permanent1.getId(), permanent1.getZoneChangeCounter(game));
|
||||
this.lockedControllers.put(permanent2.getId(), permanent1.getControllerId());
|
||||
this.zoneChangeCounter.put(permanent2.getId(), permanent2.getZoneChangeCounter());
|
||||
this.zoneChangeCounter.put(permanent2.getId(), permanent2.getZoneChangeCounter(game));
|
||||
|
||||
permanent1.changeControllerId(targetPlayer.getId(), game);
|
||||
permanent2.changeControllerId(you.getId(), game);
|
||||
|
|
@ -153,7 +153,7 @@ class JuxtaposeEffect extends ContinuousEffectImpl {
|
|||
Set<UUID> toDelete = new HashSet<>();
|
||||
for (Map.Entry<UUID, Integer> entry : zoneChangeCounter.entrySet()) {
|
||||
Permanent permanent = game.getPermanent(entry.getKey());
|
||||
if (permanent == null || permanent.getZoneChangeCounter() != entry.getValue()) {
|
||||
if (permanent == null || permanent.getZoneChangeCounter(game) != entry.getValue()) {
|
||||
// controll effect cease if the same permanent is no longer on the battlefield
|
||||
toDelete.add(entry.getKey());
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ class TheWretchedEffect extends OneShotEffect {
|
|||
BlockedAttackerWatcher watcher = (BlockedAttackerWatcher) game.getState().getWatchers().get("BlockedAttackerWatcher");
|
||||
if (watcher != null) {
|
||||
for (Permanent creature : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), game)) {
|
||||
if (watcher.creatureHasBlockedAttacker(theWretched, creature)
|
||||
if (watcher.creatureHasBlockedAttacker(theWretched, creature, game)
|
||||
&& !creature.isRemovedFromCombat()) {
|
||||
ContinuousEffect effect = new ConditionalContinuousEffect(new GainControlTargetEffect(Duration.Custom, source.getControllerId()), new SourceOnBattlefieldControlUnchangedCondition(), "test");
|
||||
effect.setTargetPointer(new FixedTarget(creature.getId()));
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class ScoutsWarningAsThoughEffect extends AsThoughEffectImpl {
|
|||
watcher = (ScoutsWarningWatcher) game.getState().getWatchers().get("consumeScoutsWarningWatcher", source.getControllerId());
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (watcher != null && card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
watcher.addScoutsWarningSpell(source.getSourceId(), zoneChangeCounter);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,32 +110,32 @@ class AureliaAttacksTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public void reset(Game game) {
|
||||
Card sourceCard = game.getCard(getSourceId());
|
||||
game.getState().setValue(getValueKey(sourceCard), new Integer(0));
|
||||
game.getState().setValue(getValueKey(sourceCard, game), new Integer(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType() == EventType.ATTACKER_DECLARED && event.getSourceId().equals(this.getSourceId()) ) {
|
||||
Card sourceCard = game.getCard(getSourceId());
|
||||
Integer amountAttacks = (Integer) game.getState().getValue(getValueKey(sourceCard));
|
||||
Integer amountAttacks = (Integer) game.getState().getValue(getValueKey(sourceCard, game));
|
||||
if (amountAttacks == null || amountAttacks.intValue() < 1) {
|
||||
if (amountAttacks == null) {
|
||||
amountAttacks = new Integer(1);
|
||||
} else {
|
||||
++amountAttacks;
|
||||
}
|
||||
game.getState().setValue(getValueKey(sourceCard), amountAttacks);
|
||||
game.getState().setValue(getValueKey(sourceCard, game), amountAttacks);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String getValueKey(Card sourceCard) {
|
||||
protected String getValueKey(Card sourceCard, Game game) {
|
||||
if (sourceCard == null) {
|
||||
return "";
|
||||
}
|
||||
return new StringBuilder(this.getId().toString()).append(sourceCard.getZoneChangeCounter()).append("amountAttacks").toString();
|
||||
return new StringBuilder(this.getId().toString()).append(sourceCard.getZoneChangeCounter(game)).append("amountAttacks").toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -100,13 +100,13 @@ class CantBeBlockedByTokenEffect extends RestrictionEffect {
|
|||
public void init(Ability source, Game game) {
|
||||
affectedObjectsSet = true;
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
if (affectedObjectList.contains(new MageObjectReference(permanent))) {
|
||||
if (affectedObjectList.contains(new MageObjectReference(permanent, game))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class QuickenAsThoughEffect extends AsThoughEffectImpl {
|
|||
quickenWatcher = (QuickenWatcher) game.getState().getWatchers().get("consumeQuickenWatcher", source.getControllerId());
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (quickenWatcher != null && card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
quickenWatcher.addQuickenSpell(source.getSourceId(), zoneChangeCounter);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ class PastInFlamesEffect extends ContinuousEffectImpl {
|
|||
for (UUID cardId: player.getGraveyard()) {
|
||||
Card card = game.getCard(cardId);
|
||||
if (card.getCardType().contains(CardType.INSTANT) || card.getCardType().contains(CardType.SORCERY)) {
|
||||
affectedObjectList.add(new MageObjectReference(card));
|
||||
affectedObjectList.add(new MageObjectReference(card, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ class GodsendExileEffect extends OneShotEffect {
|
|||
if (creature != null && controller != null && sourcePermanent != null) {
|
||||
UUID exileId = CardUtil.getCardExileZoneId(game, source);
|
||||
controller.moveCardToExileWithInfo(creature, exileId,
|
||||
new StringBuilder(sourcePermanent.getName()).append(" (").append(sourcePermanent.getZoneChangeCounter()).append(")").toString()
|
||||
new StringBuilder(sourcePermanent.getName()).append(" (").append(sourcePermanent.getZoneChangeCounter(game)).append(")").toString()
|
||||
, source.getSourceId(), game, Zone.BATTLEFIELD);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,15 +110,15 @@ class AshlingThePilgrimEffect extends OneShotEffect {
|
|||
Object object = game.getState().getValue(source.getSourceId() + "ActivationInfo");
|
||||
if (object instanceof ActivationInfo) {
|
||||
info = (ActivationInfo) object;
|
||||
if (info.turn != game.getTurnNum() || sourcePermanent.getZoneChangeCounter() != info.zoneChangeCounter) {
|
||||
if (info.turn != game.getTurnNum() || sourcePermanent.getZoneChangeCounter(game) != info.zoneChangeCounter) {
|
||||
info.turn = game.getTurnNum();
|
||||
info.zoneChangeCounter = sourcePermanent.getZoneChangeCounter();
|
||||
info.zoneChangeCounter = sourcePermanent.getZoneChangeCounter(game);
|
||||
info.activations = 0;
|
||||
}
|
||||
} else {
|
||||
info = new ActivationInfo();
|
||||
info.turn = game.getTurnNum();
|
||||
info.zoneChangeCounter = sourcePermanent.getZoneChangeCounter();
|
||||
info.zoneChangeCounter = sourcePermanent.getZoneChangeCounter(game);
|
||||
game.getState().setValue(source.getSourceId() + "ActivationInfo", info);
|
||||
}
|
||||
info.activations++;
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ class VengefulPharaohTriggeredAbility extends TriggeredAbilityImpl {
|
|||
// even if Vengeful Pharaoh is put back into your graveyard before it tries to resolve, as it's a
|
||||
// different Vengeful Pharaoh than the one that was there before.
|
||||
MageObjectReference mor = new MageObjectReference(getSourceId(), game);
|
||||
return mor.refersTo(this.getSourceObject(game));
|
||||
return mor.refersTo(this.getSourceObject(game), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class SavageSummoningAsThoughEffect extends AsThoughEffectImpl {
|
|||
watcher = (SavageSummoningWatcher) game.getState().getWatchers().get("consumeSavageSummoningWatcher", source.getControllerId());
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (watcher != null && card != null) {
|
||||
watcher.setSavageSummoningSpellActive(card);
|
||||
watcher.setSavageSummoningSpellActive(card, game);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Consume Savage watcher could not be found");
|
||||
}
|
||||
|
|
@ -174,7 +174,7 @@ class SavageSummoningWatcher extends Watcher {
|
|||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (spell != null && spell.getCardType().contains(CardType.CREATURE)) {
|
||||
spellsCastWithSavageSummoning.put(spell.getId(), new HashSet<>(savageSummoningSpells));
|
||||
String cardKey = new StringBuilder(spell.getCard().getId().toString()).append("_").append(spell.getCard().getZoneChangeCounter()).toString();
|
||||
String cardKey = new StringBuilder(spell.getCard().getId().toString()).append("_").append(spell.getCard().getZoneChangeCounter(game)).toString();
|
||||
cardsCastWithSavageSummoning.put(cardKey, new HashSet<>(savageSummoningSpells));
|
||||
savageSummoningSpells.clear();
|
||||
}
|
||||
|
|
@ -182,8 +182,8 @@ class SavageSummoningWatcher extends Watcher {
|
|||
}
|
||||
}
|
||||
|
||||
public void setSavageSummoningSpellActive(Card card) {
|
||||
String cardKey = new StringBuilder(card.getId().toString()).append("_").append(card.getZoneChangeCounter()).toString();
|
||||
public void setSavageSummoningSpellActive(Card card, Game game) {
|
||||
String cardKey = new StringBuilder(card.getId().toString()).append("_").append(card.getZoneChangeCounter(game)).toString();
|
||||
savageSummoningSpells.add(cardKey);
|
||||
}
|
||||
|
||||
|
|
@ -200,8 +200,8 @@ class SavageSummoningWatcher extends Watcher {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean isCardCastWithThisSavageSummoning(Card card, UUID cardId, int zoneChangeCounter) {
|
||||
String creatureCardKey = new StringBuilder(card.getId().toString()).append("_").append(card.getZoneChangeCounter()-1).toString();
|
||||
public boolean isCardCastWithThisSavageSummoning(Card card, UUID cardId, int zoneChangeCounter, Game game) {
|
||||
String creatureCardKey = new StringBuilder(card.getId().toString()).append("_").append(card.getZoneChangeCounter(game)-1).toString();
|
||||
// add one because card is now gone to battlefield as creature
|
||||
String cardKey = new StringBuilder(cardId.toString()).append("_").append(zoneChangeCounter).toString();
|
||||
HashSet<String> savageSpells = (HashSet<String>) cardsCastWithSavageSummoning.get(creatureCardKey);
|
||||
|
|
@ -243,7 +243,7 @@ class SavageSummoningCantCounterEffect extends ContinuousRuleModifyingEffectImpl
|
|||
if (watcher == null || card == null) {
|
||||
throw new IllegalArgumentException("Consume Savage watcher or card could not be found");
|
||||
}
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter();
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -300,7 +300,7 @@ class SavageSummoningEntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
if (watcher == null || card == null) {
|
||||
throw new IllegalArgumentException("Consume Savage watcher or card could not be found");
|
||||
}
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter();
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -327,7 +327,7 @@ class SavageSummoningEntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if ((event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD)) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null && watcher.isCardCastWithThisSavageSummoning(card, source.getSourceId(), zoneChangeCounter)) {
|
||||
if (card != null && watcher.isCardCastWithThisSavageSummoning(card, source.getSourceId(), zoneChangeCounter, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class PolymorphistsJestEffect extends ContinuousEffectImpl {
|
|||
super.init(source, game);
|
||||
if (this.affectedObjectsSet) {
|
||||
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, getTargetPointer().getFirst(game, source), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(permanent));
|
||||
affectedObjectList.add(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class ScytheOfTheWretchedTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return false;
|
||||
}
|
||||
for (MageObjectReference mor : zoneChange.getTarget().getDealtDamageByThisTurn()) {
|
||||
if (mor.refersTo(equippedCreature)) {
|
||||
if (mor.refersTo(equippedCreature, game)) {
|
||||
setTarget(new FixedTarget(event.getTargetId()));
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ class JhoiraOfTheGhituSuspendEffect extends OneShotEffect {
|
|||
if (controller.moveCardToExileWithInfo(card, exileId, "Suspended cards of " + controller.getName(), source.getSourceId(), game, Zone.HAND)) {
|
||||
card.addCounters(CounterType.TIME.createInstance(4), game);
|
||||
if (!hasSuspend) {
|
||||
game.addEffect(new JhoiraGainSuspendEffect(new MageObjectReference(card)), source);
|
||||
game.addEffect(new JhoiraGainSuspendEffect(new MageObjectReference(card, game)), source);
|
||||
}
|
||||
game.informPlayers(controller.getName() + " suspends 4 - " + card.getName());
|
||||
return true;
|
||||
|
|
@ -160,7 +160,7 @@ class JhoiraGainSuspendEffect extends ContinuousEffectImpl implements SourceEffe
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Card card = game.getCard(mor.getSourceId());
|
||||
if (card != null && mor.refersTo(card) && game.getState().getZone(card.getId()).equals(Zone.EXILED)) {
|
||||
if (card != null && mor.refersTo(card, game) && game.getState().getZone(card.getId()).equals(Zone.EXILED)) {
|
||||
SuspendAbility.addSuspendTemporaryToCard(card, source, game);
|
||||
} else {
|
||||
discard();
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class BecomesCreatureAllEffect extends ContinuousEffectImpl {
|
|||
super.init(source, game);
|
||||
this.affectedObjectsSet = true;
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(new FilterLandPermanent(), source.getControllerId(), source.getSourceId(), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,12 +123,12 @@ class RallyTheRighteousBoostEffect extends ContinuousEffectImpl {
|
|||
super.init(source, game);
|
||||
Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (target != null) {
|
||||
affectedObjectList.add(new MageObjectReference(target));
|
||||
affectedObjectList.add(new MageObjectReference(target, game));
|
||||
ObjectColor color = target.getColor();
|
||||
target.addPower(2);
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (!permanent.getId().equals(target.getId()) && permanent.getColor().shares(color)) {
|
||||
affectedObjectList.add(new MageObjectReference(permanent));
|
||||
affectedObjectList.add(new MageObjectReference(permanent, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class GraveBetrayalTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (card != null) {
|
||||
Effect effect = new GraveBetrayalEffect();
|
||||
effect.setTargetPointer(new FixedTarget(card.getId()));
|
||||
Integer zoneChanges = card.getZoneChangeCounter();
|
||||
Integer zoneChanges = card.getZoneChangeCounter(game);
|
||||
effect.setValue("zoneChanges", zoneChanges);
|
||||
|
||||
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(effect);
|
||||
|
|
@ -150,7 +150,7 @@ class GraveBetrayalEffect extends OneShotEffect {
|
|||
Card card = game.getCard(targetPointer.getFirst(game, source));
|
||||
if (card != null) {
|
||||
Integer zoneChanges = (Integer) getValue("zoneChanges");
|
||||
if (card.getZoneChangeCounter() == zoneChanges) {
|
||||
if (card.getZoneChangeCounter(game) == zoneChanges) {
|
||||
Zone currentZone = game.getState().getZone(card.getId());
|
||||
if (card.putOntoBattlefield(game, currentZone, source.getSourceId(), source.getControllerId())) {
|
||||
Permanent creature = game.getPermanent(card.getId());
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ class TrostaniSelesnyasVoiceTriggeredAbility extends TriggeredAbilityImpl {
|
|||
&& event.getTargetId() != this.getSourceId()) {
|
||||
Effect effect = this.getEffects().get(0);
|
||||
effect.setValue("lifeSource", event.getTargetId());
|
||||
effect.setValue("zoneChangeCounter", permanent.getZoneChangeCounter());
|
||||
effect.setValue("zoneChangeCounter", permanent.getZoneChangeCounter(game));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ class TrostaniSelesnyasVoiceEffect extends OneShotEffect {
|
|||
UUID creatureId = (UUID) getValue("lifeSource");
|
||||
Integer zoneChangeCounter = (Integer) getValue("zoneChangeCounter");
|
||||
Permanent creature = game.getPermanent(creatureId);
|
||||
if (creature == null || creature.getZoneChangeCounter() != zoneChangeCounter) {
|
||||
if (creature == null || creature.getZoneChangeCounter(game) != zoneChangeCounter) {
|
||||
creature = (Permanent) game.getLastKnownInformation(creatureId, Zone.BATTLEFIELD, zoneChangeCounter);
|
||||
}
|
||||
if (creature != null) {
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ class LeoninArbiterIgnoreEffect extends OneShotEffect {
|
|||
String key = permanent.getId() + keyString;
|
||||
|
||||
// Using a Map.Entry since there is no pair class
|
||||
long zoneChangeCount = permanent.getZoneChangeCounter();
|
||||
long zoneChangeCount = permanent.getZoneChangeCounter(game);
|
||||
long turnNum = game.getTurnNum();
|
||||
Long activationState = zoneChangeCount << 32 | turnNum & 0xFFFFFFFFL;
|
||||
|
||||
|
|
@ -170,7 +170,7 @@ class LeoninArbiterCantSearchEffect extends ContinuousRuleModifyingEffectImpl {
|
|||
String key = permanent.getId() + keyString;
|
||||
Map.Entry<Long, Set<UUID>> turnIgnoringPlayersPair = (Map.Entry<Long, Set<UUID>>) game.getState().getValue(key);
|
||||
if (turnIgnoringPlayersPair != null) {
|
||||
long zoneChangeCount = permanent.getZoneChangeCounter();
|
||||
long zoneChangeCount = permanent.getZoneChangeCounter(game);
|
||||
long turnNum = game.getTurnNum();
|
||||
Long activationState = zoneChangeCount << 32 | turnNum & 0xFFFFFFFFL;
|
||||
if (activationState.equals(turnIgnoringPlayersPair.getKey())) {
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ class SkeletonizeDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
|||
if (zce.isDiesEvent()) {
|
||||
DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", this.getSourceId());
|
||||
if (watcher != null) {
|
||||
return watcher.wasDamaged(zce.getTarget());
|
||||
return watcher.wasDamaged(zce.getTarget(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class MarchOfTheMachinesEffect extends ContinuousEffectImpl {
|
|||
affectedObjectList.clear();
|
||||
for(Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, game)){
|
||||
if(permanent != null){
|
||||
affectedObjectList.add(new MageObjectReference(permanent));
|
||||
affectedObjectList.add(new MageObjectReference(permanent, game));
|
||||
permanent.getCardType().add(CardType.CREATURE);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ class TimeToFeedTextEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Permanent creature = game.getPermanent(this.getTargetPointer().getFirst(game, source));
|
||||
if (creature != null) {
|
||||
DelayedTriggeredAbility ability = new TimeToFeedDiesTriggeredAbility(creature.getId(), creature.getZoneChangeCounter());
|
||||
DelayedTriggeredAbility ability = new TimeToFeedDiesTriggeredAbility(creature.getId(), creature.getZoneChangeCounter(game));
|
||||
new CreateDelayedTriggeredAbilityEffect(ability, false).apply(game, source);
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +155,7 @@ class TimeToFeedDiesTriggeredAbility extends DelayedTriggeredAbility {
|
|||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) {
|
||||
if (event.getTargetId().equals(watchedCreatureId)) {
|
||||
Permanent creature = (Permanent) game.getLastKnownInformation(watchedCreatureId, Zone.BATTLEFIELD);
|
||||
if (creature.getZoneChangeCounter() == this.zoneChangeCounter) {
|
||||
if (creature.getZoneChangeCounter(game) == this.zoneChangeCounter) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ class TritonTacticsUntapTargetEffect extends OneShotEffect {
|
|||
} else {
|
||||
targetMap = new HashMap<>();
|
||||
}
|
||||
targetMap.put(new Integer(game.getCard(source.getSourceId()).getZoneChangeCounter()), targets);
|
||||
targetMap.put(new Integer(game.getCard(source.getSourceId()).getZoneChangeCounter(game)), targets);
|
||||
if (object == null) {
|
||||
game.getState().setValue("targets" + source.getSourceId().toString(), targetMap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ class SuddenSpoilingEffect extends ContinuousEffectImpl {
|
|||
Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
||||
if (player != null) {
|
||||
for (Permanent perm: game.getState().getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ class SuddenSpoilingEffect extends ContinuousEffectImpl {
|
|||
Player player = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
||||
if (player != null) {
|
||||
for (Permanent permanent : game.getState().getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), player.getId(), game)) {
|
||||
if (affectedObjectList.contains(new MageObjectReference(permanent))) {
|
||||
if (affectedObjectList.contains(new MageObjectReference(permanent, game))) {
|
||||
switch (layer) {
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
permanent.removeAllAbilities(source.getSourceId(), game);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ class DiabolicServitudeCreatureDiesTriggeredAbility extends TriggeredAbilityImpl
|
|||
if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
Object object = game.getState().getValue(getSourceId().toString() + "returnedCreature");
|
||||
if ((object instanceof MageObjectReference) && ((MageObjectReference)object).refersTo(zEvent.getTarget())) {
|
||||
if ((object instanceof MageObjectReference) && ((MageObjectReference)object).refersTo(zEvent.getTarget(), game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class MarshCasualtiesEffect extends ContinuousEffectImpl {
|
|||
super.init(source, game);
|
||||
if (this.affectedObjectsSet) {
|
||||
for (Permanent creature : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getFirstTarget(), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(creature));
|
||||
affectedObjectList.add(new MageObjectReference(creature, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class KickerTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* 702.32. Kicker
|
||||
* 702.32a Kicker is a static ability that functions while the spell with kicker is on the stack. “Kicker
|
||||
* [cost]” means “You may pay an additional [cost] as you cast this spell.” Paying a spell’s kicker
|
||||
* cost(s) follows the rules for paying additional costs in rules 601.2b and 601.2e–g.
|
||||
* 702.32b The phrase “Kicker [cost 1] and/or [cost 2]” means the same thing as “Kicker [cost 1],
|
||||
* kicker [cost 2].”
|
||||
* 702.32c Multikicker is a variant of the kicker ability. “Multikicker [cost]” means “You may pay an
|
||||
* additional [cost] any number of times as you cast this spell.” A multikicker cost is a kicker cost.
|
||||
* 702.32d If a spell’s controller declares the intention to pay any of that spell’s kicker costs, that spell
|
||||
* has been “kicked.” If a spell has two kicker costs or has multikicker, it may be kicked multiple
|
||||
* times. See rule 601.2b.
|
||||
* 702.32e Objects with kicker or multikicker have additional abilities that specify what happens if
|
||||
* they are kicked. These abilities are linked to the kicker or multikicker abilities printed on that
|
||||
* object: they can refer only to those specific kicker or multikicker abilities. See rule 607, “Linked
|
||||
* Abilities.”
|
||||
* 702.32f Objects with more than one kicker cost have abilities that each correspond to a specific
|
||||
* kicker cost. They contain the phrases “if it was kicked with its [A] kicker” and “if it was kicked
|
||||
* with its [B] kicker,” where A and B are the first and second kicker costs listed on the card,
|
||||
* respectively. Each of those abilities is linked to the appropriate kicker ability.
|
||||
* 702.32g If part of a spell’s ability has its effect only if that spell was kicked, and that part of the
|
||||
* ability includes any targets, the spell’s controller chooses those targets only if that spell was
|
||||
* kicked. Otherwise, the spell is cast as if it did not have those targets. See rule 601.2c.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* AEther Figment
|
||||
* Creature — Illusion 1/1, 1U (2)
|
||||
* Kicker {3} (You may pay an additional {3} as you cast this spell.)
|
||||
* AEther Figment can't be blocked.
|
||||
* If AEther Figment was kicked, it enters the battlefield with two +1/+1 counters on it.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testUseKicker() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
addCard(Zone.HAND, playerA, "AEther Figment");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "AEther Figment");
|
||||
setChoice(playerA, "Yes");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "AEther Figment", 1);
|
||||
assertCounterCount("AEther Figment", CounterType.P1P1, 2);
|
||||
assertPowerToughness(playerA, "AEther Figment", 3, 3);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDontUseKicker() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 5);
|
||||
addCard(Zone.HAND, playerA, "AEther Figment");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "AEther Figment");
|
||||
setChoice(playerA, "No");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "AEther Figment", 1);
|
||||
assertCounterCount("AEther Figment", CounterType.P1P1, 0);
|
||||
assertPowerToughness(playerA, "AEther Figment", 1, 1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Apex Hawks
|
||||
* Creature — Bird 2/2, 2W (3)
|
||||
* Multikicker {1}{W} (You may pay an additional {1}{W} any number of times as you cast this spell.)
|
||||
* Flying
|
||||
* Apex Hawks enters the battlefield with a +1/+1 counter on it for each time it was kicked.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testUseMultikickerOnce() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.HAND, playerA, "Apex Hawks");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Apex Hawks");
|
||||
setChoice(playerA, "Yes");
|
||||
setChoice(playerA, "No");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Apex Hawks", 1);
|
||||
assertCounterCount("Apex Hawks", CounterType.P1P1, 1);
|
||||
assertPowerToughness(playerA, "Apex Hawks", 3, 3);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUseMultikickerTwice() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 7);
|
||||
addCard(Zone.HAND, playerA, "Apex Hawks");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Apex Hawks");
|
||||
setChoice(playerA, "Yes");
|
||||
setChoice(playerA, "Yes");
|
||||
setChoice(playerA, "No");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Apex Hawks", 1);
|
||||
assertCounterCount("Apex Hawks", CounterType.P1P1, 2);
|
||||
assertPowerToughness(playerA, "Apex Hawks", 4, 4);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDontUseMultikicker() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 7);
|
||||
addCard(Zone.HAND, playerA, "Apex Hawks");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Apex Hawks");
|
||||
setChoice(playerA, "No");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Apex Hawks", 1);
|
||||
assertCounterCount("Apex Hawks", CounterType.P1P1, 0);
|
||||
assertPowerToughness(playerA, "Apex Hawks", 2, 2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class StormTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* 702.39. Storm
|
||||
* 702.39a Storm is a triggered ability that functions on the stack. “Storm” means “When you cast this
|
||||
* spell, put a copy of it onto the stack for each other spell that was cast before it this turn. If the
|
||||
* spell has any targets, you may choose new targets for any of the copies.”
|
||||
* 702.39b If a spell has multiple instances of storm, each triggers separately.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Grapeshot
|
||||
* Sorcery, 1R (2)
|
||||
* Grapeshot deals 1 damage to target creature or player.
|
||||
* Storm (When you cast this spell, copy it for each spell cast before it
|
||||
* this turn. You may choose new targets for the copies.)
|
||||
*
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testStorm1x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.HAND, playerA, "Grapeshot");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grapeshot", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStorm2x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
addCard(Zone.HAND, playerA, "Grapeshot");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grapeshot", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 11);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStorm3x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||
addCard(Zone.HAND, playerA, "Grapeshot");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grapeshot", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStorm4x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
|
||||
addCard(Zone.HAND, playerA, "Grapeshot");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grapeshot", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoStorm() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
addCard(Zone.HAND, playerA, "Grapeshot");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grapeshot", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 19);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.continuous;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class MarchOfTheMachinesTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* March of the Machines
|
||||
* Enchantment, 3U (4)
|
||||
* Each noncreature artifact is an artifact creature with power and toughness
|
||||
* each equal to its converted mana cost. (Equipment that's a creature can't
|
||||
* equip a creature.)
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abzan Banner
|
||||
* Artifact, 3 (3)
|
||||
* {T}: Add {W}, {B}, or {G} to your mana pool.
|
||||
* {W}{B}{G}, {T}, Sacrifice Abzan Banner: Draw a card.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testNonCreatureArtifactsBecomeCreatures() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Abzan Banner");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Alloy Myr");
|
||||
addCard(Zone.HAND, playerA, "March of the Machines");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "March of the Machines");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, "Alloy Myr", 2, 2);
|
||||
assertPermanentCount(playerA, "Abzan Banner", 1);
|
||||
assertPowerToughness(playerA, "Abzan Banner", 3, 3);
|
||||
assertType("Abzan Banner", CardType.CREATURE, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArtifactsRevertBack() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Abzan Banner");
|
||||
addCard(Zone.HAND, playerA, "March of the Machines");
|
||||
|
||||
addCard(Zone.HAND, playerB, "Disenchant");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "March of the Machines");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Disenchant", "March of the Machines");
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Abzan Banner", 1);
|
||||
assertType("Abzan Banner", CardType.CREATURE, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquipmentDetaches() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Avacyn's Collar");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Ornithopter");
|
||||
addCard(Zone.HAND, playerA, "March of the Machines");
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Ornithopter");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "March of the Machines");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Ornithopter", 1);
|
||||
assertPowerToughness(playerA, "Ornithopter", 0, 2);
|
||||
assertPermanentCount(playerA, "Avacyn's Collar", 1);
|
||||
assertPowerToughness(playerA, "Avacyn's Collar", 1, 1);
|
||||
assertType("Avacyn's Collar", CardType.CREATURE, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZeroCostIsDestroyed() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Accorder's Shield");
|
||||
addCard(Zone.HAND, playerA, "March of the Machines");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "March of the Machines");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Accorder's Shield", 0);
|
||||
assertGraveyardCount(playerA, "Accorder's Shield", 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.dynamicvalue;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class SweepTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
/**
|
||||
* Plow Through Reito
|
||||
* 1W
|
||||
* Instant -- Arcane
|
||||
* Sweep -- Return any number of Plains you control to their owner's hand.
|
||||
* Target creature gets +1/+1 until end of turn for each Plains returned this way.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testSweep1x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
|
||||
addCard(Zone.HAND, playerA, "Plow Through Reito");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
|
||||
addTarget(playerA, "Plains");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Raging Goblin", 1);
|
||||
assertPermanentCount(playerA, "Plains", 4);
|
||||
assertPowerToughness(playerA, "Raging Goblin", 2, 2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSweep2x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
|
||||
addCard(Zone.HAND, playerA, "Plow Through Reito");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
|
||||
addTarget(playerA, "Plains^Plains");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Raging Goblin", 1);
|
||||
assertPermanentCount(playerA, "Plains", 3);
|
||||
assertPowerToughness(playerA, "Raging Goblin", 3, 3);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSweep3x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
|
||||
addCard(Zone.HAND, playerA, "Plow Through Reito");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
|
||||
addTarget(playerA, "Plains^Plains^Plains");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Raging Goblin", 1);
|
||||
assertPermanentCount(playerA, "Plains", 2);
|
||||
assertPowerToughness(playerA, "Raging Goblin", 4, 4);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSweep0x() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
|
||||
addCard(Zone.HAND, playerA, "Plow Through Reito");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Raging Goblin", 1);
|
||||
assertPermanentCount(playerA, "Plains", 5);
|
||||
assertPowerToughness(playerA, "Raging Goblin", 1, 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,6 +11,28 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
*/
|
||||
public class HuntmasterOfTheFellsTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* Huntmaster of the Fells
|
||||
* Creature — Human Werewolf 2/2, 2RG (4)
|
||||
* Whenever this creature enters the battlefield or transforms into Huntmaster
|
||||
* of the Fells, put a 2/2 green Wolf creature token onto the battlefield and
|
||||
* you gain 2 life.
|
||||
* At the beginning of each upkeep, if no spells were cast last turn, transform
|
||||
* Huntmaster of the Fells.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Ravager of the Fells
|
||||
* Creature — Werewolf 4/4
|
||||
* Trample
|
||||
* Whenever this creature transforms into Ravager of the Fells, it deals 2
|
||||
* damage to target opponent and 2 damage to up to one target creature that
|
||||
* player controls.
|
||||
* At the beginning of each upkeep, if a player cast two or more spells last
|
||||
* turn, transform Ravager of the Fells.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testCard() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import java.io.FilenameFilter;
|
|||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import static org.mage.test.serverside.base.MageTestPlayerBase.currentGame;
|
||||
|
||||
/**
|
||||
* Base class for all tests.
|
||||
|
|
@ -259,7 +260,7 @@ public abstract class MageTestBase {
|
|||
Card card = cardInfo != null ? cardInfo.getCard() : null;
|
||||
if (card != null) {
|
||||
if (gameZone.equals(Zone.BATTLEFIELD)) {
|
||||
PermanentCard p = new PermanentCard(card, null);
|
||||
PermanentCard p = new PermanentCard(card, null, currentGame);
|
||||
p.setTapped(tapped);
|
||||
perms.add(p);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ public abstract class MageTestPlayerBase {
|
|||
Card card = cardInfo != null ? cardInfo.getCard() : null;
|
||||
if (card != null) {
|
||||
if (gameZone.equals(Zone.BATTLEFIELD)) {
|
||||
PermanentCard p = new PermanentCard(card, null);
|
||||
PermanentCard p = new PermanentCard(card, null, currentGame);
|
||||
p.setTapped(tapped);
|
||||
perms.add(p);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ public abstract class CardTestAPIImpl extends MageTestBase implements CardTestAP
|
|||
if (card == null) {
|
||||
throw new IllegalArgumentException("[TEST] Couldn't find a card: " + cardName);
|
||||
}
|
||||
PermanentCard p = new PermanentCard(card, null);
|
||||
PermanentCard p = new PermanentCard(card, null, currentGame);
|
||||
p.setTapped(tapped);
|
||||
if (player.equals(playerA)) {
|
||||
battlefieldCardsA.add(p);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import java.util.UUID;
|
|||
public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implements CardTestAPI {
|
||||
|
||||
static {
|
||||
// CardScanner.scanned = true;
|
||||
CardScanner.scan();
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +169,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
if (card == null) {
|
||||
throw new IllegalArgumentException("[TEST] Couldn't find a card: " + cardName);
|
||||
}
|
||||
PermanentCard p = new PermanentCard(card, null);
|
||||
PermanentCard p = new PermanentCard(card, null, currentGame);
|
||||
p.setTapped(tapped);
|
||||
getBattlefieldCards(player).add(p);
|
||||
}
|
||||
|
|
@ -511,6 +512,28 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
|
|||
*
|
||||
* @param cardName Name of the permanent that should be checked.
|
||||
* @param type A type to test for
|
||||
* @param flag true if creature should have type, false if it should not
|
||||
*/
|
||||
public void assertType(String cardName, CardType type, boolean flag) throws AssertionError {
|
||||
Permanent found = null;
|
||||
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
|
||||
if (permanent.getName().equals(cardName)) {
|
||||
found = permanent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertNotNull("There is no such permanent on the battlefield, cardName=" + cardName, found);
|
||||
|
||||
Assert.assertTrue("(Battlefield) card type not found (" + cardName + ":" + type + ")", (found.getCardType().contains(type) == flag));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether a permanent is a specified type
|
||||
*
|
||||
* @param cardName Name of the permanent that should be checked.
|
||||
* @param type A type to test for
|
||||
* @param subType a subtype to test for
|
||||
*/
|
||||
public void assertType(String cardName, CardType type, String subType) throws AssertionError {
|
||||
|
|
|
|||
|
|
@ -48,4 +48,9 @@ public interface MageObject extends MageItem, Serializable {
|
|||
* @return
|
||||
*/
|
||||
boolean isCopy();
|
||||
|
||||
int getZoneChangeCounter(Game game);
|
||||
void updateZoneChangeCounter(Game game);
|
||||
void setZoneChangeCounter(int value, Game game);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,4 +198,20 @@ public abstract class MageObjectImpl implements MageObject {
|
|||
public boolean isCopy() {
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter(Game game) {
|
||||
return game.getState().getZoneChangeCounter(objectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game) {
|
||||
game.getState().updateZoneChangeCounter(objectId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoneChangeCounter(int value, Game game) {
|
||||
game.getState().setZoneChangeCounter(objectId, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,26 +45,9 @@ public class MageObjectReference implements Comparable<MageObjectReference> {
|
|||
private final UUID sourceId;
|
||||
private final int zoneChangeCounter;
|
||||
|
||||
public MageObjectReference(Permanent permanent) {
|
||||
this.sourceId = permanent.getId();
|
||||
this.zoneChangeCounter = permanent.getZoneChangeCounter();
|
||||
}
|
||||
|
||||
public MageObjectReference(Card card) {
|
||||
this.sourceId = card.getId();
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter();
|
||||
}
|
||||
|
||||
public MageObjectReference(MageObject mageObject) {
|
||||
public MageObjectReference(MageObject mageObject, Game game) {
|
||||
this.sourceId = mageObject.getId();
|
||||
if (mageObject instanceof Card) {
|
||||
this.zoneChangeCounter = ((Card)mageObject).getZoneChangeCounter();
|
||||
} else if (mageObject instanceof Permanent) {
|
||||
this.zoneChangeCounter = ((Permanent)mageObject).getZoneChangeCounter();
|
||||
} else {
|
||||
this.zoneChangeCounter = 0;
|
||||
}
|
||||
|
||||
this.zoneChangeCounter = mageObject.getZoneChangeCounter(game);
|
||||
}
|
||||
/**
|
||||
* That values manually (can be used to let it reference to a Permanent
|
||||
|
|
@ -80,17 +63,12 @@ public class MageObjectReference implements Comparable<MageObjectReference> {
|
|||
}
|
||||
|
||||
public MageObjectReference(UUID sourceId, Game game) {
|
||||
MageObject mageObject = game.getObject(sourceId);
|
||||
this.sourceId = sourceId;
|
||||
if (mageObject instanceof Permanent) {
|
||||
this.zoneChangeCounter = ((Permanent)mageObject).getZoneChangeCounter();
|
||||
} else if (mageObject instanceof Card) {
|
||||
this.zoneChangeCounter = ((Card)mageObject).getZoneChangeCounter();
|
||||
} else if (mageObject instanceof Spell) {
|
||||
this.zoneChangeCounter = ((Spell)mageObject).getZoneChangeCounter();
|
||||
} else {
|
||||
zoneChangeCounter = 0;
|
||||
}
|
||||
MageObject mageObject = game.getObject(sourceId);
|
||||
if (mageObject != null)
|
||||
this.zoneChangeCounter = mageObject.getZoneChangeCounter(game);
|
||||
else
|
||||
this.zoneChangeCounter = 0;
|
||||
}
|
||||
|
||||
public UUID getSourceId() {
|
||||
|
|
@ -127,35 +105,16 @@ public class MageObjectReference implements Comparable<MageObjectReference> {
|
|||
}
|
||||
|
||||
public boolean refersTo(UUID id, Game game) {
|
||||
return refersTo(game.getObject(id));
|
||||
return refersTo(game.getObject(id), game);
|
||||
}
|
||||
|
||||
public boolean refersTo(Permanent permanent) {
|
||||
return permanent.getZoneChangeCounter()== zoneChangeCounter && permanent.getId().equals(sourceId);
|
||||
}
|
||||
|
||||
public boolean refersTo(Card card) {
|
||||
return card.getZoneChangeCounter()== zoneChangeCounter && card.getId().equals(sourceId);
|
||||
}
|
||||
|
||||
public boolean refersTo(Spell spell) {
|
||||
return spell.getZoneChangeCounter()== zoneChangeCounter && spell.getSourceId().equals(sourceId);
|
||||
}
|
||||
|
||||
public boolean refersTo(MageObject mageObject) {
|
||||
if (mageObject instanceof Permanent) {
|
||||
return refersTo(((Permanent)mageObject));
|
||||
} else if (mageObject instanceof Spell) {
|
||||
return refersTo(((Spell)mageObject));
|
||||
} else if (mageObject instanceof Card) {
|
||||
return refersTo(((Card)mageObject));
|
||||
}
|
||||
return mageObject.getId().equals(sourceId);
|
||||
public boolean refersTo(MageObject mageObject, Game game) {
|
||||
return mageObject.getId().equals(sourceId) && this.zoneChangeCounter == mageObject.getZoneChangeCounter(game);
|
||||
}
|
||||
|
||||
public Permanent getPermanent(Game game) {
|
||||
Permanent permanent = game.getPermanent(sourceId);
|
||||
if (permanent != null && permanent.getZoneChangeCounter() == zoneChangeCounter) {
|
||||
if (permanent != null && permanent.getZoneChangeCounter(game) == zoneChangeCounter) {
|
||||
return permanent;
|
||||
}
|
||||
return null;
|
||||
|
|
@ -163,7 +122,7 @@ public class MageObjectReference implements Comparable<MageObjectReference> {
|
|||
|
||||
public Permanent getPermanentOrLKIBattlefield(Game game) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(sourceId);
|
||||
if (permanent != null && permanent.getZoneChangeCounter() == zoneChangeCounter) {
|
||||
if (permanent != null && permanent.getZoneChangeCounter(game) == zoneChangeCounter) {
|
||||
return permanent;
|
||||
}
|
||||
return null;
|
||||
|
|
@ -171,7 +130,7 @@ public class MageObjectReference implements Comparable<MageObjectReference> {
|
|||
|
||||
public Card getCard(Game game) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (card != null && card.getZoneChangeCounter() == zoneChangeCounter) {
|
||||
if (card != null && card.getZoneChangeCounter(game) == zoneChangeCounter) {
|
||||
return card;
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -879,10 +879,10 @@ public abstract class AbilityImpl implements Ability {
|
|||
boolean found = false;
|
||||
// unfortunately we need to handle double faced cards separately and only this way
|
||||
if (object instanceof PermanentCard) {
|
||||
// if (((PermanentCard)object).canTransform()) {
|
||||
// PermanentCard permanent = (PermanentCard)object;
|
||||
// found = permanent.getSecondCardFace().getAbilities().contains(this) || permanent.getCard().getAbilities().contains(this);
|
||||
// }
|
||||
if (((PermanentCard)object).canTransform()) {
|
||||
PermanentCard permanent = (PermanentCard)object;
|
||||
found = permanent.getSecondCardFace().getAbilities().contains(this) || permanent.getCard().getAbilities().contains(this);
|
||||
}
|
||||
} else {
|
||||
// check if it's an ability that is temporary gained to a card
|
||||
Abilities<Ability> otherAbilities = game.getState().getAllOtherAbilities(this.getSourceId());
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public class DiesAndDealtDamageThisTurnTriggeredAbility extends TriggeredAbility
|
|||
if (zEvent.getTarget().getCardType().contains(CardType.CREATURE)) {
|
||||
boolean damageDealt = false;
|
||||
for (MageObjectReference mor : zEvent.getTarget().getDealtDamageByThisTurn()) {
|
||||
if (mor.refersTo(getSourceObject(game))) {
|
||||
if (mor.refersTo(getSourceObject(game), game)) {
|
||||
damageDealt = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class SweepNumber implements DynamicValue {
|
|||
if (zoneChangeCounter == 0) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
if (previousZone) {
|
||||
zoneChangeCounter--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
|
|||
}
|
||||
game.rememberLKI(card.getId(), fromZone, card);
|
||||
|
||||
PermanentCard permanent = new PermanentCard(card, card.getOwnerId());
|
||||
PermanentCard permanent = new PermanentCard(card, card.getOwnerId(), game);
|
||||
game.getBattlefield().addPermanent(permanent);
|
||||
card.setZone(Zone.BATTLEFIELD, game);
|
||||
game.applyEffects();
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class PreventDamageBySourceEffect extends PreventionEffectImpl {
|
|||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (super.applies(event, source, game)) {
|
||||
MageObject mageObject = game.getObject(event.getSourceId());
|
||||
if (mageObject != null && mageObjectReference.refersTo(mageObject)) {
|
||||
if (mageObject != null && mageObjectReference.refersTo(mageObject, game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ public class ReturnToBattlefieldUnderYourControlSourceEffect extends OneShotEffe
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
MageObjectReference mor = new MageObjectReference(source.getSourceObject(game));
|
||||
MageObjectReference mor = new MageObjectReference(source.getSourceObject(game), game);
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null && game.getState().getZone(source.getSourceId()) == onlyFromZone && mor.getZoneChangeCounter() == card.getZoneChangeCounter() + 1) {
|
||||
if (card != null && game.getState().getZone(source.getSourceId()) == onlyFromZone && mor.getZoneChangeCounter() == card.getZoneChangeCounter(game) + 1) {
|
||||
Zone currentZone = game.getState().getZone(card.getId());
|
||||
if (card.putOntoBattlefield(game, currentZone, source.getSourceId(), source.getControllerId())) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class MustBeBlockedByAllTargetEffect extends RequirementEffect {
|
|||
if (attackingCreature != null && attackingCreature.isAttacking()) {
|
||||
if (!source.getAbilityType().equals(AbilityType.STATIC)) {
|
||||
BlockedAttackerWatcher blockedAttackerWatcher = (BlockedAttackerWatcher) game.getState().getWatchers().get("BlockedAttackerWatcher");
|
||||
if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attackingCreature, permanent)) {
|
||||
if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attackingCreature, permanent, game)) {
|
||||
// has already blocked this turn, so no need to do again
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class MustBeBlockedByTargetSourceEffect extends RequirementEffect {
|
|||
Permanent attacker = game.getPermanent(source.getSourceId());
|
||||
if (attacker != null) {
|
||||
BlockedAttackerWatcher blockedAttackerWatcher = (BlockedAttackerWatcher) game.getState().getWatchers().get("BlockedAttackerWatcher");
|
||||
if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attacker, blocker)) {
|
||||
if (blockedAttackerWatcher != null && blockedAttackerWatcher.creatureHasBlockedAttacker(attacker, blocker, game)) {
|
||||
// has already blocked this turn, so no need to do again
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public class BecomesFaceDownCreatureAllEffect extends ContinuousEffectImpl imple
|
|||
super.init(source, game);
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (!perm.isFaceDown(game) && !perm.canTransform()) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
perm.setFaceDown(true, game);
|
||||
// check for Morph
|
||||
Card card = game.getCard(perm.getId());
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public class BoostAllEffect extends ContinuousEffectImpl {
|
|||
if (this.affectedObjectsSet) {
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ public class BoostControlledEffect extends ContinuousEffectImpl {
|
|||
if (this.affectedObjectsSet) {
|
||||
for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public class BoostOpponentsEffect extends ContinuousEffectImpl {
|
|||
Set<UUID> opponents = game.getOpponents(source.getControllerId());
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (opponents.contains(perm.getControllerId())) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,9 +113,9 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl {
|
|||
return;
|
||||
}
|
||||
this.lockedControllers.put(permanent1.getId(), permanent2.getControllerId());
|
||||
this.zoneChangeCounter.put(permanent1.getId(), permanent1.getZoneChangeCounter());
|
||||
this.zoneChangeCounter.put(permanent1.getId(), permanent1.getZoneChangeCounter(game));
|
||||
this.lockedControllers.put(permanent2.getId(), permanent1.getControllerId());
|
||||
this.zoneChangeCounter.put(permanent2.getId(), permanent2.getZoneChangeCounter());
|
||||
this.zoneChangeCounter.put(permanent2.getId(), permanent2.getZoneChangeCounter(game));
|
||||
} else {
|
||||
// discard if there are less than 2 permanents
|
||||
discard();
|
||||
|
|
@ -127,7 +127,7 @@ public class ExchangeControlTargetEffect extends ContinuousEffectImpl {
|
|||
Set<UUID> toDelete = new HashSet<>();
|
||||
for (Map.Entry<UUID, Integer> entry: zoneChangeCounter.entrySet()) {
|
||||
Permanent permanent = game.getPermanent(entry.getKey());
|
||||
if (permanent == null || permanent.getZoneChangeCounter() != entry.getValue()) {
|
||||
if (permanent == null || permanent.getZoneChangeCounter(game) != entry.getValue()) {
|
||||
// controll effect cease if the same permanent is no longer on the battlefield
|
||||
toDelete.add(entry.getKey());
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class GainAbilityAllEffect extends ContinuousEffectImpl {
|
|||
if (this.affectedObjectsSet) {
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public class GainAbilityControlledEffect extends ContinuousEffectImpl {
|
|||
if (this.affectedObjectsSet) {
|
||||
for (Permanent perm : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) {
|
||||
if (!(excludeSource && perm.getId().equals(source.getSourceId()))) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ public class SetPowerToughnessAllEffect extends ContinuousEffectImpl {
|
|||
super.init(source, game);
|
||||
if (affectedObjectsSet) {
|
||||
for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
if (lockedInPT) {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public class SwitchPowerToughnessAllEffect extends ContinuousEffectImpl {
|
|||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
for (Permanent perm :game.getState().getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) {
|
||||
affectedObjectList.add(new MageObjectReference(perm));
|
||||
affectedObjectList.add(new MageObjectReference(perm, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public class DealtDamageToCreatureBySourceDies extends ReplacementEffectImpl {
|
|||
if (zce.isDiesEvent()) {
|
||||
DamagedByWatcher watcher = (DamagedByWatcher) game.getState().getWatchers().get("DamagedByWatcher", source.getSourceId());
|
||||
if (watcher != null) {
|
||||
return watcher.wasDamaged(zce.getTarget());
|
||||
return watcher.wasDamaged(zce.getTarget(), game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ public class ManifestEffect extends OneShotEffect {
|
|||
manaCosts = new ManaCostsImpl("{0}");
|
||||
}
|
||||
}
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game);
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter(game) +1, game);
|
||||
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource);
|
||||
controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, newSource.getSourceId(), false, true);
|
||||
Permanent permanent = game.getPermanent(card.getId());
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ public class ManifestTargetPlayerEffect extends OneShotEffect {
|
|||
manaCosts = new ManaCostsImpl("{0}");
|
||||
}
|
||||
}
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter() +1, game);
|
||||
MageObjectReference objectReference= new MageObjectReference(card.getId(), card.getZoneChangeCounter(game) +1, game);
|
||||
game.addEffect(new BecomesFaceDownCreatureEffect(manaCosts, objectReference, Duration.Custom, FaceDownType.MANIFESTED), newSource);
|
||||
targetPlayer.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, newSource.getSourceId(), false, true);
|
||||
Permanent permanent = game.getPermanent(card.getId());
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
|
|||
@Override
|
||||
public boolean isActivated(Ability ability, Game game) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (card != null && card.getZoneChangeCounter() <= zoneChangeCounter +1) {
|
||||
if (card != null && card.getZoneChangeCounter(game) <= zoneChangeCounter +1) {
|
||||
for (AlternativeCost2 cost: alternativeSourceCosts) {
|
||||
if(cost.isActivated(game)) {
|
||||
return true;
|
||||
|
|
@ -158,7 +158,7 @@ public class DashAbility extends StaticAbility implements AlternativeSourceCosts
|
|||
if (zoneChangeCounter == 0) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Dash source card not found");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ class EchoEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
MageObjectReference mor = new MageObjectReference(source.getSourceId(), game);
|
||||
if (controller != null && mor.refersTo(source.getSourceObject(game))) {
|
||||
if (controller != null && mor.refersTo(source.getSourceObject(game), game)) {
|
||||
if (controller.chooseUse(Outcome.Benefit, "Pay " + cost.getText() /* + " or sacrifice " + permanent.getName() */ + "?", game)) {
|
||||
cost.clearPaid();
|
||||
if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), false)) {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public class EvokeAbility extends StaticAbility implements AlternativeSourceCost
|
|||
@Override
|
||||
public boolean isActivated(Ability ability, Game game) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (card != null && card.getZoneChangeCounter() <= zoneChangeCounter +1) {
|
||||
if (card != null && card.getZoneChangeCounter(game) <= zoneChangeCounter +1) {
|
||||
for (AlternativeCost2 cost: evokeCosts) {
|
||||
if(cost.isActivated(game)) {
|
||||
return true;
|
||||
|
|
@ -151,7 +151,7 @@ public class EvokeAbility extends StaticAbility implements AlternativeSourceCost
|
|||
if (zoneChangeCounter == 0) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Evoke source card not found");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ public class HauntAbility extends TriggeredAbilityImpl {
|
|||
if (zEvent.isDiesEvent()) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
String key = new StringBuilder("Haunting_").append(getSourceId().toString()).append("_").append(card.getZoneChangeCounter()).toString();
|
||||
String key = new StringBuilder("Haunting_").append(getSourceId().toString()).append("_").append(card.getZoneChangeCounter(game)).toString();
|
||||
Object object = game.getState().getValue(key);
|
||||
if (object != null && object instanceof FixedTarget) {
|
||||
FixedTarget target = (FixedTarget) object;
|
||||
|
|
@ -205,7 +205,7 @@ class HauntEffect extends OneShotEffect {
|
|||
if (hauntedCreature != null) {
|
||||
if (card.moveToExile(source.getSourceId(), "Haunting", source.getSourceId(), game)) {
|
||||
// remember the haunted creature
|
||||
String key = new StringBuilder("Haunting_").append(source.getSourceId().toString()).append("_").append(card.getZoneChangeCounter()).toString();
|
||||
String key = new StringBuilder("Haunting_").append(source.getSourceId().toString()).append("_").append(card.getZoneChangeCounter(game)).toString();
|
||||
game.getState().setValue(key, new FixedTarget(targetPointer.getFirst(game, source)));
|
||||
card.addInfo("hauntinfo", new StringBuilder("Haunting ").append(hauntedCreature.getLogName()).toString(), game);
|
||||
hauntedCreature.addInfo("hauntinfo", new StringBuilder("Haunted by ").append(card.getLogName()).toString(), game);
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
|||
public boolean isKicked(Game game) {
|
||||
Card card = game.getCard(sourceId);
|
||||
// kicked status counts only if card not changed zone since it was kicked
|
||||
if (card != null && card.getZoneChangeCounter() <= zoneChangeCounter +1) {
|
||||
if (card != null && card.getZoneChangeCounter(game) <= zoneChangeCounter +1) {
|
||||
for (OptionalAdditionalCost cost: kickerCosts) {
|
||||
if(cost.isActivated()) {
|
||||
return true;
|
||||
|
|
@ -186,7 +186,7 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
|||
if (zoneChangeCounter == 0) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Kicker source card not found");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
|
|||
@Override
|
||||
public boolean isActivated(Ability ability, Game game) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (card != null && card.getZoneChangeCounter() <= zoneChangeCounter +1) {
|
||||
if (card != null && card.getZoneChangeCounter(game) <= zoneChangeCounter +1) {
|
||||
return alternateCosts.isActivated(game);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -261,7 +261,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
|
|||
if (zoneChangeCounter == 0) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Morph source card not found");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class StormEffect extends OneShotEffect {
|
|||
if (spell != null) {
|
||||
CastSpellLastTurnWatcher watcher = (CastSpellLastTurnWatcher) game.getState().getWatchers().get("CastSpellLastTurnWatcher");
|
||||
|
||||
int stormCount = watcher.getSpellOrder(spell) - 1;
|
||||
int stormCount = watcher.getSpellOrder(spell, game) - 1;
|
||||
if (stormCount > 0) {
|
||||
game.informPlayers("Storm: " + spell.getName() + " will be copied " + stormCount + " time" + (stormCount > 1 ?"s":""));
|
||||
for (int i = 0; i < stormCount; i++) {
|
||||
|
|
|
|||
|
|
@ -69,9 +69,6 @@ public interface Card extends MageObject {
|
|||
|
||||
void assignNewId();
|
||||
|
||||
int getZoneChangeCounter();
|
||||
void updateZoneChangeCounter();
|
||||
|
||||
void addInfo(String key, String value, Game game);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
protected SpellAbility spellAbility;
|
||||
protected boolean flipCard;
|
||||
protected String flipCardName;
|
||||
protected int zoneChangeCounter = 1;
|
||||
protected boolean usesVariousArt = false;
|
||||
protected boolean splitCard;
|
||||
protected boolean morphCard;
|
||||
|
|
@ -150,7 +149,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
secondSideCard = card.secondSideCard;
|
||||
nightCard = card.nightCard;
|
||||
}
|
||||
zoneChangeCounter = card.zoneChangeCounter;
|
||||
flipCard = card.flipCard;
|
||||
flipCardName = card.flipCardName;
|
||||
splitCard = card.splitCard;
|
||||
|
|
@ -377,7 +375,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
|
||||
setFaceDown(false, game);
|
||||
updateZoneChangeCounter();
|
||||
updateZoneChangeCounter(game);
|
||||
switch (event.getToZone()) {
|
||||
case GRAVEYARD:
|
||||
game.getPlayer(ownerId).putInGraveyard(this, game, !flag);
|
||||
|
|
@ -403,7 +401,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
break;
|
||||
case BATTLEFIELD:
|
||||
PermanentCard permanent = new PermanentCard(this, event.getPlayerId()); // controller can be replaced (e.g. Gather Specimens)
|
||||
PermanentCard permanent = new PermanentCard(this, event.getPlayerId(), game); // controller can be replaced (e.g. Gather Specimens)
|
||||
game.addPermanent(permanent);
|
||||
game.setZone(objectId, Zone.BATTLEFIELD);
|
||||
game.setScopeRelevant(true);
|
||||
|
|
@ -510,7 +508,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
game.getExile().createZone(exileId, name).add(this);
|
||||
}
|
||||
setFaceDown(false, game);
|
||||
updateZoneChangeCounter();
|
||||
updateZoneChangeCounter(game);
|
||||
game.setZone(objectId, event.getToZone());
|
||||
game.addSimultaneousEvent(event);
|
||||
return true;
|
||||
|
|
@ -574,8 +572,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
logger.warn("Couldn't find card in fromZone, card=" + getName() + ", fromZone=" + fromZone);
|
||||
}
|
||||
}
|
||||
updateZoneChangeCounter();
|
||||
PermanentCard permanent = new PermanentCard(this, event.getPlayerId());
|
||||
updateZoneChangeCounter(game);
|
||||
PermanentCard permanent = new PermanentCard(this, event.getPlayerId(), game);
|
||||
// make sure the controller of all continuous effects of this card are switched to the current controller
|
||||
game.getContinuousEffects().setController(objectId, event.getPlayerId());
|
||||
game.addPermanent(permanent);
|
||||
|
|
@ -662,20 +660,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
return splitCard;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter() {
|
||||
// logger.info(name + " get= " + zoneChangeCounter + " " + ((this instanceof Permanent) ? " Permanent":"Card"));
|
||||
return zoneChangeCounter;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter() {
|
||||
zoneChangeCounter++;
|
||||
// logger.info(name + " set= " + zoneChangeCounter + " " + ((this instanceof Permanent) ? " Permanent":"Card"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -2239,10 +2239,10 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (object instanceof Permanent) {
|
||||
Map<Integer, MageObject> lkiExtendedMap = lkiExtended.get(objectId);
|
||||
if (lkiExtendedMap != null) {
|
||||
lkiExtendedMap.put(((Permanent) object).getZoneChangeCounter(), copy);
|
||||
lkiExtendedMap.put(((Permanent) object).getZoneChangeCounter(this), copy);
|
||||
} else {
|
||||
lkiExtendedMap = new HashMap<>();
|
||||
lkiExtendedMap.put(((Permanent) object).getZoneChangeCounter(), copy);
|
||||
lkiExtendedMap.put(((Permanent) object).getZoneChangeCounter(this), copy);
|
||||
lkiExtended.put(objectId, lkiExtendedMap);
|
||||
}
|
||||
}
|
||||
|
|
@ -2349,7 +2349,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
for (PermanentCard card : battlefield) {
|
||||
card.setZone(Zone.BATTLEFIELD, this);
|
||||
card.setOwnerId(ownerId);
|
||||
PermanentCard permanent = new PermanentCard(card.getCard(), ownerId);
|
||||
PermanentCard permanent = new PermanentCard(card.getCard(), ownerId, this);
|
||||
getBattlefield().addPermanent(permanent);
|
||||
permanent.entersBattlefield(permanent.getId(), this, Zone.OUTSIDE, false);
|
||||
((PermanentImpl)permanent).removeSummoningSickness();
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
private Map<UUID, Zone> zones = new HashMap<>();
|
||||
private List<GameEvent> simultaneousEvents = new ArrayList<>();
|
||||
private Map<UUID, CardState> cardState = new HashMap<>();
|
||||
private Map<UUID, Integer> zoneChangeCounter = new HashMap<>();
|
||||
|
||||
public GameState() {
|
||||
players = new Players();
|
||||
|
|
@ -159,6 +160,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
for (Map.Entry<UUID, CardState> entry: state.cardState.entrySet()) {
|
||||
cardState.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
this.zoneChangeCounter.putAll(state.zoneChangeCounter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -495,6 +497,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
this.simultaneousEvents = state.simultaneousEvents;
|
||||
this.cardState = state.cardState;
|
||||
this.zoneChangeCounter = state.zoneChangeCounter;
|
||||
}
|
||||
|
||||
public void addSimultaneousEvent(GameEvent event, Game game) {
|
||||
|
|
@ -691,8 +694,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
|
||||
/**
|
||||
* Adds the ability to continuous or triggered abilities
|
||||
* @param attachedTo
|
||||
* @param ability
|
||||
* @param card
|
||||
*/
|
||||
public void addOtherAbility(Card attachedTo, Ability ability) {
|
||||
ability.setSourceId(attachedTo.getId());
|
||||
|
|
@ -794,4 +797,25 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.watchers.add(watcher);
|
||||
}
|
||||
|
||||
public int getZoneChangeCounter(UUID objectId) {
|
||||
if (this.zoneChangeCounter.containsKey(objectId)) {
|
||||
return this.zoneChangeCounter.get(objectId);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void updateZoneChangeCounter(UUID objectId) {
|
||||
Integer value = getZoneChangeCounter(objectId);
|
||||
value++;
|
||||
this.zoneChangeCounter.put(objectId, value);
|
||||
// card is changing zone so clear state
|
||||
if (cardState.containsKey(objectId)) {
|
||||
this.cardState.get(objectId).clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void setZoneChangeCounter(UUID objectId, int value) {
|
||||
this.zoneChangeCounter.put(objectId, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,5 +192,20 @@ public class Commander implements CommandObject{
|
|||
public String getImageName() {
|
||||
return card.getImageName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoneChangeCounter(int value, Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,5 +198,20 @@ public class Emblem implements CommandObject {
|
|||
public String getExpansionSetCodeForImage() {
|
||||
return expansionSetCodeForImage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoneChangeCounter(int value, Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,21 +48,17 @@ public class PermanentCard extends PermanentImpl {
|
|||
|
||||
protected int maxLevelCounters;
|
||||
protected Card card;
|
||||
protected int zoneChangeCounter;
|
||||
|
||||
public PermanentCard(Card card, UUID controllerId) {
|
||||
public PermanentCard(Card card, UUID controllerId, Game game) {
|
||||
super(card.getId(), card.getOwnerId(), controllerId, card.getName());
|
||||
this.card = card.copy();
|
||||
init(card);
|
||||
init(card, game);
|
||||
}
|
||||
|
||||
protected PermanentCard(UUID id, Card card, UUID controllerId) {
|
||||
super(card.getId(), card.getOwnerId(), controllerId, card.getName());
|
||||
this.card = card.copy();
|
||||
init(card);
|
||||
}
|
||||
|
||||
private void init(Card card) {
|
||||
private void init(Card card, Game game) {
|
||||
copyFromCard(card);
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
/*if (card.getCardType().contains(CardType.PLANESWALKER)) {
|
||||
this.loyalty = new MageInt(card.getLoyalty().getValue());
|
||||
}*/
|
||||
|
|
@ -75,6 +71,7 @@ public class PermanentCard extends PermanentImpl {
|
|||
super(permanent);
|
||||
this.card = permanent.card.copy();
|
||||
this.maxLevelCounters = permanent.maxLevelCounters;
|
||||
this.zoneChangeCounter = permanent.zoneChangeCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -99,6 +96,7 @@ public class PermanentCard extends PermanentImpl {
|
|||
this.abilities = card.getAbilities().copy();
|
||||
}
|
||||
this.abilities.setControllerId(this.controllerId);
|
||||
this.abilities.setSourceId(objectId);
|
||||
this.cardType.clear();
|
||||
this.cardType.addAll(card.getCardType());
|
||||
this.color = card.getColor().copy();
|
||||
|
|
@ -116,7 +114,6 @@ public class PermanentCard extends PermanentImpl {
|
|||
this.rarity = card.getRarity();
|
||||
this.cardNumber = card.getCardNumber();
|
||||
this.usesVariousArt = card.getUsesVariousArt();
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter();
|
||||
|
||||
canTransform = card.canTransform();
|
||||
if (canTransform) {
|
||||
|
|
@ -140,15 +137,12 @@ public class PermanentCard extends PermanentImpl {
|
|||
Zone fromZone = game.getState().getZone(objectId);
|
||||
Player controller = game.getPlayer(controllerId);
|
||||
if (controller != null && controller.removeFromBattlefield(this, game)) {
|
||||
Card originalCard = game.getCard(this.getId());
|
||||
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone, appliedEffects);
|
||||
if (!game.replaceEvent(event)) {
|
||||
Player owner = game.getPlayer(ownerId);
|
||||
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
|
||||
if (owner != null) {
|
||||
if (originalCard != null) {
|
||||
originalCard.updateZoneChangeCounter();
|
||||
}
|
||||
card.updateZoneChangeCounter(game);
|
||||
switch (event.getToZone()) {
|
||||
case GRAVEYARD:
|
||||
owner.putInGraveyard(card, game, !flag);
|
||||
|
|
@ -196,7 +190,7 @@ public class PermanentCard extends PermanentImpl {
|
|||
if (!game.replaceEvent(event)) {
|
||||
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
|
||||
// update zone change counter of original card
|
||||
game.getCard(this.getId()).updateZoneChangeCounter();
|
||||
card.updateZoneChangeCounter(game);
|
||||
if (exileId == null) {
|
||||
game.getExile().getPermanentExile().add(card);
|
||||
} else {
|
||||
|
|
@ -252,6 +246,20 @@ public class PermanentCard extends PermanentImpl {
|
|||
}
|
||||
return super.getManaCost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter(Game game) {
|
||||
return this.zoneChangeCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game) {
|
||||
this.zoneChangeCounter++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoneChangeCounter(int value, Game game) {
|
||||
this.zoneChangeCounter = value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
if (dealtDamageByThisTurn == null) {
|
||||
dealtDamageByThisTurn = new HashSet<>();
|
||||
}
|
||||
dealtDamageByThisTurn.add(new MageObjectReference(source));
|
||||
dealtDamageByThisTurn.add(new MageObjectReference(source, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,17 +124,6 @@ public class PermanentToken extends PermanentImpl {
|
|||
return new PermanentToken(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAbility(Ability ability, Game game) {
|
||||
if (!abilities.containsKey(ability.getId())) {
|
||||
Ability copyAbility = ability.copy();
|
||||
copyAbility.setControllerId(controllerId);
|
||||
copyAbility.setSourceId(objectId);
|
||||
game.getState().addAbility(copyAbility, this);
|
||||
abilities.add(copyAbility);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustTargets(Ability ability, Game game) {
|
||||
if (getToken().getCopySourceCard() != null) {
|
||||
|
|
|
|||
|
|
@ -873,10 +873,15 @@ public class Spell implements StackObject, Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter() {
|
||||
public void updateZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoneChangeCounter(int value, Game game) {
|
||||
throw new UnsupportedOperationException("Unsupported operation");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ability getStackAbility() {
|
||||
return this.ability;
|
||||
|
|
@ -888,8 +893,8 @@ public class Spell implements StackObject, Card {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter() {
|
||||
return card.getZoneChangeCounter();
|
||||
public int getZoneChangeCounter(Game game) {
|
||||
return card.getZoneChangeCounter(game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -507,5 +507,19 @@ public class StackAbility implements StackObject, Ability {
|
|||
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateZoneChangeCounter(Game game) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setZoneChangeCounter(int value, Game game) {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ public abstract class TargetImpl implements Target {
|
|||
private void rememberZoneChangeCounter(UUID id, Game game) {
|
||||
Card card = game.getCard(id);
|
||||
if (card != null) {
|
||||
zoneChangeCounters.put(id, card.getZoneChangeCounter());
|
||||
zoneChangeCounters.put(id, card.getZoneChangeCounter(game));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,7 +331,7 @@ public abstract class TargetImpl implements Target {
|
|||
for (UUID targetId: targets.keySet()) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null) {
|
||||
if (zoneChangeCounters.containsKey(targetId) && zoneChangeCounters.get(targetId) != card.getZoneChangeCounter()) {
|
||||
if (zoneChangeCounters.containsKey(targetId) && zoneChangeCounters.get(targetId) != card.getZoneChangeCounter(game)) {
|
||||
illegalTargets.add(targetId);
|
||||
continue; // it's not legal so continue to have a look at other targeted objects
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public class FirstTargetPointer implements TargetPointer {
|
|||
for (UUID target : source.getTargets().get(0).getTargets()) {
|
||||
Card card = game.getCard(target);
|
||||
if (card != null) {
|
||||
this.zoneChangeCounter.put(target, card.getZoneChangeCounter());
|
||||
this.zoneChangeCounter.put(target, card.getZoneChangeCounter(game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -47,11 +47,10 @@ public class FirstTargetPointer implements TargetPointer {
|
|||
for (UUID targetId : source.getTargets().get(0).getTargets()) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null && zoneChangeCounter.containsKey(targetId)
|
||||
&& card.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
|
||||
// because if dies trigger has to trigger as permanent has already moved zone, we have to check if target was on the battlefield immed. before
|
||||
&& card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
|
||||
// but no longer if new permanent is already on the battlefield
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(targetId);
|
||||
if (permanent == null || permanent.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
|
||||
if (permanent == null || permanent.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
@ -67,11 +66,11 @@ public class FirstTargetPointer implements TargetPointer {
|
|||
if (zoneChangeCounter.containsKey(targetId)) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null && zoneChangeCounter.containsKey(targetId)
|
||||
&& card.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
|
||||
&& card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
|
||||
// because if dies trigger has to trigger as permanent has already moved zone, we have to check if target was on the battlefield immed. before
|
||||
// but no longer if new permanent is already on the battlefield
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(targetId);
|
||||
if (permanent == null || permanent.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
|
||||
if (permanent == null || permanent.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ public class FixedTarget implements TargetPointer {
|
|||
public void init(Game game, Ability source) {
|
||||
Card card = game.getCard(target);
|
||||
if (card != null) {
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter();
|
||||
this.zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ public class FixedTarget implements TargetPointer {
|
|||
// check target not changed zone
|
||||
if (this.zoneChangeCounter > 0) { // will be zero if not defined in init
|
||||
Card card = game.getCard(target);
|
||||
if (card != null && card.getZoneChangeCounter() != this.zoneChangeCounter) {
|
||||
if (card != null && card.getZoneChangeCounter(game) != this.zoneChangeCounter) {
|
||||
return new ArrayList<>(); // return empty
|
||||
}
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ public class FixedTarget implements TargetPointer {
|
|||
// check target not changed zone
|
||||
if (this.zoneChangeCounter > 0) { // will be zero if not defined in init
|
||||
Card card = game.getCard(target);
|
||||
if (card != null && card.getZoneChangeCounter() != this.zoneChangeCounter) {
|
||||
if (card != null && card.getZoneChangeCounter(game) != this.zoneChangeCounter) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public class SecondTargetPointer implements TargetPointer {
|
|||
for (UUID target : source.getTargets().get(1).getTargets()) {
|
||||
Card card = game.getCard(target);
|
||||
if (card != null) {
|
||||
this.zoneChangeCounter.put(target, card.getZoneChangeCounter());
|
||||
this.zoneChangeCounter.put(target, card.getZoneChangeCounter(game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ public class SecondTargetPointer implements TargetPointer {
|
|||
for (UUID targetId : source.getTargets().get(1).getTargets()) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null && zoneChangeCounter.containsKey(targetId)
|
||||
&& card.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
|
||||
&& card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
|
||||
continue;
|
||||
}
|
||||
target.add(targetId);
|
||||
|
|
@ -62,7 +62,7 @@ public class SecondTargetPointer implements TargetPointer {
|
|||
if (zoneChangeCounter.containsKey(targetId)) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null && zoneChangeCounter.containsKey(targetId)
|
||||
&& card.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
|
||||
&& card.getZoneChangeCounter(game) != zoneChangeCounter.get(targetId)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -485,9 +485,9 @@ public class CardUtil {
|
|||
public static UUID getObjectExileZoneId(Game game, MageObject mageObject, boolean previous) {
|
||||
int zoneChangeCounter = 0;
|
||||
if (mageObject instanceof Permanent) {
|
||||
zoneChangeCounter = ((Permanent) mageObject).getZoneChangeCounter();
|
||||
zoneChangeCounter = ((Permanent) mageObject).getZoneChangeCounter(game);
|
||||
} else if (mageObject instanceof Card) {
|
||||
zoneChangeCounter = ((Card) mageObject).getZoneChangeCounter();
|
||||
zoneChangeCounter = ((Card) mageObject).getZoneChangeCounter(game);
|
||||
}
|
||||
if (zoneChangeCounter > 0 && previous) {
|
||||
zoneChangeCounter--;
|
||||
|
|
@ -526,7 +526,7 @@ public class CardUtil {
|
|||
int zoneChangeCounter= 0;
|
||||
Card card = game.getCard(cardId); // if called for a token, the id is enough
|
||||
if (card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
zoneChangeCounter = card.getZoneChangeCounter(game);
|
||||
}
|
||||
return getObjectZoneString(text,cardId, game, zoneChangeCounter, previous);
|
||||
}
|
||||
|
|
@ -534,9 +534,9 @@ public class CardUtil {
|
|||
public static String getObjectZoneString(String text, MageObject mageObject, Game game) {
|
||||
int zoneChangeCounter = 0;
|
||||
if (mageObject instanceof Permanent) {
|
||||
zoneChangeCounter = ((Permanent) mageObject).getZoneChangeCounter();
|
||||
zoneChangeCounter = ((Permanent) mageObject).getZoneChangeCounter(game);
|
||||
} else if (mageObject instanceof Card) {
|
||||
zoneChangeCounter = ((Card) mageObject).getZoneChangeCounter();
|
||||
zoneChangeCounter = ((Card) mageObject).getZoneChangeCounter(game);
|
||||
}
|
||||
return getObjectZoneString(text, mageObject.getId(), game, zoneChangeCounter, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ public class BlockedAttackerWatcher extends Watcher {
|
|||
blockData.clear();
|
||||
}
|
||||
|
||||
public boolean creatureHasBlockedAttacker(Permanent attacker, Permanent blocker) {
|
||||
Set<MageObjectReference> blockedAttackers = blockData.get(new MageObjectReference(blocker));
|
||||
return blockedAttackers != null && blockedAttackers.contains(new MageObjectReference(attacker));
|
||||
public boolean creatureHasBlockedAttacker(Permanent attacker, Permanent blocker, Game game) {
|
||||
Set<MageObjectReference> blockedAttackers = blockData.get(new MageObjectReference(blocker, game));
|
||||
return blockedAttackers != null && blockedAttackers.contains(new MageObjectReference(attacker, game));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ public class CastSpellLastTurnWatcher extends Watcher {
|
|||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.SPELL_CAST) {
|
||||
spellsCastThisTurnInOrder.add(new MageObjectReference(event.getSourceId(), game));
|
||||
spellsCastThisTurnInOrder.add(new MageObjectReference(event.getTargetId(), game));
|
||||
UUID playerId = event.getPlayerId();
|
||||
if (playerId != null) {
|
||||
Integer amount = amountOfSpellsCastOnCurrentTurn.get(playerId);
|
||||
|
|
@ -115,11 +115,11 @@ public class CastSpellLastTurnWatcher extends Watcher {
|
|||
}
|
||||
}
|
||||
|
||||
public int getSpellOrder(Spell spell) {
|
||||
public int getSpellOrder(Spell spell, Game game) {
|
||||
int index = 0;
|
||||
for (MageObjectReference mor : spellsCastThisTurnInOrder) {
|
||||
index++;
|
||||
if (mor.refersTo(spell)) {
|
||||
if (mor.refersTo(spell, game)) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue