Search in sources :

Example 31 with StackAbility

use of mage.game.stack.StackAbility in project mage by magefree.

the class ActivatePlaneswalkerLoyaltyAbilityTriggeredAbility method checkTrigger.

@Override
public boolean checkTrigger(GameEvent event, Game game) {
    if (!event.getPlayerId().equals(getControllerId())) {
        return false;
    }
    StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId());
    if (stackAbility == null || !(stackAbility.getStackAbility() instanceof LoyaltyAbility)) {
        return false;
    }
    Permanent permanent = stackAbility.getSourcePermanentOrLKI(game);
    if (permanent == null || !permanent.isPlaneswalker(game) || !permanent.hasSubtype(planeswalkerSubType, game)) {
        return false;
    }
    this.getEffects().setValue("stackAbility", stackAbility);
    return true;
}
Also used : Permanent(mage.game.permanent.Permanent) LoyaltyAbility(mage.abilities.LoyaltyAbility) StackAbility(mage.game.stack.StackAbility)

Example 32 with StackAbility

use of mage.game.stack.StackAbility in project mage by magefree.

the class AuraReplacementEffect method replaceEvent.

@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
    Zone fromZone = ((ZoneChangeEvent) event).getFromZone();
    Card card = game.getCard(event.getTargetId());
    if (card == null) {
        return false;
    }
    Card firstCardFace = null;
    if (game.getState().getValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + card.getId()) != null) {
        firstCardFace = card;
        card = card.getSecondCardFace();
        if (!card.isEnchantment(game) || !card.hasSubtype(SubType.AURA, game)) {
            return false;
        }
    }
    // Aura cards that go to battlefield face down (Manifest) don't have to select targets
    if (card.isFaceDown(game)) {
        return false;
    }
    // Aura enters the battlefield attached
    Object object = game.getState().getValue("attachTo:" + card.getId());
    if (object != null) {
        if (object instanceof Permanent) {
            // Aura is attached to a permanent on the battlefield
            return false;
        }
        if (object instanceof UUID) {
            Player player = game.getPlayer((UUID) object);
            if (player != null) {
                // Aura is attached to a player
                return false;
            }
        }
    }
    UUID targetId = null;
    MageObject sourceObject = game.getObject(event.getSourceId());
    boolean enchantCardInGraveyard = false;
    if (sourceObject instanceof StackAbility) {
        StackAbility stackAbility = (StackAbility) sourceObject;
        if (!stackAbility.getEffects().isEmpty()) {
            targetId = stackAbility.getEffects().get(0).getTargetPointer().getFirst(game, stackAbility);
        }
    }
    // So continuousEffects are removed if previous effect of the same ability did move objects that cause continuous effects
    game.applyEffects();
    Player controllingPlayer = null;
    if (targetId == null) {
        SpellAbility spellAbility = card.getSpellAbility();
        if (spellAbility.getTargets().isEmpty()) {
            for (Ability ability : card.getAbilities(game)) {
                if ((ability instanceof SpellAbility) && SpellAbilityType.BASE_ALTERNATE == ((SpellAbility) ability).getSpellAbilityType() && !ability.getTargets().isEmpty()) {
                    spellAbility = (SpellAbility) ability;
                    break;
                }
            }
        }
        if (spellAbility.getTargets().isEmpty()) {
            return false;
        }
        Target target = spellAbility.getTargets().get(0).copy();
        Outcome auraOutcome = Outcome.BoostCreature;
        for (Effect effect : spellAbility.getEffects()) {
            if (effect instanceof AttachEffect) {
                auraOutcome = effect.getOutcome();
                break;
            }
        }
        enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
        if (target != null) {
            // always not target because this way it's not handled targeted
            target.setNotTarget(true);
            // necessary if e.g. aura is blinked multiple times
            target.clearChosen();
        }
        if (event.getPlayerId() != null) {
            controllingPlayer = game.getPlayer(event.getPlayerId());
        } else {
            controllingPlayer = game.getPlayer(card.getOwnerId());
        }
        if (target != null && controllingPlayer != null && controllingPlayer.choose(auraOutcome, target, card.getId(), game)) {
            targetId = target.getFirstTarget();
        }
    }
    Card targetCard = null;
    Permanent targetPermanent = null;
    if (enchantCardInGraveyard) {
        targetCard = game.getCard(targetId);
    } else {
        targetPermanent = game.getPermanent(targetId);
    }
    Player targetPlayer = game.getPlayer(targetId);
    if (targetCard != null || targetPermanent != null || targetPlayer != null) {
        if (firstCardFace != null) {
            // transforming card. remove first face (original card) from old zone
            firstCardFace.removeFromZone(game, fromZone, source);
        } else {
            card.removeFromZone(game, fromZone, source);
        }
        PermanentCard permanent = new PermanentCard(card, (controllingPlayer == null ? card.getOwnerId() : controllingPlayer.getId()), game);
        ZoneChangeEvent zoneChangeEvent = new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD);
        permanent.updateZoneChangeCounter(game, zoneChangeEvent);
        game.addPermanent(permanent, 0);
        card.setZone(Zone.BATTLEFIELD, game);
        if (permanent.entersBattlefield(source, game, fromZone, true)) {
            String attachToName = null;
            if (targetCard != null) {
                permanent.attachTo(targetCard.getId(), source, game);
                attachToName = targetCard.getLogName();
            } else if (targetPermanent != null) {
                targetPermanent.addAttachment(permanent.getId(), source, game);
                attachToName = targetPermanent.getLogName();
            } else if (targetPlayer != null) {
                targetPlayer.addAttachment(permanent.getId(), source, game);
                attachToName = targetPlayer.getLogName();
            }
            game.applyEffects();
            game.fireEvent(zoneChangeEvent);
            if (!game.isSimulation()) {
                if (controllingPlayer != null && fromZone != null && permanent != null) {
                    game.informPlayers(controllingPlayer.getLogName() + " puts " + (card.getLogName()) + " from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + " onto the Battlefield attached to " + attachToName);
                }
            }
            return true;
        }
    }
    return false;
}
Also used : StackAbility(mage.game.stack.StackAbility) SpellAbility(mage.abilities.SpellAbility) TransformAbility(mage.abilities.keyword.TransformAbility) Ability(mage.abilities.Ability) Player(mage.players.Player) Permanent(mage.game.permanent.Permanent) MageObject(mage.MageObject) SpellAbility(mage.abilities.SpellAbility) StackAbility(mage.game.stack.StackAbility) PermanentCard(mage.game.permanent.PermanentCard) Card(mage.cards.Card) AttachEffect(mage.abilities.effects.common.AttachEffect) ZoneChangeEvent(mage.game.events.ZoneChangeEvent) Target(mage.target.Target) TargetCardInGraveyard(mage.target.common.TargetCardInGraveyard) MageObject(mage.MageObject) AttachEffect(mage.abilities.effects.common.AttachEffect) UUID(java.util.UUID) PermanentCard(mage.game.permanent.PermanentCard)

