Search in sources :

Example 31 with GameEvent

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

the class AbilityImpl method activate.

@Override
public boolean activate(Game game, boolean noMana) {
    Player controller = game.getPlayer(this.getControllerId());
    if (controller == null) {
        return false;
    }
    game.applyEffects();
    MageObject sourceObject = getSourceObject(game);
    if (getSourceObjectZoneChangeCounter() == 0) {
        setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(getSourceId()));
    }
    setSourcePermanentTransformCount(game);
    /* 20130201 - 601.2b
         * If the player wishes to splice any cards onto the spell (see rule 702.45), he
         * or she reveals those cards in their hand.
         */
    if (this.abilityType == AbilityType.SPELL) {
        game.getContinuousEffects().applySpliceEffects(this, game);
    }
    // For Flashback ability can be set X before, so the X costs have to be restored for the flashbacked ability
    if (noMana) {
        if (!this.getManaCostsToPay().getVariableCosts().isEmpty()) {
            int xValue = this.getManaCostsToPay().getX();
            this.getManaCostsToPay().clear();
            VariableManaCost xCosts = new VariableManaCost(VariableCostType.ADDITIONAL);
            // no x events - rules from Unbound Flourishing:
            // - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
            xCosts.setAmount(xValue, xValue, false);
            this.getManaCostsToPay().add(xCosts);
        } else {
            this.getManaCostsToPay().clear();
        }
    }
    // A player can't apply two alternative methods of casting or two alternative costs to a single spell.
    if (!activateAlternateOrAdditionalCosts(sourceObject, noMana, controller, game)) {
        if (getAbilityType() == AbilityType.SPELL && ((SpellAbility) this).getSpellAbilityType() == SpellAbilityType.FACE_DOWN_CREATURE) {
            return false;
        }
    }
    // }
    if (getAbilityType() == AbilityType.SPELL && (getManaCostsToPay().isEmpty() && getCosts().isEmpty()) && !noMana) {
        return false;
    }
    // 20121001 - 601.2b
    // If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
    // its mana cost; see rule 107.3), the player announces the value of that variable.
    VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller);
    String announceString = handleOtherXCosts(game, controller);
    // For effects from cards like Void Winnower x costs have to be set
    if (this.getAbilityType() == AbilityType.SPELL) {
        GameEvent castEvent = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, this.getId(), this, getControllerId());
        castEvent.setZone(game.getState().getZone(CardUtil.getMainCardId(game, sourceId)));
        if (game.replaceEvent(castEvent, this)) {
            return false;
        }
    }
    handlePhyrexianManaCosts(game, controller);
    // Kicking a spell is always optional.
    if (!getModes().choose(game, this)) {
        return false;
    }
    // 2. From single addTarget/setChoice, it's a preffered method for tests (process it in normal choose dialogs like human player)
    if (controller.isTestsMode()) {
        if (!controller.addTargets(this, game)) {
            return false;
        }
    }
    for (UUID modeId : this.getModes().getSelectedModes()) {
        this.getModes().setActiveMode(modeId);
        if (sourceObject != null && this.getAbilityType() != AbilityType.TRIGGERED) {
            // triggered abilities check this already in playerImpl.triggerAbility
            sourceObject.adjustTargets(this, game);
        }
        if (!getTargets().isEmpty()) {
            Outcome outcome = getEffects().getOutcome(this);
            // only activated abilities can be canceled by human user (not triggered)
            boolean canCancel = this instanceof ActivatedAbility && controller.isHuman();
            if (!getTargets().chooseTargets(outcome, this.controllerId, this, noMana, game, canCancel)) {
                // was canceled during targer selection
                return false;
            }
        }
    }
    // this is a hack to prevent mana abilities with mana costs from causing endless loops - pay other costs first
    if (this instanceof ActivatedManaAbilityImpl && !costs.pay(this, game, this, controllerId, noMana, null)) {
        logger.debug("activate mana ability failed - non mana costs");
        return false;
    }
    // fused spell contains 3 abilities (fused, left, right)
    // fused cost added to fused ability, so no need cost modification for other parts
    boolean needCostModification = !CardUtil.isFusedPartAbility(this, game);
    // 20101001 - 601.2e
    if (needCostModification && sourceObject != null) {
        // still needed for CostAdjuster objects (to handle some types of dynamic costs)
        sourceObject.adjustCosts(this, game);
        game.getContinuousEffects().costModification(this, game);
    }
    UUID activatorId = controllerId;
    if ((this instanceof ActivatedAbilityImpl) && ((ActivatedAbilityImpl) this).getActivatorId() != null) {
        activatorId = ((ActivatedAbilityImpl) this).getActivatorId();
    }
    // 20100716 - 601.2f  (noMana is not used here, because mana costs were cleared for this ability before adding additional costs and applying cost modification effects)
    if (!manaCostsToPay.pay(this, game, this, activatorId, false, null)) {
        // cancel during mana payment
        return false;
    }
    // 20100716 - 601.2g
    if (!costs.pay(this, game, this, activatorId, noMana, null)) {
        logger.debug("activate failed - non mana costs");
        return false;
    }
    // inform about x costs now, so canceled announcements are not shown in the log
    if ((announceString != null) && (!announceString.equals(""))) {
        game.informPlayers(announceString);
    }
    if (variableManaCost != null) {
        int xValue = getManaCostsToPay().getX();
        game.informPlayers(controller.getLogName() + " announces a value of " + xValue + " for " + variableManaCost.getText());
    }
    activated = true;
    return true;
}
Also used : Player(mage.players.Player) MageObject(mage.MageObject) ActivatedManaAbilityImpl(mage.abilities.mana.ActivatedManaAbilityImpl) Hint(mage.abilities.hint.Hint) VariableManaCost(mage.abilities.costs.mana.VariableManaCost) GameEvent(mage.game.events.GameEvent) UUID(java.util.UUID)

