* Rally the Ancestors - Fixed that creatures cards were moved to exile also if already in the graveyard. Problem was that the zoneChangeCounter was not raised as a permanent card left the battlefield. So some more fixes were neccessary for implementations that are based on this fixed zoneChangeCounter of permanents leaving the battlefield. I guess there will be some more bugs caused by this change but I guess this is the correct way to go.

This commit is contained in:
LevelX2 2015-01-31 19:17:22 +01:00
parent dbbbbc0279
commit faa2b0a0bf
18 changed files with 77 additions and 37 deletions

View file

@ -76,7 +76,11 @@ public abstract class DelayedTriggeredAbility extends TriggeredAbilityImpl {
return triggerOnlyOnce;
}
public void init(Game game) {};
public void init(Game game) {
for (Effect effect: this.getEffects()) {
effect.getTargetPointer().init(game, this);
}
};
public boolean isInactive(Game game) {
return false;

View file

@ -61,14 +61,6 @@ public class AtTheBeginOfNextEndStepDelayedTriggeredAbility extends DelayedTrigg
this.targetController = ability.targetController;
}
@Override
public void init(Game game) {
super.init(game);
for (Effect effect: this.getEffects()) {
effect.getTargetPointer().init(game, this);
}
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == EventType.END_TURN_STEP_PRE) {

View file

@ -100,7 +100,8 @@ class ReturnExiledPermanentsEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
ExileZone exile = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
// because source already changed zone we have to get previous related exile zone
ExileZone exile = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source.getSourceId(), true));
if (exile != null) {
LinkedList<UUID> cards = new LinkedList<>(exile);
for (UUID cardId : cards) {

View file

@ -74,10 +74,12 @@ public class ManifestEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Ability newSource = source.copy();
newSource.setWorksFaceDown(true);
List<Card> cards = controller.getLibrary().getTopCards(game, amount);
for (Card card: cards) {
card.setFaceDown(true);
controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId());
controller.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, newSource.getSourceId());
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null) {
permanent.setManifested(true);
@ -90,7 +92,7 @@ public class ManifestEffect extends OneShotEffect {
}
ContinuousEffect effect = new BecomesFaceDownCreatureEffect(manaCosts, true, Duration.Custom, FaceDownType.MANIFESTED);
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
game.addEffect(effect, newSource);
}
}
game.applyEffects(); // to apply before ETB triggered or replace Effects are executed

View file

@ -78,10 +78,12 @@ public class ManifestTargetPlayerEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
if (targetPlayer != null) {
Ability newSource = source.copy();
newSource.setWorksFaceDown(true);
List<Card> cards = targetPlayer.getLibrary().getTopCards(game, amount);
for (Card card: cards) {
card.setFaceDown(true);
targetPlayer.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, source.getSourceId());
targetPlayer.putOntoBattlefieldWithInfo(card, game, Zone.LIBRARY, newSource.getSourceId());
Permanent permanent = game.getPermanent(card.getId());
if (permanent != null) {
permanent.setManifested(true);
@ -94,7 +96,7 @@ public class ManifestTargetPlayerEffect extends OneShotEffect {
}
ContinuousEffect effect = new BecomesFaceDownCreatureEffect(manaCosts, true, Duration.Custom, FaceDownType.MANIFESTED);
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
game.addEffect(effect, newSource);
} }
return true;
}

View file

@ -126,6 +126,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost
ruleText = sb.toString();
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesFaceDownCreatureEffect(morphCosts, FaceDownType.MORPHED));
ability.setWorksFaceDown(true);
ability.setRuleVisible(false);
card.addAbility(ability);

View file

