Search in sources :

Example 46 with ZoneChangeEvent

use of mage.game.events.ZoneChangeEvent in project mage by magefree.

the class VerdantSuccessionEffect method checkTrigger.

@Override
public boolean checkTrigger(GameEvent event, Game game) {
    ZoneChangeEvent zoneChangeEvent = (ZoneChangeEvent) event;
    if (zoneChangeEvent.isDiesEvent()) {
        Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
        MageObject mageObject = game.getObject(sourceId);
        if (permanent != null && mageObject != null && filter.match(permanent, game)) {
            game.getState().setValue("verdantSuccession" + mageObject, permanent);
            return true;
        }
    }
    return false;
}
Also used : ZoneChangeEvent(mage.game.events.ZoneChangeEvent) Permanent(mage.game.permanent.Permanent) FilterCreaturePermanent(mage.filter.common.FilterCreaturePermanent) MageObject(mage.MageObject)

Example 47 with ZoneChangeEvent

use of mage.game.events.ZoneChangeEvent in project mage by magefree.

the class PutIntoGraveFromBattlefieldSourceTriggeredAbility method checkTrigger.

@Override
public boolean checkTrigger(GameEvent event, Game game) {
    if (event.getTargetId().equals(getSourceId())) {
        ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
        Permanent permanent = zEvent.getTarget();
        if (permanent != null && zEvent.isDiesEvent()) {
            return !onlyToControllerGraveyard || this.isControlledBy(game.getOwnerId(zEvent.getTargetId()));
        }
    }
    return false;
}
Also used : ZoneChangeEvent(mage.game.events.ZoneChangeEvent) Permanent(mage.game.permanent.Permanent)

Example 48 with ZoneChangeEvent

use of mage.game.events.ZoneChangeEvent in project mage by magefree.

the class ZonesHandler method placeInDestinationZone.

