Fixed handling and initialization of Fixedtarget object. Fixing a problem of ReturnToBattlefieldUnderYourControlTargetEffect that caused objects to return taht already left the zone they should be moved from.

This commit is contained in:
LevelX2 2015-06-29 18:34:53 +02:00
parent 148fd0e6ae
commit f45c5cedeb
16 changed files with 398 additions and 209 deletions

View file

@ -1,16 +1,16 @@
/*
* 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
@ -20,18 +20,16 @@
* 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 mage.abilities.effects.common;
import mage.MageObject;
import mage.constants.Outcome;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
@ -69,8 +67,7 @@ public class AttachEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
return permanent.addAttachment(source.getSourceId(), game);
}
else {
} else {
Player player = game.getPlayer(getTargetPointer().getFirst(game, source));
if (player != null) {
return player.addAttachment(source.getSourceId(), game);

View file

@ -1,16 +1,16 @@
/*
* 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
@ -20,26 +20,22 @@
* 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 mage.abilities.effects.common;
import java.util.UUID;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
@ -49,14 +45,15 @@ import mage.util.CardUtil;
public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffect {
private boolean fromExileZone;
public ReturnToBattlefieldUnderYourControlTargetEffect() {
this(false);
}
/**
*
* @param fromExileZone - the card will only be returned if it's still in the source object specific exile zone
*
* @param fromExileZone - the card will only be returned if it's still in
* the source object specific exile zone
*/
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean fromExileZone) {
super(Outcome.Benefit);
@ -77,29 +74,18 @@ public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffe
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = null;
if (controller != null) {
Card card = null;
if (fromExileZone) {
UUID exilZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
if (exilZoneId != null) {
ExileZone exileZone = game.getExile().getExileZone(exilZoneId);
if (exileZone != null && getTargetPointer().getFirst(game, source) != null) {
card = exileZone.get(getTargetPointer().getFirst(game, source), game);
}
}
}
} else {
UUID cardId = targetPointer.getFirst(game, source);
if(targetPointer instanceof FixedTarget) {
UUID fixedTargetCardId = ((FixedTarget) targetPointer).getTarget();
//Moved zones from battlefield to graveyard
if(fixedTargetCardId != null && cardId == null) {
Permanent permanent = game.getPermanentOrLKIBattlefield(fixedTargetCardId);
if(permanent != null) {
cardId = fixedTargetCardId;
}
}
}
card = game.getCard(cardId);
card = game.getCard(getTargetPointer().getFirst(game, source));
}
if (card != null) {
Zone currentZone = game.getState().getZone(card.getId());

View file

@ -1401,6 +1401,9 @@ public abstract class GameImpl implements Game, Serializable {
} else {
TriggeredAbility newAbility = ability.copy();
newAbility.newId();
for (Effect effect : newAbility.getEffects()) {
effect.getTargetPointer().init(this, newAbility);
}
state.addTriggeredAbility(newAbility);
}
}
@ -1409,7 +1412,9 @@ public abstract class GameImpl implements Game, Serializable {
public UUID addDelayedTriggeredAbility(DelayedTriggeredAbility delayedAbility) {
DelayedTriggeredAbility newAbility = delayedAbility.copy();
newAbility.newId();
newAbility.init(this);
// ability.init is called as the ability triggeres not now.
// If a FixedTarget pointer is already set from the effect setting up this delayed ability
// it has to be already initialized so it won't be overwitten as the ability triggers
state.addDelayedTriggeredAbility(newAbility);
return newAbility.getId();
}

View file

@ -1,31 +1,52 @@
package mage.target.targetpointer;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.game.Game;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.game.Game;
public class FixedTarget implements TargetPointer {
private final UUID target;
private final UUID targetId;
private int zoneChangeCounter;
private boolean initialized;
public FixedTarget(UUID target) {
this.target = target;
this.targetId = target;
this.initialized = false;
}
/**
* Use this if you already want to fix the target object to the known zone
* now (otherwise the zone will be set if the ability triggers or not at
* all) If not initialized, the object of the current zone then will be
* used.
*
* @param targetId
* @param zoneChangeCounter
*/
public FixedTarget(UUID targetId, int zoneChangeCounter) {
this.targetId = targetId;
this.initialized = true;
this.zoneChangeCounter = zoneChangeCounter;
}
public FixedTarget(final FixedTarget fixedTarget) {
this.target = fixedTarget.target;
this.targetId = fixedTarget.targetId;
this.zoneChangeCounter = fixedTarget.zoneChangeCounter;
this.initialized = fixedTarget.initialized;
}
@Override
public void init(Game game, Ability source) {
Card card = game.getCard(target);
if (card != null) {
this.zoneChangeCounter = card.getZoneChangeCounter(game);
if (!initialized) {
initialized = true;
Card card = game.getCard(targetId);
if (card != null) {
this.zoneChangeCounter = card.getZoneChangeCounter(game);
}
}
}
@ -33,14 +54,14 @@ public class FixedTarget implements TargetPointer {
public List<UUID> getTargets(Game game, Ability source) {
// check target not changed zone
if (this.zoneChangeCounter > 0) { // will be zero if not defined in init
Card card = game.getCard(target);
Card card = game.getCard(targetId);
if (card != null && card.getZoneChangeCounter(game) != this.zoneChangeCounter) {
return new ArrayList<>(); // return empty
}
}
ArrayList<UUID> list = new ArrayList<>(1);
list.add(target);
list.add(targetId);
return list;
}
@ -48,26 +69,26 @@ public class FixedTarget implements TargetPointer {
public UUID getFirst(Game game, Ability source) {
// check target not changed zone
if (this.zoneChangeCounter > 0) { // will be zero if not defined in init
Card card = game.getCard(target);
Card card = game.getCard(targetId);
if (card != null && card.getZoneChangeCounter(game) != this.zoneChangeCounter) {
return null;
}
}
return target;
return targetId;
}
@Override
public TargetPointer copy() {
return new FixedTarget(this);
}
public UUID getTarget() {
return target;
return targetId;
}
public int getZoneChangeCounter() {
return zoneChangeCounter;
}
}