This commit is contained in:
BetaSteward 2010-11-26 05:06:25 +00:00
parent a99ef071c8
commit 3b1696d8f0
14 changed files with 102 additions and 31 deletions

View file

@ -32,6 +32,7 @@ import java.util.UUID;
import mage.Constants.CardType; import mage.Constants.CardType;
import mage.Constants.Duration; import mage.Constants.Duration;
import mage.Constants.Rarity; import mage.Constants.Rarity;
import mage.Constants.TargetController;
import mage.abilities.effects.common.PreventAllDamageToEffect; import mage.abilities.effects.common.PreventAllDamageToEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.filter.common.FilterCreatureOrPlayer; import mage.filter.common.FilterCreatureOrPlayer;
@ -42,11 +43,18 @@ import mage.filter.common.FilterCreatureOrPlayer;
*/ */
public class SafePassage extends CardImpl<SafePassage> { public class SafePassage extends CardImpl<SafePassage> {
private static FilterCreatureOrPlayer filter = new FilterCreatureOrPlayer("you and creatures you control");
static {
filter.getCreatureFilter().setTargetController(TargetController.YOU);
filter.getPlayerFilter().setPlayerTarget(TargetController.YOU);
}
public SafePassage(UUID ownerId) { public SafePassage(UUID ownerId) {
super(ownerId, 28, "Safe Passage", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{W}"); super(ownerId, 28, "Safe Passage", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{2}{W}");
this.expansionSetCode = "M10"; this.expansionSetCode = "M10";
this.color.setWhite(true); this.color.setWhite(true);
this.getSpellAbility().addEffect(new PreventAllDamageToEffect(Duration.EndOfTurn, new FilterCreatureOrPlayer("you and creatures you control", ownerId))); this.getSpellAbility().addEffect(new PreventAllDamageToEffect(Duration.EndOfTurn, filter));
} }
public SafePassage(final SafePassage card) { public SafePassage(final SafePassage card) {

View file

@ -62,7 +62,7 @@ public abstract class AbilityImpl<T extends AbilityImpl<T>> implements Ability {
private final static transient Logger logger = Logging.getLogger(AbilityImpl.class.getName()); private final static transient Logger logger = Logging.getLogger(AbilityImpl.class.getName());
protected final UUID id; protected UUID id;
protected AbilityType abilityType; protected AbilityType abilityType;
protected UUID controllerId; protected UUID controllerId;
protected UUID sourceId; protected UUID sourceId;

View file

@ -90,4 +90,10 @@ public class SpellAbility extends ActivatedAbilityImpl<SpellAbility> {
return new SpellAbility(this); return new SpellAbility(this);
} }
public SpellAbility copySpell() {
SpellAbility spell = new SpellAbility(this);
spell.id = UUID.randomUUID();
return spell;
}
} }

View file

@ -40,7 +40,7 @@ import mage.game.events.GameEvent;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public abstract class PreventionEffectImpl<T extends PreventionEffectImpl<T>> extends ReplacementEffectImpl<T> { public abstract class PreventionEffectImpl<T extends PreventionEffectImpl<T>> extends ReplacementEffectImpl<T> implements PreventionEffect<T> {
public PreventionEffectImpl(Duration duration) { public PreventionEffectImpl(Duration duration) {
super(duration, Outcome.PreventDamage); super(duration, Outcome.PreventDamage);

View file

@ -75,7 +75,7 @@ public class CantTargetSourceEffect extends ReplacementEffectImpl<CantTargetSour
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == EventType.TARGET && event.getTargetId().equals(source.getSourceId())) { if (event.getType() == EventType.TARGET && event.getTargetId().equals(source.getSourceId())) {
StackObject sourceObject = game.getStack().getStackObject(event.getSourceId()); StackObject sourceObject = game.getStack().getStackObject(event.getSourceId());
if (sourceObject != null && filterSource.match(sourceObject)) { if (sourceObject != null && filterSource.match(sourceObject, source.getControllerId(), game)) {
return true; return true;
} }
} }

View file

@ -53,7 +53,7 @@ public class CopyTargetSpellEffect extends OneShotEffect<CopyTargetSpellEffect>
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(source.getFirstTarget()); Spell spell = game.getStack().getSpell(source.getFirstTarget());
if (spell != null) { if (spell != null) {
Spell copy = spell.copy(); Spell copy = spell.copySpell();
copy.setControllerId(source.getControllerId()); copy.setControllerId(source.getControllerId());
game.getStack().push(copy); game.getStack().push(copy);
copy.chooseNewTargets(game); copy.chooseNewTargets(game);

View file

@ -32,6 +32,7 @@ import mage.Constants.Duration;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.PreventionEffectImpl; import mage.abilities.effects.PreventionEffectImpl;
import mage.filter.Filter; import mage.filter.Filter;
import mage.filter.FilterInPlay;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -43,9 +44,9 @@ import mage.players.Player;
*/ */
public class PreventAllDamageToEffect extends PreventionEffectImpl<PreventAllDamageToEffect> { public class PreventAllDamageToEffect extends PreventionEffectImpl<PreventAllDamageToEffect> {
protected Filter filter; protected FilterInPlay filter;
public PreventAllDamageToEffect(Duration duration, Filter filter) { public PreventAllDamageToEffect(Duration duration, FilterInPlay filter) {
super(duration); super(duration);
this.filter = filter; this.filter = filter;
} }
@ -81,12 +82,12 @@ public class PreventAllDamageToEffect extends PreventionEffectImpl<PreventAllDam
if (super.applies(event, source, game)) { if (super.applies(event, source, game)) {
Permanent permanent = game.getPermanent(event.getTargetId()); Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null) { if (permanent != null) {
if (filter.match(permanent)) if (filter.match(permanent, source.getControllerId(), game))
return true; return true;
} }
else { else {
Player player = game.getPlayer(event.getTargetId()); Player player = game.getPlayer(event.getTargetId());
if (player != null && filter.match(player)) if (player != null && filter.match(player, source.getControllerId(), game))
return true; return true;
} }
} }

View file

@ -34,7 +34,7 @@ import java.io.Serializable;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public interface Filter<T> extends Serializable { public interface Filter<E> extends Serializable {
public enum ComparisonType { public enum ComparisonType {
GreaterThan, Equal, LessThan GreaterThan, Equal, LessThan
@ -44,11 +44,11 @@ public interface Filter<T> extends Serializable {
Any, All Any, All
} }
public boolean match(T o); public boolean match(E o);
public String getMessage(); public String getMessage();
public void setMessage(String message); public void setMessage(String message);
public void setNotFilter(boolean notFilter); public void setNotFilter(boolean notFilter);
public Filter<T> copy(); public Filter<E> copy();
} }

View file

@ -31,6 +31,8 @@ package mage.filter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.Constants.TargetController;
import mage.game.Game;
import mage.players.Player; import mage.players.Player;
/** /**
@ -41,6 +43,7 @@ public class FilterPlayer extends FilterImpl<Player, FilterPlayer> implements Fi
protected List<UUID> playerId = new ArrayList<UUID>(); protected List<UUID> playerId = new ArrayList<UUID>();
protected boolean notPlayer; protected boolean notPlayer;
protected TargetController playerTarget = TargetController.ANY;
public FilterPlayer() { public FilterPlayer() {
super("player"); super("player");
@ -52,6 +55,7 @@ public class FilterPlayer extends FilterImpl<Player, FilterPlayer> implements Fi
this.playerId.add(pId); this.playerId.add(pId);
} }
this.notPlayer = filter.notPlayer; this.notPlayer = filter.notPlayer;
this.playerTarget = filter.playerTarget;
} }
@Override @Override
@ -63,6 +67,30 @@ public class FilterPlayer extends FilterImpl<Player, FilterPlayer> implements Fi
return !notFilter; return !notFilter;
} }
public boolean match(Player player, UUID playerId, Game game) {
if (!this.match(player))
return notFilter;
if (playerTarget != TargetController.ANY && playerId != null) {
switch(playerTarget) {
case YOU:
if (!player.getId().equals(playerId))
return notFilter;
break;
case OPPONENT:
if (!game.getOpponents(playerId).contains(player.getId()))
return notFilter;
break;
case NOT_YOU:
if (player.getId().equals(playerId))
return notFilter;
break;
}
}
return !notFilter;
}
public List<UUID> getPlayerId() { public List<UUID> getPlayerId() {
return playerId; return playerId;
} }
@ -71,6 +99,10 @@ public class FilterPlayer extends FilterImpl<Player, FilterPlayer> implements Fi
this.notPlayer = notPlayer; this.notPlayer = notPlayer;
} }
public void setPlayerTarget(TargetController playerTarget) {
this.playerTarget = playerTarget;
}
@Override @Override
public FilterPlayer copy() { public FilterPlayer copy() {
return new FilterPlayer(this); return new FilterPlayer(this);

View file

@ -31,6 +31,7 @@ package mage.filter.common;
import java.util.UUID; import java.util.UUID;
import mage.filter.Filter; import mage.filter.Filter;
import mage.filter.FilterImpl; import mage.filter.FilterImpl;
import mage.filter.FilterInPlay;
import mage.filter.FilterPlayer; import mage.filter.FilterPlayer;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -40,7 +41,7 @@ import mage.players.Player;
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
public class FilterCreatureOrPlayer extends FilterImpl<Object, FilterCreatureOrPlayer> implements Filter<Object> { public class FilterCreatureOrPlayer extends FilterImpl<Object, FilterCreatureOrPlayer> implements FilterInPlay<Object> {
protected FilterCreaturePermanent creatureFilter; protected FilterCreaturePermanent creatureFilter;
protected FilterPlayer playerFilter; protected FilterPlayer playerFilter;
@ -80,9 +81,10 @@ public class FilterCreatureOrPlayer extends FilterImpl<Object, FilterCreatureOrP
return notFilter; return notFilter;
} }
@Override
public boolean match(Object o, UUID playerId, Game game) { public boolean match(Object o, UUID playerId, Game game) {
if (o instanceof Player) { if (o instanceof Player) {
return playerFilter.match((Player)o); return playerFilter.match((Player)o, playerId, game);
} }
else if (o instanceof Permanent) { else if (o instanceof Permanent) {
return creatureFilter.match((Permanent)o, playerId, game); return creatureFilter.match((Permanent)o, playerId, game);
@ -90,6 +92,13 @@ public class FilterCreatureOrPlayer extends FilterImpl<Object, FilterCreatureOrP
return notFilter; return notFilter;
} }
public FilterCreaturePermanent getCreatureFilter() {
return this.creatureFilter;
}
public FilterPlayer getPlayerFilter() {
return this.playerFilter;
}
@Override @Override
public FilterCreatureOrPlayer copy() { public FilterCreatureOrPlayer copy() {

View file

@ -48,6 +48,7 @@ import mage.game.events.GameEvent.EventType;
import mage.game.events.ZoneChangeEvent; import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Battlefield; import mage.game.permanent.Battlefield;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.stack.StackObject; import mage.game.stack.StackObject;
import mage.game.turn.Turn; import mage.game.turn.Turn;
import mage.game.turn.TurnMods; import mage.game.turn.TurnMods;
@ -307,11 +308,17 @@ public class GameState implements Serializable, Copyable<GameState> {
public void handleEvent(GameEvent event, Game game) { public void handleEvent(GameEvent event, Game game) {
watchers.watch(event, game); watchers.watch(event, game);
if (!replaceEvent(event, game)) { if (!replaceEvent(event, game)) {
//TODO: this is awkward - improve
if (event.getType() == EventType.ZONE_CHANGE) { if (event.getType() == EventType.ZONE_CHANGE) {
ZoneChangeEvent zEvent = (ZoneChangeEvent)event; ZoneChangeEvent zEvent = (ZoneChangeEvent)event;
if (zEvent.getFromZone() == Zone.BATTLEFIELD) { if (zEvent.getFromZone() == Zone.BATTLEFIELD) {
zEvent.getTarget().checkTriggers(zEvent.getFromZone(), event, game); if (zEvent.getTarget() instanceof PermanentCard) {
zEvent.getTarget().checkTriggers(zEvent.getToZone(), event, game); ((PermanentCard)zEvent.getTarget()).checkPermanentOnlyTriggers(zEvent, game);
}
else {
zEvent.getTarget().checkTriggers(zEvent.getFromZone(), event, game);
zEvent.getTarget().checkTriggers(zEvent.getToZone(), event, game);
}
} }
} }
for (Player player: players.values()) { for (Player player: players.values()) {

View file

@ -35,10 +35,12 @@ import mage.Constants.CardType;
import mage.Constants.Zone; import mage.Constants.Zone;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.TriggeredAbility;
import mage.abilities.keyword.LevelAbility; import mage.abilities.keyword.LevelAbility;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.LevelerCard; import mage.cards.LevelerCard;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent; import mage.game.events.ZoneChangeEvent;
import mage.players.Player; import mage.players.Player;
@ -112,6 +114,21 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
this.cardNumber = card.getCardNumber(); this.cardNumber = card.getCardNumber();
} }
public void checkPermanentOnlyTriggers(ZoneChangeEvent event, Game game) {
// we only want to trigger abilities that are not on the underlying card ie. have been added by another effect
// card abilities will get triggered later when the card hits the new zone
Card card = game.getCard(objectId).copy();
for (TriggeredAbility ability: abilities.getTriggeredAbilities(event.getFromZone())) {
if (!card.getAbilities().containsKey(ability.getId()))
ability.checkTrigger(event, game);
}
for (TriggeredAbility ability: abilities.getTriggeredAbilities(event.getToZone())) {
if (!card.getAbilities().containsKey(ability.getId()))
ability.checkTrigger(event, game);
}
}
@Override @Override
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) { public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) {
Zone fromZone = game.getZone(objectId); Zone fromZone = game.getZone(objectId);

View file

@ -496,19 +496,6 @@ public abstract class PermanentImpl<T extends PermanentImpl<T>> extends CardImpl
return (!hasProtectionFrom(source)); return (!hasProtectionFrom(source));
} }
// protected void addEffects(Game game) {
// for (Ability ability: abilities.getStaticAbilities(Zone.BATTLEFIELD)) {
// if (ability instanceof EntersBattlefieldStaticAbility) {
// for (Effect effect: ability.getEffects()) {
// if (effect instanceof OneShotEffect) {
// //20100423 - 603.6e
// effect.apply(game, ability);
// }
// }
// }
// }
// }
@Override @Override
public boolean destroy(UUID sourceId, Game game, boolean noRegen) { public boolean destroy(UUID sourceId, Game game, boolean noRegen) {
//20091005 - 701.6 //20091005 - 701.6

View file

@ -283,10 +283,14 @@ public class Spell<T extends Spell<T>> implements StackObject, Card {
public void setExpansionSetCode(String expansionSetCode) {} public void setExpansionSetCode(String expansionSetCode) {}
@Override @Override
public Spell<T> copy() { public Spell copy() {
return new Spell<T>(this); return new Spell(this);
} }
public Spell copySpell() {
return new Spell(this.card.copy(), this.ability.copySpell(), this.controllerId);
}
@Override @Override
public void adjustCosts(Ability ability, Game game) {} public void adjustCosts(Ability ability, Game game) {}