private static void placeInDestinationZone(ZoneChangeInfo info, Game game, int createOrder) {
    // Handle unmelded cards
    if (info instanceof ZoneChangeInfo.Unmelded) {
        ZoneChangeInfo.Unmelded unmelded = (ZoneChangeInfo.Unmelded) info;
        Zone toZone = null;
        for (ZoneChangeInfo subInfo : unmelded.subInfo) {
            toZone = subInfo.event.getToZone();
            placeInDestinationZone(subInfo, game, createOrder);
        }
        // We arbitrarily prefer the bottom half card. This should never be relevant.
        if (toZone != null) {
            game.setZone(unmelded.event.getTargetId(), toZone);
        }
        return;
    }
    // Handle normal cases
    ZoneChangeEvent event = info.event;
    Zone toZone = event.getToZone();
    Card targetCard = getTargetCard(game, event.getTargetId());
    // moving real cards
    Cards cardsToMove = null;
    // updating all card's parts (must be ordered LinkedHashMap)
    Map<Zone, Cards> cardsToUpdate = new LinkedHashMap<>();
    cardsToUpdate.put(toZone, new CardsImpl());
    cardsToUpdate.put(Zone.OUTSIDE, new CardsImpl());
    // if we're moving a token it shouldn't be put into any zone as an object.
    if (!(targetCard instanceof Permanent) && targetCard != null) {
        if (targetCard instanceof MeldCard) {
            // meld/group cards must be independent (use can choose order)
            cardsToMove = ((MeldCard) targetCard).getHalves();
            cardsToUpdate.get(toZone).addAll(cardsToMove);
        } else if (targetCard instanceof ModalDoubleFacesCard || targetCard instanceof ModalDoubleFacesCardHalf) {
            // mdf cards must be moved as single object, but each half must be updated separately
            ModalDoubleFacesCard mdfCard = (ModalDoubleFacesCard) targetCard.getMainCard();
            cardsToMove = new CardsImpl(mdfCard);
            cardsToUpdate.get(toZone).add(mdfCard);
            // * right to outside (it helps to ignore all triggers and other effects from that card)
            switch(toZone) {
                case STACK:
                case BATTLEFIELD:
                    if (targetCard.getId().equals(mdfCard.getLeftHalfCard().getId())) {
                        // play left
                        cardsToUpdate.get(toZone).add(mdfCard.getLeftHalfCard());
                        cardsToUpdate.get(Zone.OUTSIDE).add(mdfCard.getRightHalfCard());
                    } else if (targetCard.getId().equals(mdfCard.getRightHalfCard().getId())) {
                        // play right
                        cardsToUpdate.get(toZone).add(mdfCard.getRightHalfCard());
                        cardsToUpdate.get(Zone.OUTSIDE).add(mdfCard.getLeftHalfCard());
                    } else {
                        // cast mdf (only on stack)
                        if (!toZone.equals(Zone.STACK)) {
                            throw new IllegalStateException("Wrong mdf card move to " + toZone + " in placeInDestinationZone");
                        }
                        cardsToUpdate.get(toZone).add(mdfCard.getLeftHalfCard());
                        cardsToUpdate.get(toZone).add(mdfCard.getRightHalfCard());
                    }
                    break;
                default:
                    // move all parts
                    cardsToUpdate.get(toZone).add(mdfCard.getLeftHalfCard());
                    cardsToUpdate.get(toZone).add(mdfCard.getRightHalfCard());
                    break;
            }
        } else {
            cardsToMove = new CardsImpl(targetCard);
            cardsToUpdate.get(toZone).addAll(cardsToMove);
        }
        Player owner = game.getPlayer(targetCard.getOwnerId());
        switch(toZone) {
            case HAND:
                for (Card card : cardsToMove.getCards(game)) {
                    game.getPlayer(card.getOwnerId()).getHand().add(card);
                }
                break;
            case GRAVEYARD:
                for (Card card : chooseOrder("order to put in graveyard (last chosen will be on top)", cardsToMove, owner, game)) {
                    game.getPlayer(card.getOwnerId()).getGraveyard().add(card);
                }
                break;
            case LIBRARY:
                if (info instanceof ZoneChangeInfo.Library && ((ZoneChangeInfo.Library) info).top) {
                    // on top
                    for (Card card : chooseOrder("order to put on top of library (last chosen will be topmost)", cardsToMove, owner, game)) {
                        game.getPlayer(card.getOwnerId()).getLibrary().putOnTop(card, game);
                    }
                } else {
                    // on bottom
                    for (Card card : chooseOrder("order to put on bottom of library (last chosen will be bottommost)", cardsToMove, owner, game)) {
                        game.getPlayer(card.getOwnerId()).getLibrary().putOnBottom(card, game);
                    }
                }
                break;
            case EXILED:
                for (Card card : cardsToMove.getCards(game)) {
                    if (info instanceof ZoneChangeInfo.Exile && ((ZoneChangeInfo.Exile) info).id != null) {
                        ZoneChangeInfo.Exile exileInfo = (ZoneChangeInfo.Exile) info;
                        game.getExile().createZone(exileInfo.id, exileInfo.name).add(card);
                    } else {
                        game.getExile().getPermanentExile().add(card);
                    }
                }
                break;
            case COMMAND:
                // There should never be more than one card here.
                for (Card card : cardsToMove.getCards(game)) {
                    game.addCommander(new Commander(card));
                }
                break;
            case STACK:
                // There should never be more than one card here.
                for (Card card : cardsToMove.getCards(game)) {
                    Spell spell;
                    if (info instanceof ZoneChangeInfo.Stack && ((ZoneChangeInfo.Stack) info).spell != null) {
                        spell = ((ZoneChangeInfo.Stack) info).spell;
                    } else {
                        spell = new Spell(card, card.getSpellAbility().copy(), card.getOwnerId(), event.getFromZone(), game);
                    }
                    spell.syncZoneChangeCounterOnStack(card, game);
                    game.getStack().push(spell);
                    game.getState().setZone(spell.getId(), Zone.STACK);
                    game.getState().setZone(card.getId(), Zone.STACK);
                }
                break;
            case BATTLEFIELD:
                Permanent permanent = event.getTarget();
                game.addPermanent(permanent, createOrder);
                game.getPermanentsEntering().remove(permanent.getId());
                break;
            default:
                throw new UnsupportedOperationException("to Zone " + toZone.toString() + " not supported yet");
        }
    }
    // update zone in main
    game.setZone(event.getTargetId(), event.getToZone());
    // update zone in other parts (meld cards, mdf half cards)
    cardsToUpdate.entrySet().forEach(entry -> {
        for (Card card : entry.getValue().getCards(game)) {
            if (!card.getId().equals(event.getTargetId())) {
                game.setZone(card.getId(), entry.getKey());
            }
        }
    });
    // reset meld status
    if (targetCard instanceof MeldCard) {
        if (event.getToZone() != Zone.BATTLEFIELD) {
            ((MeldCard) targetCard).setMelded(false, game);
        }
    }
}
Also used : Player(mage.players.Player) Permanent(mage.game.permanent.Permanent) Commander(mage.game.command.Commander) Zone(mage.constants.Zone) Spell(mage.game.stack.Spell) FilterCard(mage.filter.FilterCard) TargetCard(mage.target.TargetCard) PermanentCard(mage.game.permanent.PermanentCard) ZoneChangeEvent(mage.game.events.ZoneChangeEvent)

