Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions Mage.Sets/src/mage/cards/l/LatticeLibrary.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package mage.cards.l;

import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.common.CountersSourceCount;
import mage.abilities.effects.common.EntersBattlefieldWithXCountersEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.token.FractalToken;
import mage.game.stack.Spell;
import mage.watchers.common.FirstXSpellCastThisTurnWatcher;

/**
*
* @author muz
*/
public final class LatticeLibrary extends CardImpl {

public LatticeLibrary(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{X}{G}{G}");

// This enchantment enters with X study counters on it.
this.addAbility(new EntersBattlefieldAbility(new EntersBattlefieldWithXCountersEffect(CounterType.STUDY.createInstance())));

// When this enchantment enters and whenever you cast your first spell with {X} in its mana cost each turn,
// create a 0/0 green and blue Fractal creature token. Put a number of +1/+1 counters on it equal to the
// number of study counters on this enchantment.
this.addAbility(new LatticeLibraryTriggeredAbility(), new FirstXSpellCastThisTurnWatcher());
}

private LatticeLibrary(final LatticeLibrary card) {
super(card);
}

@Override
public LatticeLibrary copy() {
return new LatticeLibrary(this);
}
}

class LatticeLibraryTriggeredAbility extends TriggeredAbilityImpl {

LatticeLibraryTriggeredAbility() {
super(
Zone.BATTLEFIELD,
FractalToken.getEffect(
new CountersSourceCount(CounterType.STUDY),
". Put a number of +1/+1 counters on it equal to the number of study counters on {this}"
),
false
);
setTriggerPhrase("When {this} enters and whenever you cast your first spell with {X} in its mana cost each turn, ");
}

private LatticeLibraryTriggeredAbility(final LatticeLibraryTriggeredAbility ability) {
super(ability);
}

@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD || event.getType() == GameEvent.EventType.SPELL_CAST;
}

@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
return event.getTargetId().equals(getSourceId());
}

if (!event.getPlayerId().equals(getControllerId())) {
return false;
}
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell == null) {
return false;
}
// Watcher fires before triggers; it records first X spell via putIfAbsent.
// Matching the current spell's ID ensures we only trigger on the first one.
FirstXSpellCastThisTurnWatcher watcher = game.getState().getWatcher(FirstXSpellCastThisTurnWatcher.class);
return watcher != null && spell.getId().equals(watcher.getFirstXSpellId(getControllerId()));
}

@Override
public LatticeLibraryTriggeredAbility copy() {
return new LatticeLibraryTriggeredAbility(this);
}
}
102 changes: 102 additions & 0 deletions Mage.Sets/src/mage/cards/n/NevThePracticalDean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package mage.cards.n;

import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.dynamicvalue.common.EffectKeyValue;
import mage.abilities.effects.common.continuous.GainAbilityControlledEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.CounterAnyPredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.util.CardUtil;
import mage.watchers.common.FirstXSpellCastThisTurnWatcher;

/**
*
* @author muz
*/
public final class NevThePracticalDean extends CardImpl {

private static final FilterCreaturePermanent filter =
new FilterCreaturePermanent("creatures you control with counters on them");

static {
filter.add(CounterAnyPredicate.instance);
}

public NevThePracticalDean(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}");

this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.MERFOLK);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(2);
this.toughness = new MageInt(2);

// Creatures you control with counters on them have trample.
this.addAbility(new SimpleStaticAbility(new GainAbilityControlledEffect(
TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter
).setText("creatures you control with counters on them have trample")));

// Whenever you cast your first spell with {X} in its mana cost each turn, put X +1/+1 counters on Nev.
this.addAbility(new NevTriggeredAbility(), new FirstXSpellCastThisTurnWatcher());
}

private NevThePracticalDean(final NevThePracticalDean card) {
super(card);
}

@Override
public NevThePracticalDean copy() {
return new NevThePracticalDean(this);
}
}

class NevTriggeredAbility extends TriggeredAbilityImpl {

NevTriggeredAbility() {
super(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance(), new EffectKeyValue("xValue", "X")), false);
setTriggerPhrase("Whenever you cast your first spell with {X} in its mana cost each turn, ");
}

private NevTriggeredAbility(final NevTriggeredAbility ability) {
super(ability);
}

@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}

@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!event.getPlayerId().equals(getControllerId())) {
return false;
}
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell == null) {
return false;
}
FirstXSpellCastThisTurnWatcher watcher = game.getState().getWatcher(FirstXSpellCastThisTurnWatcher.class);
if (watcher == null || !spell.getId().equals(watcher.getFirstXSpellId(getControllerId()))) {
return false;
}
int xValue = CardUtil.getSourceCostsTag(game, spell.getSpellAbility(), "X", 0);
getEffects().setValue("xValue", xValue);
return xValue > 0;
}

@Override
public NevTriggeredAbility copy() {
return new NevTriggeredAbility(this);
}
}
95 changes: 95 additions & 0 deletions Mage.Sets/src/mage/cards/o/OwlinSpiralmancer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package mage.cards.o;

import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.CopyStackObjectEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.VigilanceAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.target.targetpointer.FixedTarget;
import mage.watchers.common.FirstXSpellCastThisTurnWatcher;

/**
*
* @author muz
*/
public final class OwlinSpiralmancer extends CardImpl {

public OwlinSpiralmancer(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");

this.subtype.add(SubType.BIRD);
this.subtype.add(SubType.WIZARD);
this.power = new MageInt(3);
this.toughness = new MageInt(4);

// Flying
this.addAbility(FlyingAbility.getInstance());

// Vigilance
this.addAbility(VigilanceAbility.getInstance());

// Whenever you cast your first spell with {X} in its mana cost each turn, you may copy it. You may choose new targets for the copy.
this.addAbility(new OwlinSpiralmancerTriggeredAbility(), new FirstXSpellCastThisTurnWatcher());
}

private OwlinSpiralmancer(final OwlinSpiralmancer card) {
super(card);
}

@Override
public OwlinSpiralmancer copy() {
return new OwlinSpiralmancer(this);
}
}

class OwlinSpiralmancerTriggeredAbility extends TriggeredAbilityImpl {

OwlinSpiralmancerTriggeredAbility() {
super(Zone.BATTLEFIELD, new CopyStackObjectEffect(), true);
}

private OwlinSpiralmancerTriggeredAbility(final OwlinSpiralmancerTriggeredAbility ability) {
super(ability);
}

@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}

@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!event.getPlayerId().equals(getControllerId())) {
return false;
}
Spell spell = game.getStack().getSpell(event.getTargetId());
if (spell == null) {
return false;
}
FirstXSpellCastThisTurnWatcher watcher = game.getState().getWatcher(FirstXSpellCastThisTurnWatcher.class);
if (watcher == null || !spell.getId().equals(watcher.getFirstXSpellId(getControllerId()))) {
return false;
}
getAllEffects().setTargetPointer(new FixedTarget(spell.getId(), game));
return true;
}

@Override
public String getRule() {
return "Whenever you cast your first spell with {X} in its mana cost each turn, you may copy it. You may choose new targets for the copy.";
}

@Override
public OwlinSpiralmancerTriggeredAbility copy() {
return new OwlinSpiralmancerTriggeredAbility(this);
}
}
Loading
Loading