Example 33 with StackAbility

use of mage.game.stack.StackAbility in project mage by magefree.

the class RandomPlayer method triggerAbility.

@Override
public boolean triggerAbility(TriggeredAbility source, Game game) {
    if (source != null && source.canChooseTarget(game, playerId)) {
        Ability ability;
        List<Ability> options = getPlayableOptions(source, game);
        if (options.isEmpty()) {
            ability = source;
        } else {
            if (options.size() == 1) {
                ability = options.get(0);
            } else {
                ability = options.get(RandomUtil.nextInt(options.size()));
            }
        }
        if (ability.isUsesStack()) {
            game.getStack().push(new StackAbility(ability, playerId));
            if (ability.activate(game, false)) {
                game.fireEvent(new GameEvent(GameEvent.EventType.TRIGGERED_ABILITY, ability.getId(), ability, ability.getControllerId()));
                actionCount++;
                return true;
            }
        } else {
            if (ability.activate(game, false)) {
                ability.resolve(game);
                actionCount++;
                return true;
            }
        }
    }
    return false;
}
Also used : PassAbility(mage.abilities.common.PassAbility) StackAbility(mage.game.stack.StackAbility) GameEvent(mage.game.events.GameEvent) StackAbility(mage.game.stack.StackAbility)

Example 34 with StackAbility

use of mage.game.stack.StackAbility in project mage by magefree.

the class CantBeTargetedSourceEffect method applies.

@Override
public boolean applies(GameEvent event, Ability source, Game game) {
    if (event.getTargetId().equals(source.getSourceId())) {
        StackObject stackObject = game.getStack().getStackObject(event.getSourceId());
        MageObject sourceObject;
        if (stackObject instanceof StackAbility) {
            sourceObject = ((StackAbility) stackObject).getSourceObject(game);
        } else {
            sourceObject = stackObject;
        }
        if (filterSource.match(sourceObject, game)) {
            return true;
        }
    }
    return false;
}
Also used : StackObject(mage.game.stack.StackObject) MageObject(mage.MageObject) StackAbility(mage.game.stack.StackAbility)