@ -1,5 +1,6 @@
package mage.abilities.keyword;
import java.util.UUID;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.abilities.Ability;
@ -36,9 +37,9 @@ public class UndyingAbility extends DiesTriggeredAbility {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (super.checkTrigger(event, game)) {
Permanent p = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
if (!p.getCounters().containsKey(CounterType.P1P1) || p.getCounters().getCount(CounterType.P1P1) == 0) {
game.getState().setValue(new StringBuilder("undying").append(getSourceId()).toString(), new FixedTarget(p.getId()));
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
if (!permanent.getCounters().containsKey(CounterType.P1P1) || permanent.getCounters().getCount(CounterType.P1P1) == 0) {
game.getState().setValue("undying" + getSourceId(),permanent.getId());
return true;
}
}
@ -109,8 +110,10 @@ class UndyingReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getTargetId().equals(source.getSourceId())) {
Object fixedTarget = game.getState().getValue(new StringBuilder("undying").append(source.getSourceId()).toString());
if (fixedTarget instanceof FixedTarget && ((FixedTarget) fixedTarget).getFirst(game, source).equals(source.getSourceId())) {
// Check if undying condition is true
UUID target = (UUID) game.getState().getValue("undying" + source.getSourceId());
if (target.equals(source.getSourceId())) {
game.getState().setValue("undying" + source.getSourceId(), null);
return true;
}
}

View file

@ -77,6 +77,7 @@ public interface Card extends MageObject {
void assignNewId();
int getZoneChangeCounter();
void updateZoneChangeCounter();
void addInfo(String key, String value);

View file

@ -665,7 +665,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
return zoneChangeCounter;
}
private void updateZoneChangeCounter() {
@Override
public void updateZoneChangeCounter() {
zoneChangeCounter++;
}

View file

@ -135,9 +135,10 @@ 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());
if (isFaceDown()) {
setFaceDown(false);
game.getCard(this.getId()).setFaceDown(false); //TODO: Do this in a better way
originalCard.setFaceDown(false); //TODO: Do this in a better way
}
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, controllerId, fromZone, toZone, appliedEffects);
if (!game.replaceEvent(event)) {
@ -145,6 +146,7 @@ public class PermanentCard extends PermanentImpl {
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
if (owner != null) {
this.setControllerId(ownerId); // neccessary for e.g. abilities in graveyard or hand to not have a controller != owner
originalCard.updateZoneChangeCounter();
switch (event.getToZone()) {
case GRAVEYARD:
owner.putInGraveyard(card, game, !flag);
@ -195,6 +197,8 @@ public class PermanentCard extends PermanentImpl {
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
if (!game.replaceEvent(event)) {
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
// update zone change counter of original card
game.getCard(this.getId()).updateZoneChangeCounter();
if (exileId == null) {
game.getExile().getPermanentExile().add(card);
} else {

View file

@ -7,7 +7,9 @@ import java.util.Map;
import java.util.UUID;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
public class FirstTargetPointer implements TargetPointer {
@ -47,7 +49,12 @@ public class FirstTargetPointer implements TargetPointer {
Card card = game.getCard(targetId);
if (card != null && zoneChangeCounter.containsKey(targetId)
&& card.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
continue;
// 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)) {
continue;
}
}
target.add(targetId);
}
@ -62,7 +69,12 @@ public class FirstTargetPointer implements TargetPointer {
Card card = game.getCard(targetId);
if (card != null && zoneChangeCounter.containsKey(targetId)
&& card.getZoneChangeCounter() != zoneChangeCounter.get(targetId)) {
return null;
// 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)) {
return null;
}
}
}
return targetId;

View file

@ -479,7 +479,11 @@ public class CardUtil {
}
public static UUID getCardExileZoneId(Game game, UUID sourceId) {
String key = getCardZoneString("SourceExileZone", sourceId, game);
return getCardExileZoneId(game, sourceId, false);
}
public static UUID getCardExileZoneId(Game game, UUID sourceId, boolean previous) {
String key = getCardZoneString("SourceExileZone", sourceId, game, previous);
UUID exileId = (UUID) game.getState().getValue(key);
if (exileId == null) {
exileId = UUID.randomUUID();
@ -499,6 +503,11 @@ public class CardUtil {
* @return
*/
public static String getCardZoneString(String text, UUID cardId, Game game) {
return getCardZoneString(text, cardId, game, false);
}
public static String getCardZoneString(String text, UUID cardId, Game game, boolean previous) {
StringBuilder uniqueString = new StringBuilder();
if (text != null) {
uniqueString.append(text);
@ -506,7 +515,7 @@ public class CardUtil {
uniqueString.append(cardId);
Card card = game.getCard(cardId); // if called for a token, the id is enough
if (card != null) {
uniqueString.append(card.getZoneChangeCounter());
uniqueString.append(previous ? card.getZoneChangeCounter() - 1: card.getZoneChangeCounter());
}
return uniqueString.toString();
}