Example 49 with ZoneChangeEvent

use of mage.game.events.ZoneChangeEvent in project mage by magefree.

the class ZonesHandler method maybeRemoveFromSourceZone.

private static boolean maybeRemoveFromSourceZone(ZoneChangeInfo info, Game game, Ability source) {
    ZoneChangeEvent event = info.event;
    // Handle Unmelded Cards
    if (info instanceof ZoneChangeInfo.Unmelded) {
        ZoneChangeInfo.Unmelded unmelded = (ZoneChangeInfo.Unmelded) info;
        MeldCard meld = game.getMeldCard(event.getTargetId());
        for (Iterator<ZoneChangeInfo> itr = unmelded.subInfo.iterator(); itr.hasNext(); ) {
            ZoneChangeInfo subInfo = itr.next();
            if (!maybeRemoveFromSourceZone(subInfo, game, source)) {
                itr.remove();
            } else if (Objects.equals(subInfo.event.getTargetId(), meld.getTopHalfCard().getId())) {
                meld.setTopLastZoneChangeCounter(meld.getTopHalfCard().getZoneChangeCounter(game));
            } else if (Objects.equals(subInfo.event.getTargetId(), meld.getBottomHalfCard().getId())) {
                meld.setBottomLastZoneChangeCounter(meld.getBottomHalfCard().getZoneChangeCounter(game));
            }
        }
        if (unmelded.subInfo.isEmpty()) {
            return false;
        }
        // We arbitrarily prefer the bottom half card. This should never be relevant.
        meld.updateZoneChangeCounter(game, unmelded.subInfo.get(unmelded.subInfo.size() - 1).event);
        return true;
    }
    // Handle all normal cases
    Card card = getTargetCard(game, event.getTargetId());
    if (card == null) {
        // If we can't find the card we can't remove it.
        return false;
    }
    boolean success = false;
    if (info.faceDown) {
        card.setFaceDown(true, game);
    } else if (event.getToZone().equals(Zone.BATTLEFIELD)) {
        if (!card.isPermanent(game) && (!card.isTransformable() || Boolean.FALSE.equals(game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId())))) {
            // Non permanents (Instants, Sorceries, ... stay in the zone they are if an abilty/effect tries to move it to the battlefield
            return false;
        }
    }
    if (!game.replaceEvent(event)) {
        Zone fromZone = event.getFromZone();
        if (event.getToZone() == Zone.BATTLEFIELD) {
            // prepare card and permanent
            // If needed take attributes from the spell (e.g. color of spell was changed)
            card = takeAttributesFromSpell(card, event, game);
            // controlling player can be replaced so use event player now
            Permanent permanent;
            if (card instanceof MeldCard) {
                permanent = new PermanentMeld(card, event.getPlayerId(), game);
            } else if (card instanceof ModalDoubleFacesCard) {
                // main mdf card must be processed before that call (e.g. only halfes can be moved to battlefield)
                throw new IllegalStateException("Unexpected trying of move mdf card to battlefield instead half");
            } else if (card instanceof Permanent) {
                throw new IllegalStateException("Unexpected trying of move permanent to battlefield instead card");
            } else {
                permanent = new PermanentCard(card, event.getPlayerId(), game);
            }
            // put onto battlefield with possible counters
            game.getPermanentsEntering().put(permanent.getId(), permanent);
            card.checkForCountersToAdd(permanent, source, game);
            permanent.setTapped(info instanceof ZoneChangeInfo.Battlefield && ((ZoneChangeInfo.Battlefield) info).tapped);
            permanent.setFaceDown(info.faceDown, game);
            if (info.faceDown) {
                card.setFaceDown(false, game);
            }
            // make sure the controller of all continuous effects of this card are switched to the current controller
            game.setScopeRelevant(true);
            game.getContinuousEffects().setController(permanent.getId(), permanent.getControllerId());
            if (permanent.entersBattlefield(source, game, fromZone, true) && card.removeFromZone(game, fromZone, source)) {
                success = true;
                event.setTarget(permanent);
            } else {
                // revert controller to owner if permanent does not enter
                game.getContinuousEffects().setController(permanent.getId(), permanent.getOwnerId());
                game.getPermanentsEntering().remove(permanent.getId());
            }
            game.setScopeRelevant(false);
        } else if (event.getTarget() != null) {
            card.setFaceDown(info.faceDown, game);
            Permanent target = event.getTarget();
            success = target.removeFromZone(game, fromZone, source) && game.getPlayer(target.getControllerId()).removeFromBattlefield(target, source, game);
        } else {
            card.setFaceDown(info.faceDown, game);
            success = card.removeFromZone(game, fromZone, source);
        }
    }
    if (success) {
        // KickerTest do many tests for token's zcc
        if (event.getToZone() == Zone.BATTLEFIELD && event.getTarget() != null) {
            event.getTarget().updateZoneChangeCounter(game, event);
        } else if (!(card instanceof Permanent)) {
            card.updateZoneChangeCounter(game, event);
        }
    }
    return success;
}
Also used : Permanent(mage.game.permanent.Permanent) Zone(mage.constants.Zone) FilterCard(mage.filter.FilterCard) TargetCard(mage.target.TargetCard) PermanentCard(mage.game.permanent.PermanentCard) ZoneChangeEvent(mage.game.events.ZoneChangeEvent) PermanentMeld(mage.game.permanent.PermanentMeld) PermanentCard(mage.game.permanent.PermanentCard)