Example 32 with GameEvent

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

the class AbilityImpl method handleManaXMultiplier.

public int handleManaXMultiplier(Game game, int value) {
    // some spells can change X value without new pays (Unbound Flourishing doubles X)
    GameEvent xEvent = GameEvent.getEvent(GameEvent.EventType.X_MANA_ANNOUNCE, this.getId(), this, getControllerId(), value);
    game.replaceEvent(xEvent, this);
    return xEvent.getAmount();
}
Also used : GameEvent(mage.game.events.GameEvent)

Example 33 with GameEvent

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

the class SpellAbility method canActivate.

@Override
public ActivationStatus canActivate(UUID playerId, Game game) {
    if (this.spellCanBeActivatedRegularlyNow(playerId, game)) {
        if (spellAbilityType == SpellAbilityType.SPLIT || spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) {
            return ActivationStatus.getFalse();
        }
        // play from not own hand
        ApprovingObject approvingObject = game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, this, playerId, game);
        if (approvingObject == null) {
            Card card = game.getCard(sourceId);
            if (!(card != null && card.isOwnedBy(playerId))) {
                return ActivationStatus.getFalse();
            }
        }
        // Check if rule modifying events prevent to cast the spell in check playable mode
        if (game.inCheckPlayableState()) {
            Card card = game.getCard(sourceId);
            GameEvent castEvent = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, this.getId(), this, playerId);
            castEvent.setZone(card == null ? null : game.getState().getZone(card.getMainCard().getId()));
            if (game.getContinuousEffects().preventedByRuleModification(castEvent, this, game, true)) {
                return ActivationStatus.getFalse();
            }
        }
        // Alternate spell abilities (Flashback, Overload) can't be cast with no mana to pay option
        if (getSpellAbilityType() == SpellAbilityType.BASE_ALTERNATE) {
            Player player = game.getPlayer(playerId);
            if (player != null && player.getCastSourceIdWithAlternateMana().contains(getSourceId())) {
                return ActivationStatus.getFalse();
            }
        }
        // can pay all costs and choose targets
        if (costs.canPay(this, this, playerId, game)) {
            if (getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) {
                SplitCard splitCard = (SplitCard) game.getCard(getSourceId());
                if (splitCard != null) {
                    // see https://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/magic-rulings-archives/251926-snapcaster-mage-and-fuse
                    if (game.getState().getZone(splitCard.getId()) == Zone.HAND) {
                        return new ActivationStatus(splitCard.getLeftHalfCard().getSpellAbility().canChooseTarget(game, playerId) && splitCard.getRightHalfCard().getSpellAbility().canChooseTarget(game, playerId), null);
                    }
                }
                return ActivationStatus.getFalse();
            } else {
                return new ActivationStatus(canChooseTarget(game, playerId), approvingObject);
            }
        }
    }
    return ActivationStatus.getFalse();
}
Also used : Player(mage.players.Player) ApprovingObject(mage.ApprovingObject) GameEvent(mage.game.events.GameEvent) SplitCard(mage.cards.SplitCard) SplitCard(mage.cards.SplitCard) Card(mage.cards.Card)

Example 34 with GameEvent

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

the class CumulativeUpkeepEffect method apply.

