Search in sources :

Example 21 with PermanentToken

use of mage.game.permanent.PermanentToken in project mage by magefree.

the class GameState method createEventGroups.

public List<GameEvent> createEventGroups(List<GameEvent> events, Game game) {
    class ZoneChangeData {

        private final Zone fromZone;

        private final Zone toZone;

        private final UUID sourceId;

        private final UUID playerId;

        Ability source;

        public ZoneChangeData(Ability source, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone) {
            this.sourceId = sourceId;
            this.playerId = playerId;
            this.fromZone = fromZone;
            this.toZone = toZone;
            this.source = source;
        }

        @Override
        public int hashCode() {
            return (this.fromZone.ordinal() + 1) * 1 + (this.toZone.ordinal() + 1) * 10 + (this.sourceId != null ? this.sourceId.hashCode() : 0) + (this.source != null ? this.source.hashCode() : 0);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj instanceof ZoneChangeData) {
                ZoneChangeData data = (ZoneChangeData) obj;
                return this.fromZone == data.fromZone && this.toZone == data.toZone && Objects.equals(this.sourceId, data.sourceId) && Objects.equals(this.source, data.source);
            }
            return false;
        }
    }
    Map<ZoneChangeData, List<GameEvent>> eventsByKey = new HashMap<>();
    List<GameEvent> groupEvents = new LinkedList<>();
    for (GameEvent event : events) {
        if (event instanceof ZoneChangeEvent) {
            ZoneChangeEvent castEvent = (ZoneChangeEvent) event;
            ZoneChangeData key = new ZoneChangeData(castEvent.getSource(), castEvent.getSourceId(), castEvent.getPlayerId(), castEvent.getFromZone(), castEvent.getToZone());
            if (eventsByKey.containsKey(key)) {
                eventsByKey.get(key).add(event);
            } else {
                List<GameEvent> list = new LinkedList<>();
                list.add(event);
                eventsByKey.put(key, list);
            }
        }
    }
    for (Map.Entry<ZoneChangeData, List<GameEvent>> entry : eventsByKey.entrySet()) {
        Set<Card> movedCards = new LinkedHashSet<>();
        Set<PermanentToken> movedTokens = new LinkedHashSet<>();
        for (Iterator<GameEvent> it = entry.getValue().iterator(); it.hasNext(); ) {
            GameEvent event = it.next();
            ZoneChangeEvent castEvent = (ZoneChangeEvent) event;
            UUID targetId = castEvent.getTargetId();
            Card card = ZonesHandler.getTargetCard(game, targetId);
            if (card instanceof PermanentToken) {
                movedTokens.add((PermanentToken) card);
            } else if (game.getObject(targetId) instanceof PermanentToken) {
                movedTokens.add((PermanentToken) game.getObject(targetId));
            } else if (card != null) {
                movedCards.add(card);
            }
        }
        ZoneChangeData eventData = entry.getKey();
        if (!movedCards.isEmpty() || !movedTokens.isEmpty()) {
            ZoneChangeGroupEvent event = new ZoneChangeGroupEvent(movedCards, movedTokens, eventData.sourceId, eventData.source, eventData.playerId, eventData.fromZone, eventData.toZone);
            groupEvents.add(event);
        }
    }
    return groupEvents;
}
Also used : Zone(mage.constants.Zone) PermanentToken(mage.game.permanent.PermanentToken) PermanentCard(mage.game.permanent.PermanentCard) MageObject(mage.MageObject) StackObject(mage.game.stack.StackObject) CommandObject(mage.game.command.CommandObject) PlayerList(mage.players.PlayerList) Collections.emptyList(java.util.Collections.emptyList)

Example 22 with PermanentToken

use of mage.game.permanent.PermanentToken in project mage by magefree.

the class CopyTokenFunction method apply.

