@Override public ActivationStatus canActivate(UUID playerId, Game game) { if (null != game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.CAST_AS_INSTANT, this, playerId, game) // check this first to allow Offering in main phase || this.spellCanBeActivatedRegularlyNow(playerId, game)) { if (spellAbilityType == SpellAbilityType.SPLIT || spellAbilityType == SpellAbilityType.SPLIT_AFTERMATH) { return ActivationStatus.getFalse(); MageObjectReference permittingSource = game.getContinuousEffects().asThough(getSourceId(), AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, null, playerId, game); if (permittingSource == null) { Card card = game.getCard(sourceId); if (this.isCheckPlayableMode()) { if (game.getContinuousEffects().preventedByRuleModification( GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, this.getId(), this.getSourceId(), playerId), this, game, true)) { return ActivationStatus.getFalse(); if (getSpellAbilityType() == SpellAbilityType.BASE_ALTERNATE) { Player player = game.getPlayer(playerId); if (player != null && getSourceId().equals(player.getCastSourceIdWithAlternateMana())) { return ActivationStatus.getFalse(); if (getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) { SplitCard splitCard = (SplitCard) game.getCard(getSourceId()); if (splitCard != null) { return new ActivationStatus(splitCard.getLeftHalfCard().getSpellAbility().canChooseTarget(game) && splitCard.getRightHalfCard().getSpellAbility().canChooseTarget(game), null); return new ActivationStatus(canChooseTarget(game), permittingSource);
public EmergeAbility(Card card, ManaCosts<ManaCost> emergeCost) { super(emergeCost, card.getName() + " with emerge", Zone.HAND, SpellAbilityType.BASE_ALTERNATE); this.getCosts().addAll(card.getSpellAbility().getCosts().copy()); this.getEffects().addAll(card.getSpellAbility().getEffects().copy()); this.getTargets().addAll(card.getSpellAbility().getTargets().copy()); this.timing = card.getSpellAbility().getTiming(); this.setRuleAtTheTop(true); this.emergeCost = emergeCost.copy(); }
public DrainLife(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{1}{B}"); // Spend only black mana on X. this.addAbility(new SimpleStaticAbility( Zone.ALL, new InfoEffect("Spend only black mana on X")).setRuleAtTheTop(true) ); // Drain Life deals X damage to any target. You gain life equal to the damage dealt, but not more life than the player's life total before Drain Life dealt damage or the creature's toughness. this.getSpellAbility().addTarget(new TargetAnyTarget()); this.getSpellAbility().addEffect(new DrainLifeEffect()); VariableCost variableCost = this.getSpellAbility().getManaCostsToPay().getVariableCosts().get(0); if (variableCost instanceof VariableManaCost) { ((VariableManaCost) variableCost).setFilter(filterBlack); } }
@Override public boolean apply(Card input, Game game) { SpellAbility ability = input.getSpellAbility().copy(); ability.setControllerId(controllerId); input.adjustTargets(ability, game); return ability.canChooseTarget(game); }
public Card getCharacteristics(Game game) { Spell spell = game.getSpell(this.getId()); if (spell != null) { return spell; } return game.getCard(this.getSourceId()); }
public boolean activate(Game game, boolean noMana) { setDoneActivatingManaAbilities(false); // Used for e.g. improvise if (!spellAbilities.get(0).activate(game, noMana)) { return false; } if (spellAbilities.size() > 1) { // if there are more abilities (fused split spell) or first ability added new abilities (splice), activate the additional abilities boolean ignoreAbility = true; boolean payNoMana = noMana; for (SpellAbility spellAbility : spellAbilities) { if (ignoreAbility) { ignoreAbility = false; } else { // costs for spliced abilities were added to main spellAbility, so pay no mana for spliced abilities payNoMana |= spellAbility.getSpellAbilityType() == SpellAbilityType.SPLICE; if (!spellAbility.activate(game, payNoMana)) { return false; } } } } setDoneActivatingManaAbilities(true); // can be activated again maybe during the resolution of the spell (e.g. Metallic Rebuke) return true; }
SpellAbility ability = originalAbility.copy(); ability.setControllerId(getId()); ability.setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(ability.getSourceId())); if (ability.getSpellAbilityType() != SpellAbilityType.BASE) { ability = chooseSpellAbilityForCast(ability, game, noMana); if (ability == null) { if (ability.getSourceId() == null) { logger.error("Ability without sourceId turn " + game.getTurnNum() + ". Ability: " + ability.getRule()); return false; Card card = game.getCard(ability.getSourceId()); if (card != null) { if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability.getSourceId(), playerId, permittingObject), ability)) { int bookmark = game.bookmarkState(); Zone fromZone = game.getState().getZone(card.getMainCard().getId()); card.cast(game, fromZone, ability, playerId); Spell spell = game.getStack().getSpell(ability.getId()); if (spell == null) { logger.error("Got no spell from stack. ability: " + ability.getRule()); return false; ability.setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(ability.getSourceId())); if (ability.getSourceId().equals(getCastSourceIdWithAlternateMana())) { Ability spellAbility = spell.getSpellAbility(); ManaCosts alternateCosts = getCastSourceIdManaCosts(); GameEvent event = GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId, permittingObject);
public Deprive(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}{U}"); // As an additional cost to cast Deprive, return a land you control to its owner's hand. this.getSpellAbility().addCost(new ReturnToHandChosenControlledPermanentCost(new TargetControlledPermanent(filter))); // Counter target spell. this.getSpellAbility().addTarget(new TargetSpell()); this.getSpellAbility().addEffect(new CounterTargetEffect()); }
@Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (permanent == null) { return false; } SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); if (spellAbility == null || !spellAbility.getSourceId().equals(source.getSourceId()) || permanent.getZoneChangeCounter(game) != spellAbility.getSourceObjectZoneChangeCounter()) { return false; } int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { if (amount < 5) { permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game); } else { permanent.addCounters(CounterType.P1P1.createInstance(amount * 2), source, game); } } return true; }
@Override public SpellAbility getSpellAbility() { if (spellAbility == null) { for (Ability ability : abilities.getActivatedAbilities(Zone.HAND)) { if (ability instanceof SpellAbility && ((SpellAbility) ability).getSpellAbilityType() != SpellAbilityType.BASE_ALTERNATE) { return spellAbility = (SpellAbility) ability; } } } return spellAbility; }
public SabaccGame(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); /* * Choose target permanent an opponent controls. That opponent chooses a permanent you control. * Flip a coin. If you win the flip, gain control of the permanent you chose. * If you lose the flip, your opponent gains control of the permanent they chose. */ this.getSpellAbility().getEffects().add(new SabaccGameEffect()); this.getSpellAbility().getTargets().add(new TargetPermanent(filter)); }
public Spell(Card card, SpellAbility ability, UUID controllerId, Zone fromZone) { this.card = card; this.color = card.getColor(null).copy(); this.frameColor = card.getFrameColor(null).copy(); this.frameStyle = card.getFrameStyle(); id = ability.getId(); this.ability = ability; this.ability.setControllerId(controllerId); if (ability.getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) { spellCards.add(((SplitCard) card).getLeftHalfCard()); spellAbilities.add(((SplitCard) card).getLeftHalfCard().getSpellAbility().copy()); spellCards.add(((SplitCard) card).getRightHalfCard()); spellAbilities.add(((SplitCard) card).getRightHalfCard().getSpellAbility().copy()); } else { spellCards.add(card); spellAbilities.add(ability); } this.controllerId = controllerId; this.fromZone = fromZone; this.countered = false; }
private void playRemoval(List<UUID> creatures, Game game) { for (UUID creatureId : creatures) { for (Card card : this.playableInstant) { if (card.getSpellAbility().canActivate(playerId, game).canActivate()) { for (Effect effect : card.getSpellAbility().getEffects()) { if (effect.getOutcome() == Outcome.DestroyPermanent || effect.getOutcome() == Outcome.ReturnToHand) { if (card.getSpellAbility().getTargets().get(0).canTarget(creatureId, card.getSpellAbility(), game)) { if (this.activateAbility(card.getSpellAbility(), game)) { return; } } } } } } } }
@Override public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) { switch (ability.getSpellAbilityType()) { case SPLIT: case SPLIT_FUSED: case SPLIT_AFTERMATH: MageObject object = game.getObject(ability.getSourceId()); if (object != null) { LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getSpellAbilities(object, game.getState().getZone(object.getId()), game); if (useableAbilities != null && !useableAbilities.isEmpty()) { // game.fireGetChoiceEvent(playerId, name, object, new ArrayList<>(useableAbilities.values())); // TODO: Improve this return (SpellAbility) useableAbilities.values().iterator().next(); } } return null; default: return ability; } }
public CleansingNova(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{W}{W}"); // Choose one — // • Destroy all creatures. this.getSpellAbility().addEffect(new DestroyAllEffect(StaticFilters.FILTER_PERMANENT_CREATURES)); // • Destroy all artifacts and enchantments. Mode mode = new Mode(); mode.addEffect(new DestroyAllEffect(filter)); this.getSpellAbility().getModes().addMode(mode); }
for (Ability ability : object.getAbilities()) { if (ability instanceof SpellAbility) { switch (((SpellAbility) ability).getSpellAbilityType()) { case SPLIT_FUSED: if (zone == Zone.HAND) { if (((SplitCard) object).getLeftHalfCard().getSpellAbility().canChooseTarget(game)) { useable.put(((SplitCard) object).getLeftHalfCard().getSpellAbility().getId(), ((SplitCard) object).getLeftHalfCard().getSpellAbility()); if (((SplitCard) object).getRightHalfCard().getSpellAbility().canChooseTarget(game)) { useable.put(((SplitCard) object).getRightHalfCard().getSpellAbility().getId(), ((SplitCard) object).getRightHalfCard().getSpellAbility()); if (((SplitCard) object).getRightHalfCard().getSpellAbility().canChooseTarget(game)) { useable.put(((SplitCard) object).getRightHalfCard().getSpellAbility().getId(), ((SplitCard) object).getRightHalfCard().getSpellAbility()); if (((SplitCard) object).getLeftHalfCard().getSpellAbility().canChooseTarget(game)) { useable.put(((SplitCard) object).getLeftHalfCard().getSpellAbility().getId(), ((SplitCard) object).getLeftHalfCard().getSpellAbility());
public FissureVent(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}{R}"); // Choose one or both - Destroy target artifact; and/or destroy target nonbasic land. this.getSpellAbility().getModes().setMinModes(1); this.getSpellAbility().getModes().setMaxModes(2); this.getSpellAbility().addEffect(new DestroyTargetEffect()); this.getSpellAbility().addTarget(new TargetArtifactPermanent().withChooseHint("destroy")); Mode mode1 = new Mode(); mode1.addEffect(new DestroyTargetEffect()); mode1.addTarget(new TargetNonBasicLandPermanent().withChooseHint("destroy")); this.getSpellAbility().addMode(mode1); }
@Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanentEntering(source.getSourceId()); if (permanent != null) { SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); if (spellAbility != null && spellAbility.getSourceId().equals(source.getSourceId()) && permanent.getZoneChangeCounter(game) == spellAbility.getSourceObjectZoneChangeCounter()) { // TODO: No perfect solution because there could be other effects that allow to cast the card for this mana cost if (spellAbility.getManaCosts().getText().equals("{W}{U}{B}{R}{G}")) { permanent.addCounters(CounterType.P1P1.createInstance(2), source, game); } } } return true; }
public PartWater(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{X}{U}"); // X target creatures gain islandwalk until end of turn. Effect effect = new GainAbilityTargetEffect(new IslandwalkAbility(false), Duration.EndOfTurn); effect.setText("X target creatures gain islandwalk until end of turn"); this.getSpellAbility().getEffects().add(effect); this.getSpellAbility().getTargets().add(new TargetCreaturePermanent()); this.getSpellAbility().setTargetAdjuster(PartWaterAdjuster.instance); }
public static void increaseCost(SpellAbility spellAbility, ManaCosts<ManaCost> manaCostsToIncrease) { ManaCosts<ManaCost> increasedCost = spellAbility.getManaCostsToPay().copy(); for (ManaCost manaCost : manaCostsToIncrease) { increasedCost.add(manaCost.copy()); } spellAbility.getManaCostsToPay().clear(); spellAbility.getManaCostsToPay().addAll(increasedCost); }