@Override
public boolean apply(Game game, Ability source) {
    Player player = game.getPlayer(source.getControllerId());
    Permanent permanent = game.getPermanent(source.getSourceId());
    if (player != null && permanent != null) {
        int ageCounter = permanent.getCounters(game).getCount(CounterType.AGE);
        if (cumulativeCost instanceof ManaCost) {
            ManaCostsImpl totalCost = new ManaCostsImpl<>();
            for (int i = 0; i < ageCounter; i++) {
                totalCost.add((ManaCost) cumulativeCost.copy());
            }
            if (player.chooseUse(Outcome.Benefit, "Pay " + totalCost.getText() + '?', source, game)) {
                totalCost.clearPaid();
                if (totalCost.payOrRollback(source, game, source, source.getControllerId())) {
                    game.fireEvent(new ManaEvent(EventType.PAID_CUMULATIVE_UPKEEP, permanent.getId(), source, player.getId(), totalCost.getUsedManaToPay()));
                    return true;
                }
            }
            game.fireEvent(new GameEvent(GameEvent.EventType.DIDNT_PAY_CUMULATIVE_UPKEEP, permanent.getId(), source, player.getId(), ageCounter, false));
            if (source.getControllerId().equals(permanent.getControllerId())) {
                // Permanent can only be sacrificed if you still control it
                permanent.sacrifice(source, game);
            }
            return true;
        } else {
            CostsImpl<Cost> totalCost = new CostsImpl<>();
            for (int i = 0; i < ageCounter; i++) {
                totalCost.add(cumulativeCost.copy());
            }
            if (player.chooseUse(Outcome.Benefit, totalCost.getText() + '?', source, game)) {
                totalCost.clearPaid();
                int bookmark = game.bookmarkState();
                if (totalCost.pay(source, game, source, source.getControllerId(), false, null)) {
                    game.fireEvent(new GameEvent(GameEvent.EventType.PAID_CUMULATIVE_UPKEEP, permanent.getId(), source, player.getId(), ageCounter, false));
                    return true;
                } else {
                    player.restoreState(bookmark, source.getRule(), game);
                }
            }
            game.fireEvent(new GameEvent(GameEvent.EventType.DIDNT_PAY_CUMULATIVE_UPKEEP, permanent.getId(), source, player.getId(), ageCounter, false));
            permanent.sacrifice(source, game);
            return true;
        }
    }
    return false;
}
Also used : Player(mage.players.Player) Permanent(mage.game.permanent.Permanent) ManaCost(mage.abilities.costs.mana.ManaCost) CostsImpl(mage.abilities.costs.CostsImpl) ManaCostsImpl(mage.abilities.costs.mana.ManaCostsImpl) GameEvent(mage.game.events.GameEvent) ManaCostsImpl(mage.abilities.costs.mana.ManaCostsImpl) ManaEvent(mage.game.events.ManaEvent) Cost(mage.abilities.costs.Cost) ManaCost(mage.abilities.costs.mana.ManaCost) OrCost(mage.abilities.costs.OrCost)

Example 35 with GameEvent

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

the class CandlesGlowPreventDamageTargetEffect method replaceEvent.

@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
    GameEvent preventEvent = new PreventDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), event.getAmount(), ((DamageEvent) event).isCombatDamage());
    if (!game.replaceEvent(preventEvent)) {
        int prevented;
        if (event.getAmount() >= this.amount) {
            int damage = amount;
            event.setAmount(event.getAmount() - amount);
            this.used = true;
            game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage));
            prevented = damage;
        } else {
            int damage = event.getAmount();
            event.setAmount(0);
            amount -= damage;
            game.fireEvent(new PreventedDamageEvent(event.getTargetId(), source.getSourceId(), source, source.getControllerId(), damage));
            prevented = damage;
        }
        // add live now
        if (prevented > 0) {
            Player controller = game.getPlayer(source.getControllerId());
            if (controller != null) {
                controller.gainLife(prevented, game, source);
                game.informPlayers("Candles' Glow: Prevented " + prevented + " damage ");
                game.informPlayers("Candles' Glow: " + controller.getLogName() + " gained " + prevented + "life");
            }
        }
    }
    return false;
}
Also used : Player(mage.players.Player) GameEvent(mage.game.events.GameEvent) PreventedDamageEvent(mage.game.events.PreventedDamageEvent) PreventDamageEvent(mage.game.events.PreventDamageEvent)

Aggregations

GameEvent (mage.game.events.GameEvent)82 Permanent (mage.game.permanent.Permanent)28 Player (mage.players.Player)24 PreventDamageEvent (mage.game.events.PreventDamageEvent)23 PreventedDamageEvent (mage.game.events.PreventedDamageEvent)23 Game (mage.game.Game)22 Ability (mage.abilities.Ability)15 MageInt (mage.MageInt)13 CardImpl (mage.cards.CardImpl)13 CardSetInfo (mage.cards.CardSetInfo)13 java.util (java.util)12 OneShotEffect (mage.abilities.effects.OneShotEffect)12 Watcher (mage.watchers.Watcher)12 MageObjectReference (mage.MageObjectReference)11 Card (mage.cards.Card)11 UUID (java.util.UUID)10 TriggeredAbilityImpl (mage.abilities.TriggeredAbilityImpl)10 mage.constants (mage.constants)10 MageObject (mage.MageObject)9 Spell (mage.game.stack.Spell)9