@Override
public Token apply(Card source, Game game) {
    if (target == null) {
        throw new IllegalArgumentException("Target can't be null");
    }
    // A copy contains only the attributes of the basic card or basic Token that's the base of the permanent
    // else gained abililies would be copied too.
    MageObject sourceObj = source;
    if (source instanceof PermanentToken) {
        sourceObj = ((PermanentToken) source).getToken();
        // to show the source image, the original values have to be used
        target.setOriginalExpansionSetCode(((Token) sourceObj).getOriginalExpansionSetCode());
        target.setOriginalCardNumber(((Token) sourceObj).getOriginalCardNumber());
        target.setCopySourceCard(((PermanentToken) source).getToken().getCopySourceCard());
    } else if (source instanceof PermanentCard) {
        if (((PermanentCard) source).isMorphed() || ((PermanentCard) source).isManifested()) {
            MorphAbility.setPermanentToFaceDownCreature(target, game);
            return target;
        } else {
            if (((PermanentCard) source).isTransformed() && source.getSecondCardFace() != null) {
                sourceObj = ((PermanentCard) source).getSecondCardFace();
            } else {
                sourceObj = ((PermanentCard) source).getCard();
            }
            target.setOriginalExpansionSetCode(source.getExpansionSetCode());
            target.setOriginalCardNumber(source.getCardNumber());
            target.setCopySourceCard((Card) sourceObj);
        }
    } else {
        target.setOriginalExpansionSetCode(source.getExpansionSetCode());
        target.setOriginalCardNumber(source.getCardNumber());
        target.setCopySourceCard(source);
    }
    // modify all attributes permanently (without game usage)
    target.setName(sourceObj.getName());
    target.getColor().setColor(sourceObj.getColor());
    target.getManaCost().clear();
    target.getManaCost().add(sourceObj.getManaCost().copy());
    target.removeAllCardTypes();
    for (CardType type : sourceObj.getCardType()) {
        target.addCardType(type);
    }
    target.getSubtype().copyFrom(sourceObj.getSubtype());
    target.getSuperType().clear();
    for (SuperType type : sourceObj.getSuperType()) {
        target.addSuperType(type);
    }
    target.getAbilities().clear();
    for (Ability ability0 : sourceObj.getAbilities()) {
        Ability ability = ability0.copy();
        // The token is independant from the copy from object so it need a new original Id,
        // otherwise there are problems to check for created continuous effects to check if
        // the source (the Token) has still this ability
        ability.newOriginalId();
        target.addAbility(ability);
    }
    target.getPower().modifyBaseValue(sourceObj.getPower().getBaseValueModified());
    target.getToughness().modifyBaseValue(sourceObj.getToughness().getBaseValueModified());
    target.setStartingLoyalty(sourceObj.getStartingLoyalty());
    return target;
}
Also used : MorphAbility(mage.abilities.keyword.MorphAbility) Ability(mage.abilities.Ability) CardType(mage.constants.CardType) MageObject(mage.MageObject) PermanentToken(mage.game.permanent.PermanentToken) SuperType(mage.constants.SuperType) PermanentCard(mage.game.permanent.PermanentCard) PermanentCard(mage.game.permanent.PermanentCard) Card(mage.cards.Card)

Example 23 with PermanentToken

use of mage.game.permanent.PermanentToken in project mage by magefree.

the class NimDeathmantleEffect method checkTrigger.

@Override
public boolean checkTrigger(GameEvent event, Game game) {
    ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
    Permanent permanent = zEvent.getTarget();
    if (permanent != null && permanent.isOwnedBy(this.controllerId) && zEvent.isDiesEvent() && !(permanent instanceof PermanentToken) && permanent.isCreature(game)) {
        getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game) + 1));
        return true;
    }
    return false;
}
Also used : FixedTarget(mage.target.targetpointer.FixedTarget) ZoneChangeEvent(mage.game.events.ZoneChangeEvent) Permanent(mage.game.permanent.Permanent) PermanentToken(mage.game.permanent.PermanentToken)

Example 24 with PermanentToken

use of mage.game.permanent.PermanentToken in project mage by magefree.

the class PlayerImpl method putCardOnTopXOfLibrary.