Example 35 with StackAbility

use of mage.game.stack.StackAbility in project mage by magefree.

the class ChangeATargetOfTargetSpellAbilityToSourceEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    StackObject stackObject = game.getStack().getStackObject(source.getFirstTarget());
    MageObject sourceObject = game.getObject(source.getSourceId());
    if (stackObject != null && sourceObject != null) {
        Targets targets = new Targets();
        Ability sourceAbility;
        String oldTargetName = null;
        if (stackObject instanceof Spell) {
            Spell spell = (Spell) stackObject;
            sourceAbility = spell.getSpellAbility();
        } else if (stackObject instanceof StackAbility) {
            StackAbility stackAbility = (StackAbility) stackObject;
            sourceAbility = stackAbility;
        } else {
            return false;
        }
        for (UUID modeId : sourceAbility.getModes().getSelectedModes()) {
            Mode mode = sourceAbility.getModes().get(modeId);
            targets.addAll(mode.getTargets());
        }
        boolean twoTimesTarget = false;
        if (targets.size() == 1 && targets.get(0).getTargets().size() == 1) {
            Target target = targets.get(0);
            if (target.getFirstTarget().equals(source.getSourceId())) {
                // Target was already the same source, so no change / target event to create
                return true;
            }
            if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
                oldTargetName = getTargetName(targets.getFirstTarget(), game);
                target.clearChosen();
                // The source is still the spell on the stack
                target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
            }
        } else {
            Player controller = game.getPlayer(source.getControllerId());
            boolean validTargets = false;
            do {
                for (Target target : targets) {
                    for (UUID targetId : target.getTargets()) {
                        String name = getTargetName(targets.getFirstTarget(), game);
                        if (!targetId.equals(source.getSourceId()) && target.getTargets().contains(source.getSourceId())) {
                            // you can't change this target to source because the source is already another targetId of that target.
                            twoTimesTarget = true;
                            continue;
                        }
                        if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
                            validTargets = true;
                            if (name != null && controller.chooseUse(Outcome.Neutral, "Change target from " + name + " to " + sourceObject.getLogName() + '?', source, game)) {
                                oldTargetName = getTargetName(targetId, game);
                                target.remove(targetId);
                                // The source is still the spell on the stack
                                target.addTarget(source.getSourceId(), stackObject.getStackAbility(), game);
                                break;
                            }
                        }
                    }
                    if (oldTargetName != null) {
                        break;
                    }
                }
                if (oldTargetName == null) {
                    game.informPlayer(controller, "You have to select at least one target to change to " + sourceObject.getIdName() + '!');
                }
            } while (validTargets && oldTargetName == null);
        }
        if (oldTargetName != null) {
            game.informPlayers(sourceObject.getLogName() + ": Changed target of " + stackObject.getLogName() + " from " + oldTargetName + " to " + sourceObject.getLogName());
        } else if (twoTimesTarget) {
            game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName());
        } else {
            game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName());
        }
        return true;
    }
    return false;
}
Also used : StackAbility(mage.game.stack.StackAbility) Ability(mage.abilities.Ability) Target(mage.target.Target) Player(mage.players.Player) Mode(mage.abilities.Mode) StackObject(mage.game.stack.StackObject) MageObject(mage.MageObject) Targets(mage.target.Targets) UUID(java.util.UUID) Spell(mage.game.stack.Spell) StackAbility(mage.game.stack.StackAbility)

Aggregations

StackAbility (mage.game.stack.StackAbility)42 Permanent (mage.game.permanent.Permanent)15 StackObject (mage.game.stack.StackObject)12 Player (mage.players.Player)11 Target (mage.target.Target)9 MageObject (mage.MageObject)8 Ability (mage.abilities.Ability)7 Spell (mage.game.stack.Spell)7 ActivatedManaAbilityImpl (mage.abilities.mana.ActivatedManaAbilityImpl)6 GameEvent (mage.game.events.GameEvent)6 Game (mage.game.Game)5 UUID (java.util.UUID)4 MageObjectReference (mage.MageObjectReference)4 PassAbility (mage.abilities.common.PassAbility)4 Mode (mage.abilities.Mode)3 Card (mage.cards.Card)3 FixedTarget (mage.target.targetpointer.FixedTarget)3 ActivatedAbility (mage.abilities.ActivatedAbility)2 LoyaltyAbility (mage.abilities.LoyaltyAbility)2 SpellAbility (mage.abilities.SpellAbility)2