* Some changes to zone object movement and source object handling. Origin source object of ability is now hold in ability to be able to check e.g. zone change counter.

This commit is contained in:
LevelX2 2015-02-11 17:51:41 +01:00
parent 4fe5560222
commit b73f34a52e
32 changed files with 396 additions and 82 deletions

View file

@ -476,5 +476,22 @@ public interface Ability extends Controllable, Serializable {
void setCostModificationActive(boolean active);
boolean activateAlternateOrAdditionalCosts(MageObject sourceObject, boolean noMana, Player controller, Game game);
/**
* Sets the object that actually existed while a ability triggerd or
* an ability was activated.
*
* @param mageObject
*/
void setSourceObject(MageObject mageObject);
/**
* Returns the object that actually existed while a ability triggerd or
* an ability was activated.
* If not set yet, the current object will be retrieved from the game.
*
* @param game
* @return
*/
MageObject getSourceObject(Game game);
}

View file

@ -106,6 +106,7 @@ public abstract class AbilityImpl implements Ability {
protected boolean costModificationActive = true;
protected boolean activated = false;
protected boolean worksFaceDown = false;
protected MageObject sourceObject;
public AbilityImpl(AbilityType abilityType, Zone zone) {
this.id = UUID.randomUUID();
@ -142,6 +143,7 @@ public abstract class AbilityImpl implements Ability {
this.costModificationActive = ability.costModificationActive;
this.worksFaceDown = ability.worksFaceDown;
this.abilityWord = ability.abilityWord;
this.sourceObject = ability.sourceObject;
}
@Override
@ -230,7 +232,7 @@ public abstract class AbilityImpl implements Ability {
// TODO: Because all (non targeted) choices have to be done during resolution
// this has to be removed, if all using effects are changed
MageObject sourceObject = game.getObject(sourceId);
sourceObject = game.getObject(sourceId);
if (sourceObject != null) {
sourceObject.adjustChoices(this, game);
}
@ -1024,6 +1026,19 @@ public abstract class AbilityImpl implements Ability {
this.worksFaceDown = worksFaceDown;
}
@Override
public MageObject getSourceObject(Game game) {
if (sourceObject != null) {
return sourceObject;
} else {
return game.getObject(sourceId);
}
}
@Override
public void setSourceObject(MageObject sourceObject) {
this.sourceObject = sourceObject;
}
}

View file

@ -44,5 +44,5 @@ public interface TriggeredAbility extends Ability {
boolean checkTrigger(GameEvent event, Game game);
boolean checkInterveningIfClause(Game game);
TriggeredAbility copy();
void setSourceObject(MageObject mageObject);
}

View file

@ -43,7 +43,6 @@ import mage.players.Player;
public abstract class TriggeredAbilityImpl extends AbilityImpl implements TriggeredAbility {
protected boolean optional;
protected MageObject sourceObject;
public TriggeredAbilityImpl(Zone zone, Effect effect) {
this(zone, effect, false);
@ -152,12 +151,4 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
return sb.toString();
}
public MageObject getSourceObject() {
return sourceObject;
}
@Override
public void setSourceObject(MageObject sourceObject) {
this.sourceObject = sourceObject;
}
}

View file

@ -30,6 +30,8 @@ package mage.abilities.common;
import mage.constants.Zone;
import mage.abilities.effects.Effect;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
*

View file

@ -49,12 +49,16 @@ public class ZoneChangeTriggeredAbility extends TriggeredAbilityImpl {
protected String rule;
public ZoneChangeTriggeredAbility(Zone fromZone, Zone toZone, Effect effect, String rule, boolean optional) {
super(fromZone, effect, optional);
this(fromZone, fromZone, toZone, effect, rule, optional);
}
public ZoneChangeTriggeredAbility(Zone worksInZone, Zone fromZone, Zone toZone, Effect effect, String rule, boolean optional) {
super(worksInZone, effect, optional);
this.fromZone = fromZone;
this.toZone = toZone;
this.rule = rule;
}
public ZoneChangeTriggeredAbility(Zone toZone, Effect effect, String rule, boolean optional) {
super(toZone, effect, optional);
this.fromZone = null;
@ -62,7 +66,7 @@ public class ZoneChangeTriggeredAbility extends TriggeredAbilityImpl {
this.rule = rule;
}
public ZoneChangeTriggeredAbility(ZoneChangeTriggeredAbility ability) {
public ZoneChangeTriggeredAbility(final ZoneChangeTriggeredAbility ability) {
super(ability);
this.fromZone = ability.fromZone;
this.toZone = ability.toZone;

View file

@ -27,6 +27,7 @@
*/
package mage.abilities.effects.common;
import mage.MageObject;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.constants.Zone;
@ -62,8 +63,9 @@ public class CastSourceTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType().equals(GameEvent.EventType.SPELL_CAST) && event.getSourceId().equals(this.getSourceId())) {
if (getSourceObject() != null && getSourceObject() instanceof Spell) {
Spell spell = (Spell)getSourceObject();
MageObject sourceObject = getSourceObject(game);
if (sourceObject != null && (sourceObject instanceof Spell)) {
Spell spell = (Spell)sourceObject;
if (spell.getSpellAbility() != null) {
for (Effect effect : getEffects()) {
effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility());

View file

@ -29,15 +29,19 @@
package mage.abilities.effects.common;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.constants.AbilityType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
@ -45,12 +49,6 @@ import mage.players.Player;
*/
public class ExileTargetForSourceEffect extends OneShotEffect {
private String exileZone = null;
public ExileTargetForSourceEffect(String exileZone) {
this();
this.exileZone = exileZone;
}
public ExileTargetForSourceEffect() {
super(Outcome.Exile);
@ -58,7 +56,6 @@ public class ExileTargetForSourceEffect extends OneShotEffect {
public ExileTargetForSourceEffect(final ExileTargetForSourceEffect effect) {
super(effect);
this.exileZone = effect.exileZone;
}
@Override
@ -69,15 +66,16 @@ public class ExileTargetForSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Permanent permanent = game.getPermanent(targetPointer.getFirst(game, source));
UUID exileId = source.getSourceId();
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
UUID exileId = CardUtil.getObjectExileZoneId(game, sourceObject);
if (permanent != null) {
return controller.moveCardToExileWithInfo(permanent, exileId, exileZone, source.getSourceId(), game, Zone.BATTLEFIELD);
return controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getLogName(), source.getSourceId(), game, Zone.BATTLEFIELD);
} else {
Card card = game.getCard(targetPointer.getFirst(game, source));
Card card = game.getCard(getTargetPointer().getFirst(game, source));
if (card != null) {
return controller.moveCardToExileWithInfo(card, exileId, exileZone, source.getSourceId(), game, game.getState().getZone(card.getId()));
return controller.moveCardToExileWithInfo(card, exileId, sourceObject.getLogName(), source.getSourceId(), game, game.getState().getZone(card.getId()));
}
}
}

View file

@ -30,9 +30,12 @@ package mage.abilities.effects.common;
import java.util.LinkedList;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.constants.AbilityType;
import mage.constants.Outcome;
import mage.constants.Zone;
import static mage.constants.Zone.BATTLEFIELD;
@ -41,6 +44,7 @@ import static mage.constants.Zone.HAND;
import mage.game.ExileZone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
@ -75,9 +79,10 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
UUID exileId = source.getSourceId();
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
UUID exileId = CardUtil.getObjectExileZoneId(game, sourceObject);
ExileZone exile = game.getExile().getExileZone(exileId);
if (exile != null) { // null is valid if source left battlefield before enters the battlefield effect resolved
LinkedList<UUID> cards = new LinkedList<>(exile);
@ -86,7 +91,7 @@ public class ReturnFromExileForSourceEffect extends OneShotEffect {
if (card == null) {
return false;
}
game.informPlayers(controller.getName() + " moves " + card.getLogName() + " to " + zone.toString().toLowerCase());
game.informPlayers(controller.getName() + " moves " + card.getLogName() + " from exile to " + zone.toString().toLowerCase());
card.moveToZone(zone, source.getSourceId(), game, tapped);
}
exile.clear();

View file

@ -28,6 +28,8 @@
package mage.abilities.effects.common;
import java.util.UUID;
import mage.MageObject;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.abilities.Ability;
@ -35,6 +37,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
/**
*
@ -42,13 +45,25 @@ import mage.players.Player;
*/
public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffect {
private boolean fromExileZone;
public ReturnToBattlefieldUnderYourControlTargetEffect() {
this(false);
}
/**
*
* @param fromExileZone - the card will only be retunred if it's still in the sour obect specific exile zone
*/
public ReturnToBattlefieldUnderYourControlTargetEffect(boolean fromExileZone) {
super(Outcome.Benefit);
staticText = "return that card to the battlefield under your control";
this.fromExileZone = fromExileZone;
}
public ReturnToBattlefieldUnderYourControlTargetEffect(final ReturnToBattlefieldUnderYourControlTargetEffect effect) {
super(effect);
this.fromExileZone = effect.fromExileZone;
}
@Override
@ -59,17 +74,23 @@ public class ReturnToBattlefieldUnderYourControlTargetEffect extends OneShotEffe
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Card card = game.getCard(targetPointer.getFirst(game, source));
MageObject sourceObject = source.getSourceObject(game);
if (controller != null && sourceObject != null) {
Card card = null;
if (fromExileZone) {
UUID exilZoneId = CardUtil.getObjectExileZoneId(game, sourceObject);
if (exilZoneId != null) {
card = game.getExile().getExileZone(exilZoneId).get(getTargetPointer().getFirst(game, source), game);
}
} else {
card = game.getCard(targetPointer.getFirst(game, source));
}
if (card != null) {
Zone currentZone = game.getState().getZone(card.getId());
if (controller.putOntoBattlefieldWithInfo(card, game, currentZone, source.getSourceId())) {
return true;
}
controller.putOntoBattlefieldWithInfo(card, game, currentZone, source.getSourceId());
}
return true;
}
return false;
}
}

View file

@ -49,6 +49,7 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import mage.util.CardUtil;
/*
* @author LevelX2
@ -151,14 +152,16 @@ class ChampionExileCost extends CostImpl {
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
MageObject sourceObject = ability.getSourceObject(game);
if (controller != null && sourceObject != null) {
if (targets.choose(Outcome.Exile, controllerId, sourceId, game)) {
UUID exileId = CardUtil.getObjectExileZoneId(game, sourceObject);
for (UUID targetId: targets.get(0).getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent == null) {
return false;
}
paid |= controller.moveCardToExileWithInfo(permanent, sourceId, exileZone, sourceId, game, Zone.BATTLEFIELD);
paid |= controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getLogName() + " championed permanents", sourceId, game, Zone.BATTLEFIELD);
}
}
}

View file

@ -476,5 +476,15 @@ public class StackAbility implements StackObject, Ability {
this.ability.setWorksFaceDown(worksFaceDown);
}
@Override
public MageObject getSourceObject(Game game) {
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public void setSourceObject(MageObject sourceObject) {
throw new UnsupportedOperationException("Not supported."); //To change body of generated methods, choose Tools | Templates.
}
}

View file

@ -69,6 +69,8 @@ public class CardUtil {
private static final String regexGreen = ".*\\x7b.{0,2}G.{0,2}\\x7d.*";
private static final String regexWhite = ".*\\x7b.{0,2}W.{0,2}\\x7d.*";
private static final String SOURCE_EXILE_ZONE_TEXT = "SourceExileZone";
static String numberStrings[] = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "ninteen", "twenty"};
@ -483,13 +485,28 @@ public class CardUtil {
}
public static UUID getCardExileZoneId(Game game, UUID sourceId, boolean previous) {
String key = getCardZoneString("SourceExileZone", sourceId, game, previous);
return getExileZoneId(getCardZoneString(SOURCE_EXILE_ZONE_TEXT, sourceId, game, previous), game);
}
public static UUID getObjectExileZoneId(Game game, MageObject mageObject) {
int zoneChangeCounter = 0;
if (mageObject instanceof Card) {
zoneChangeCounter = ((Card) mageObject).getZoneChangeCounter();
}
return getExileZoneId(getObjectZoneString(SOURCE_EXILE_ZONE_TEXT,mageObject.getId(), game, zoneChangeCounter, false), game);
}
public static UUID getExileZoneId(Game game, UUID objectId, int zoneChangeCounter) {
return getExileZoneId(getObjectZoneString(SOURCE_EXILE_ZONE_TEXT,objectId, game, zoneChangeCounter, false), game);
}
public static UUID getExileZoneId(String key, Game game) {
UUID exileId = (UUID) game.getState().getValue(key);
if (exileId == null) {
exileId = UUID.randomUUID();
game.getState().setValue(key, exileId);
}
return exileId;
return exileId;
}
/**
@ -506,18 +523,23 @@ public class CardUtil {
return getCardZoneString(text, cardId, game, false);
}
public static String getCardZoneString(String text, UUID cardId, Game game, boolean previous) {
public static String getCardZoneString(String text, UUID cardId, Game game, boolean previous) {
int zoneChangeCounter= 0;
Card card = game.getCard(cardId); // if called for a token, the id is enough
if (card != null) {
zoneChangeCounter = card.getZoneChangeCounter();
}
return getObjectZoneString(text,cardId, game, zoneChangeCounter, previous);
}
public static String getObjectZoneString(String text, UUID objectId, Game game, int zoneChangeCounter, boolean previous) {
StringBuilder uniqueString = new StringBuilder();
if (text != null) {
uniqueString.append(text);
}
uniqueString.append(cardId);
Card card = game.getCard(cardId); // if called for a token, the id is enough
if (card != null) {
uniqueString.append(previous ? card.getZoneChangeCounter() - 1: card.getZoneChangeCounter());
}
return uniqueString.toString();
uniqueString.append(objectId);
uniqueString.append(previous ? zoneChangeCounter - 1: zoneChangeCounter);
return uniqueString.toString();
}
/**