@Override
public boolean putCardOnTopXOfLibrary(Card card, Game game, Ability source, int xFromTheTop, boolean withName) {
    if (card.isOwnedBy(getId())) {
        if (library.size() + 1 < xFromTheTop) {
            putCardsOnBottomOfLibrary(new CardsImpl(card), game, source, true);
        } else {
            if (card.moveToZone(Zone.LIBRARY, source, game, true) && !(card instanceof PermanentToken) && !card.isCopy()) {
                Card cardInLib = getLibrary().getFromTop(game);
                if (cardInLib != null && cardInLib.getId().equals(card.getId())) {
                    // check needed because e.g. commander can go to command zone
                    cardInLib = getLibrary().removeFromTop(game);
                    getLibrary().putCardToTopXPos(cardInLib, xFromTheTop, game);
                    game.informPlayers((withName ? cardInLib.getLogName() : "A card") + " is put into " + getLogName() + "'s library " + CardUtil.numberToOrdinalText(xFromTheTop) + " from the top" + CardUtil.getSourceLogName(game, source, cardInLib.getId()));
                }
            } else {
                return false;
            }
        }
    } else {
        return game.getPlayer(card.getOwnerId()).putCardOnTopXOfLibrary(card, game, source, xFromTheTop, withName);
    }
    return true;
}
Also used : PermanentToken(mage.game.permanent.PermanentToken) FilterCard(mage.filter.FilterCard) TargetCard(mage.target.TargetCard) PermanentCard(mage.game.permanent.PermanentCard)

Example 25 with PermanentToken

use of mage.game.permanent.PermanentToken in project mage by magefree.

the class TokenImpl method putOntoBattlefieldHelper.