Example 50 with ZoneChangeEvent

use of mage.game.events.ZoneChangeEvent in project mage by magefree.

the class ManaPaidSourceWatcher method watch.

@Override
public void watch(GameEvent event, Game game) {
    switch(event.getType()) {
        case ZONE_CHANGE:
            if (((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) {
                manaMap.remove(event.getTargetId());
            }
            return;
        case MANA_PAID:
            ManaPaidEvent manaEvent = (ManaPaidEvent) event;
            manaMap.computeIfAbsent(manaEvent.getTargetId(), x -> new ManaPaidTracker()).increment(manaEvent.getSourceObject(), manaEvent.getManaType(), game);
            manaMap.computeIfAbsent(manaEvent.getSourcePaidId(), x -> new ManaPaidTracker()).increment(manaEvent.getSourceObject(), manaEvent.getManaType(), game);
    }
}
Also used : Zone(mage.constants.Zone) HashMap(java.util.HashMap) UUID(java.util.UUID) SubType(mage.constants.SubType) ManaPaidEvent(mage.game.events.ManaPaidEvent) Serializable(java.io.Serializable) Game(mage.game.Game) Watcher(mage.watchers.Watcher) GameEvent(mage.game.events.GameEvent) ZoneChangeEvent(mage.game.events.ZoneChangeEvent) ManaType(mage.constants.ManaType) Map(java.util.Map) WatcherScope(mage.constants.WatcherScope) MageObject(mage.MageObject) Spell(mage.game.stack.Spell) ObjectColor(mage.ObjectColor) Copyable(mage.util.Copyable) ManaPaidEvent(mage.game.events.ManaPaidEvent)

Aggregations

ZoneChangeEvent (mage.game.events.ZoneChangeEvent)94 Permanent (mage.game.permanent.Permanent)56 Player (mage.players.Player)27 FixedTarget (mage.target.targetpointer.FixedTarget)23 Card (mage.cards.Card)20 UUID (java.util.UUID)14 MageObject (mage.MageObject)11 MageObjectReference (mage.MageObjectReference)10 Effect (mage.abilities.effects.Effect)9 FilterCard (mage.filter.FilterCard)8 PermanentToken (mage.game.permanent.PermanentToken)8 FilterPermanent (mage.filter.FilterPermanent)7 FilterCreaturePermanent (mage.filter.common.FilterCreaturePermanent)7 Ability (mage.abilities.Ability)6 OneShotEffect (mage.abilities.effects.OneShotEffect)6 CreateTokenEffect (mage.abilities.effects.common.CreateTokenEffect)6 Spell (mage.game.stack.Spell)6 Zone (mage.constants.Zone)5 TargetPermanent (mage.target.TargetPermanent)5 TargetCreaturePermanent (mage.target.common.TargetCreaturePermanent)5