Fixed a problem with casting split cards from non hand zone. Added some generic cast from non hand zone effects and started replacing card specific effects by the generic ones (fixes #5356 and fixes #4493).

This commit is contained in:
LevelX2 2018-10-03 13:44:01 +02:00
parent c097ec053f
commit c41c6e1fe9
25 changed files with 304 additions and 476 deletions

View file

@ -13,6 +13,7 @@ import mage.abilities.keyword.SpliceOntoArcaneAbility;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.SplitCardHalf;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicate;
@ -488,15 +489,23 @@ public class ContinuousEffects implements Serializable {
*/
public MageObjectReference asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game);
for (AsThoughEffect effect : asThoughEffectsList) {
Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) {
if (affectedAbility == null) {
if (effect.applies(objectId, ability, controllerId, game)) {
if (!asThoughEffectsList.isEmpty()) {
UUID idToCheck;
if (affectedAbility != null && affectedAbility.getSourceObject(game) instanceof SplitCardHalf) {
idToCheck = ((SplitCardHalf) affectedAbility.getSourceObject(game)).getParentCard().getId();
} else {
idToCheck = objectId;
}
for (AsThoughEffect effect : asThoughEffectsList) {
Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) {
if (affectedAbility == null) {
if (effect.applies(idToCheck, ability, controllerId, game)) {
return new MageObjectReference(ability.getSourceObject(game), game);
}
} else if (effect.applies(idToCheck, affectedAbility, ability, game, controllerId)) {
return new MageObjectReference(ability.getSourceObject(game), game);
}
} else if (effect.applies(objectId, affectedAbility, ability, game, controllerId)) {
return new MageObjectReference(ability.getSourceObject(game), game);
}
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
@ -39,7 +38,9 @@ public class AttachEffect extends OneShotEffect {
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
int zcc = game.getState().getZoneChangeCounter(sourcePermanent.getId());
if (zcc == source.getSourceObjectZoneChangeCounter() || zcc == source.getSourceObjectZoneChangeCounter() + 1) {
if (zcc == source.getSourceObjectZoneChangeCounter()
|| zcc == source.getSourceObjectZoneChangeCounter() + 1
|| zcc == source.getSourceObjectZoneChangeCounter() + 2) {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (permanent != null) {
return permanent.addAttachment(source.getSourceId(), game);

View file

@ -0,0 +1,74 @@
package mage.abilities.effects.common.asthought;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.cards.Card;
import mage.constants.AsThoughEffectType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
/**
*
* @author LevelX2
*/
public class PlayFromNotOwnHandZoneAllEffect extends AsThoughEffectImpl {
private final FilterCard filter;
private final Zone fromZone;
private final boolean onlyOwnedCards;
private final TargetController allowedCaster;
public PlayFromNotOwnHandZoneAllEffect(FilterCard filter, Zone fromZone, boolean onlyOwnedCards, TargetController allowedCaster, Duration duration) {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, duration, Outcome.Benefit);
this.filter = filter;
this.fromZone = fromZone;
this.onlyOwnedCards = onlyOwnedCards;
this.allowedCaster = allowedCaster;
}
public PlayFromNotOwnHandZoneAllEffect(final PlayFromNotOwnHandZoneAllEffect effect) {
super(effect);
this.filter = effect.filter;
this.fromZone = effect.fromZone;
this.onlyOwnedCards = effect.onlyOwnedCards;
this.allowedCaster = effect.allowedCaster;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public PlayFromNotOwnHandZoneAllEffect copy() {
return new PlayFromNotOwnHandZoneAllEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
Card card = game.getCard(objectId);
if (card != null) {
switch (allowedCaster) {
case YOU:
if (affectedControllerId != source.getControllerId()) {
return false;
}
break;
case OPPONENT:
if (!game.getOpponents(source.getControllerId()).contains(affectedControllerId)) {
return false;
}
break;
}
return !onlyOwnedCards || card.getOwnerId().equals(source.getControllerId())
&& filter.match(card, game)
&& game.getState().getZone(card.getId()).match(fromZone);
}
return false;
}
}

View file

@ -0,0 +1,82 @@
package mage.abilities.effects.common.asthought;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
/**
*
* @author LevelX2
*/
public class PlayFromNotOwnHandZoneTargetEffect extends AsThoughEffectImpl {
private final Zone fromZone;
private final TargetController allowedCaster;
public PlayFromNotOwnHandZoneTargetEffect() {
this(Duration.EndOfTurn);
}
public PlayFromNotOwnHandZoneTargetEffect(Duration duration) {
this(Zone.ALL, TargetController.YOU, duration);
}
public PlayFromNotOwnHandZoneTargetEffect(Zone fromZone, Duration duration) {
this(fromZone, TargetController.YOU, duration);
}
public PlayFromNotOwnHandZoneTargetEffect(Zone fromZone, TargetController allowedCaster, Duration duration) {
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, duration, Outcome.Benefit);
this.fromZone = fromZone;
this.allowedCaster = allowedCaster;
}
public PlayFromNotOwnHandZoneTargetEffect(final PlayFromNotOwnHandZoneTargetEffect effect) {
super(effect);
this.fromZone = effect.fromZone;
this.allowedCaster = effect.allowedCaster;
}
@Override
public boolean apply(Game game, Ability source) {
return true;
}
@Override
public PlayFromNotOwnHandZoneTargetEffect copy() {
return new PlayFromNotOwnHandZoneTargetEffect(this);
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
switch (allowedCaster) {
case YOU:
if (affectedControllerId != source.getControllerId()) {
return false;
}
break;
case OPPONENT:
if (!game.getOpponents(source.getControllerId()).contains(affectedControllerId)) {
return false;
}
break;
case ANY:
break;
}
List<UUID> targets = getTargetPointer().getTargets(game, source);
if (targets.isEmpty()) {
this.discard();
return false;
}
return targets.contains(objectId)
&& affectedControllerId.equals(source.getControllerId())
&& game.getState().getZone(objectId).match(fromZone);
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.keyword;
import java.util.UUID;
@ -68,16 +67,19 @@ class AftermathCastFromGraveyard extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (objectId.equals(source.getSourceId())
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID affectedControllerId) {
if (affectedAbility != null && affectedAbility.getSourceId().equals(source.getSourceId())
&& affectedControllerId.equals(source.getControllerId())) {
Card card = game.getCard(source.getSourceId());
if (card != null && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
return true;
}
return game.getState().getZone(objectId).equals(Zone.GRAVEYARD);
}
return false;
}
@Override
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return false;
}
}
class AftermathCantCastFromHand extends ContinuousRuleModifyingEffectImpl {
@ -168,17 +170,14 @@ class AftermathExileAsResolvesFromGraveyard extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
UUID sourceId = source.getSourceId();
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard instanceof SplitCardHalf) {
sourceCard = ((SplitCardHalf) sourceCard).getParentCard();
sourceId = sourceCard.getId();
}
if (sourceCard != null) {
Player player = game.getPlayer(sourceCard.getOwnerId());
if (player != null) {
return player.moveCardToExileWithInfo(sourceCard, null, "", sourceId, game, ((ZoneChangeEvent) event).getFromZone(), true);
return player.moveCards(sourceCard, Zone.EXILED, source, game);
}
}
return false;