private static void putOntoBattlefieldHelper(CreateTokenEvent event, Game game, Ability source, boolean tapped, boolean attacking, UUID attackedPlayer, boolean created) {
    Player controller = game.getPlayer(event.getPlayerId());
    if (controller == null) {
        return;
    }
    for (Map.Entry<Token, Integer> entry : event.getTokens().entrySet()) {
        Token token = entry.getKey();
        int amount = entry.getValue();
        String setCode = token instanceof TokenImpl ? ((TokenImpl) token).getSetCode(game, event.getSourceId()) : null;
        List<Permanent> needTokens = new ArrayList<>();
        List<Permanent> allowedTokens = new ArrayList<>();
        // prepare tokens to enter
        for (int i = 0; i < amount; i++) {
            // use event.getPlayerId() as controller cause it can be replaced by replacement effect
            PermanentToken newPermanent = new PermanentToken(token, event.getPlayerId(), setCode, game);
            game.getState().addCard(newPermanent);
            needTokens.add(newPermanent);
            game.getPermanentsEntering().put(newPermanent.getId(), newPermanent);
            newPermanent.setTapped(tapped);
            ZoneChangeEvent emptyEvent = new ZoneChangeEvent(newPermanent, newPermanent.getControllerId(), Zone.OUTSIDE, Zone.BATTLEFIELD);
            // tokens zcc must simulate card's zcc too keep copied card/spell settings
            // (example: etb's kicker ability of copied creature spell, see tests with Deathforge Shaman)
            newPermanent.updateZoneChangeCounter(game, emptyEvent);
        }
        // check ETB effects
        game.setScopeRelevant(true);
        for (Permanent permanent : needTokens) {
            if (permanent.entersBattlefield(source, game, Zone.OUTSIDE, true)) {
                allowedTokens.add(permanent);
            } else {
                game.getPermanentsEntering().remove(permanent.getId());
            }
        }
        game.setScopeRelevant(false);
        // put allowed tokens to play
        int createOrder = game.getState().getNextPermanentOrderNumber();
        for (Permanent permanent : allowedTokens) {
            game.addPermanent(permanent, createOrder);
            permanent.setZone(Zone.BATTLEFIELD, game);
            game.getPermanentsEntering().remove(permanent.getId());
            // keep tokens ids
            if (token instanceof TokenImpl) {
                ((TokenImpl) token).lastAddedTokenIds.add(permanent.getId());
                ((TokenImpl) token).lastAddedTokenId = permanent.getId();
            }
            // created token events
            ZoneChangeEvent zccEvent = new ZoneChangeEvent(permanent, permanent.getControllerId(), Zone.OUTSIDE, Zone.BATTLEFIELD);
            game.addSimultaneousEvent(zccEvent);
            if (permanent instanceof PermanentToken && created) {
                game.addSimultaneousEvent(new CreatedTokenEvent(source, (PermanentToken) permanent));
            }
            // code refactored from CopyPermanentEffect
            if (permanent.getSubtype().contains(SubType.AURA)) {
                Outcome auraOutcome = Outcome.BoostCreature;
                Target auraTarget = null;
                // attach - search effect in spell ability (example: cast Utopia Sprawl, cast Estrid's Invocation on it)
                for (Ability ability : permanent.getAbilities()) {
                    if (!(ability instanceof SpellAbility)) {
                        continue;
                    }
                    auraOutcome = ability.getEffects().getOutcome(ability);
                    for (Effect effect : ability.getEffects()) {
                        if (!(effect instanceof AttachEffect)) {
                            continue;
                        }
                        if (permanent.getSpellAbility().getTargets().size() > 0) {
                            auraTarget = permanent.getSpellAbility().getTargets().get(0);
                        }
                    }
                }
                // enchant - search in all abilities (example: cast Estrid's Invocation on enchanted creature by Estrid, the Masked second ability, cast Estrid's Invocation on it)
                if (auraTarget == null) {
                    for (Ability ability : permanent.getAbilities()) {
                        if (!(ability instanceof EnchantAbility)) {
                            continue;
                        }
                        auraOutcome = ability.getEffects().getOutcome(ability);
                        if (ability.getTargets().size() > 0) {
                            // Animate Dead don't have targets
                            auraTarget = ability.getTargets().get(0);
                        }
                    }
                }
                // if this is a copy of a copy, the copy's target has been copied and needs to be cleared
                if (auraTarget == null) {
                    break;
                }
                // clear selected target
                if (auraTarget.getFirstTarget() != null) {
                    auraTarget.remove(auraTarget.getFirstTarget());
                }
                // select new target
                auraTarget.setNotTarget(true);
                if (!controller.choose(auraOutcome, auraTarget, source.getSourceId(), game)) {
                    break;
                }
                UUID targetId = auraTarget.getFirstTarget();
                Permanent targetPermanent = game.getPermanent(targetId);
                Player targetPlayer = game.getPlayer(targetId);
                if (targetPermanent != null) {
                    targetPermanent.addAttachment(permanent.getId(), source, game);
                } else if (targetPlayer != null) {
                    targetPlayer.addAttachment(permanent.getId(), source, game);
                }
            }
            // must attack
            if (attacking && game.getCombat() != null && game.getActivePlayerId().equals(permanent.getControllerId())) {
                game.getCombat().addAttackingCreature(permanent.getId(), game, attackedPlayer);
            }
            // game logs
            if (created) {
                game.informPlayers(controller.getLogName() + " creates a " + permanent.getLogName() + " token");
            } else {
                game.informPlayers(permanent.getLogName() + " enters the battlefield as a token under " + controller.getLogName() + "'s control'");
            }
        }
    }
    // Needed to do it here without LKIReset i.e. do get SwordOfTheMeekTest running correctly.
    game.getState().applyEffects(game);
}
Also used : EnchantAbility(mage.abilities.keyword.EnchantAbility) SpellAbility(mage.abilities.SpellAbility) Ability(mage.abilities.Ability) Player(mage.players.Player) Permanent(mage.game.permanent.Permanent) CreatedTokenEvent(mage.game.events.CreatedTokenEvent) PermanentToken(mage.game.permanent.PermanentToken) PermanentToken(mage.game.permanent.PermanentToken) SpellAbility(mage.abilities.SpellAbility) EnchantAbility(mage.abilities.keyword.EnchantAbility) AttachEffect(mage.abilities.effects.common.AttachEffect) ZoneChangeEvent(mage.game.events.ZoneChangeEvent) Target(mage.target.Target) Outcome(mage.constants.Outcome) Effect(mage.abilities.effects.Effect) AttachEffect(mage.abilities.effects.common.AttachEffect)

Aggregations

PermanentToken (mage.game.permanent.PermanentToken)40 Permanent (mage.game.permanent.Permanent)30 Player (mage.players.Player)14 ZoneChangeEvent (mage.game.events.ZoneChangeEvent)8 Test (org.junit.Test)8 UUID (java.util.UUID)7 MageObject (mage.MageObject)7 Card (mage.cards.Card)7 PermanentCard (mage.game.permanent.PermanentCard)6 Ability (mage.abilities.Ability)5 TargetCreaturePermanent (mage.target.common.TargetCreaturePermanent)4 FixedTarget (mage.target.targetpointer.FixedTarget)4 Cards (mage.cards.Cards)3 CardsImpl (mage.cards.CardsImpl)3 CardType (mage.constants.CardType)3 Outcome (mage.constants.Outcome)3 Zone (mage.constants.Zone)3 Counters (mage.counters.Counters)3 FilterCard (mage.filter.FilterCard)3 ExileZone (mage.game.ExileZone)3