[LCI] Implement Ojer Pakpatiq, Deepest Epoch / Temple of Cyclical Time

This commit is contained in:
Susucre 2023-11-05 16:28:43 +01:00
parent ada9c549c3
commit ec475f486c
3 changed files with 261 additions and 0 deletions

View file

@ -0,0 +1,203 @@
package mage.cards.o;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.common.SpellCastControllerTriggeredAbility;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ReboundAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.counters.CounterType;
import mage.filter.FilterSpell;
import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
* @author Susucr
*/
public final class OjerPakpatiqDeepestEpoch extends CardImpl {
private static final FilterSpell filter = new FilterSpell("an instant spell");
static {
filter.add(CardType.INSTANT.getPredicate());
}
public OjerPakpatiqDeepestEpoch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}");
this.secondSideCardClazz = mage.cards.t.TempleOfCyclicalTime.class;
this.supertype.add(SuperType.LEGENDARY);
this.subtype.add(SubType.GOD);
this.power = new MageInt(4);
this.toughness = new MageInt(3);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Whenever you cast an instant spell from your hand, it gains rebound.
this.addAbility(new SpellCastControllerTriggeredAbility(
Zone.BATTLEFIELD, new OjerPakpatiqDeepestEpochGainReboundEffect(), filter,
false, SetTargetPointer.SPELL, Zone.HAND
));
// When Ojer Pakpatiq dies, return it to the battlefield tapped and transformed under its owner's control with three time counters on it.
this.addAbility(new TransformAbility());
this.addAbility(new DiesSourceTriggeredAbility(new OjerPakpatiqDeepestEpochTrigger()));
}
private OjerPakpatiqDeepestEpoch(final OjerPakpatiqDeepestEpoch card) {
super(card);
}
@Override
public OjerPakpatiqDeepestEpoch copy() {
return new OjerPakpatiqDeepestEpoch(this);
}
}
/**
* Inspired by {@link mage.cards.n.NarsetTranscendent}
*/
class OjerPakpatiqDeepestEpochGainReboundEffect extends ContinuousEffectImpl {
public OjerPakpatiqDeepestEpochGainReboundEffect() {
super(Duration.Custom, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
staticText = "it gains rebound";
}
private OjerPakpatiqDeepestEpochGainReboundEffect(final OjerPakpatiqDeepestEpochGainReboundEffect effect) {
super(effect);
}
@Override
public OjerPakpatiqDeepestEpochGainReboundEffect copy() {
return new OjerPakpatiqDeepestEpochGainReboundEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source));
if (spell == null) {
discard();
return false;
}
Card card = spell.getCard();
if (card == null) {
return false;
}
addReboundAbility(card, game);
return true;
}
private void addReboundAbility(Card card, Game game) {
boolean found = false;
for (Ability ability : card.getAbilities(game)) {
if (ability instanceof ReboundAbility) {
found = true;
break;
}
}
if (!found) {
Ability ability = new ReboundAbility();
game.getState().addOtherAbility(card, ability);
}
}
}
// Inspired by Edgar, Charmed Groom
class OjerPakpatiqDeepestEpochTrigger extends OneShotEffect {
OjerPakpatiqDeepestEpochTrigger() {
super(Outcome.Benefit);
staticText = "return it to the battlefield tapped and transformed under its owner's control with three time counters on it";
}
private OjerPakpatiqDeepestEpochTrigger(final OjerPakpatiqDeepestEpochTrigger effect) {
super(effect);
}
@Override
public OjerPakpatiqDeepestEpochTrigger copy() {
return new OjerPakpatiqDeepestEpochTrigger(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
MageObject sourceObject = source.getSourceObjectIfItStillExists(game);
if (!(sourceObject instanceof Card)) {
return false;
}
game.getState().setValue(TransformAbility.VALUE_KEY_ENTER_TRANSFORMED + source.getSourceId(), Boolean.TRUE);
OjerPakpatiqDeepestEpochAddCounterReplacementEffect counterEffect =
new OjerPakpatiqDeepestEpochAddCounterReplacementEffect();
counterEffect.setTargetPointer(new FixedTarget(sourceObject.getId(), game));
game.addEffect(counterEffect, source);
controller.moveCards((Card) sourceObject, Zone.BATTLEFIELD, source, game, true, false, true, null);
return true;
}
}
class OjerPakpatiqDeepestEpochAddCounterReplacementEffect extends ReplacementEffectImpl {
public OjerPakpatiqDeepestEpochAddCounterReplacementEffect() {
super(Duration.EndOfStep, Outcome.BoostCreature);
}
private OjerPakpatiqDeepestEpochAddCounterReplacementEffect(final OjerPakpatiqDeepestEpochAddCounterReplacementEffect effect) {
super(effect);
}
@Override
public OjerPakpatiqDeepestEpochAddCounterReplacementEffect copy() {
return new OjerPakpatiqDeepestEpochAddCounterReplacementEffect(this);
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
return getTargetPointer().getTargets(game, source).contains(event.getTargetId());
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (permanent == null) {
return false;
}
permanent.addCounters(CounterType.TIME.createInstance(3), source.getControllerId(), source, game, event.getAppliedEffects());
discard();
return false;
}
}

View file

@ -0,0 +1,56 @@
package mage.cards.t;
import mage.abilities.Ability;
import mage.abilities.common.ActivateIfConditionActivatedAbility;
import mage.abilities.condition.common.SourceHasCounterCondition;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.TransformSourceEffect;
import mage.abilities.effects.common.counter.RemoveCounterSourceEffect;
import mage.abilities.mana.BlueManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.counters.CounterType;
import java.util.UUID;
/**
* @author Susucr
*/
public final class TempleOfCyclicalTime extends CardImpl {
public TempleOfCyclicalTime(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
this.nightCard = true;
// (Transforms from Ojer Pakpatiq, Deepest Epoch.)
// {T}: Add {U}. Remove a time counter from Temple of Cyclical Time.
Ability ability = new BlueManaAbility();
ability.addEffect(new RemoveCounterSourceEffect(CounterType.TIME.createInstance()));
this.addAbility(ability);
// {2}{U}, {T}: Transform Temple of Cyclical Time. Activate only if it has no time counters on it and only as a sorcery.
ability = new ActivateIfConditionActivatedAbility(
Zone.BATTLEFIELD,
new TransformSourceEffect(),
new ManaCostsImpl<>("{2}{U}"),
new SourceHasCounterCondition(CounterType.TIME, 0, 0),
TimingRule.SORCERY
);
ability.addCost(new TapSourceCost());
this.addAbility(ability);
}
private TempleOfCyclicalTime(final TempleOfCyclicalTime card) {
super(card);
}
@Override
public TempleOfCyclicalTime copy() {
return new TempleOfCyclicalTime(this);
}
}

View file

@ -214,6 +214,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
cards.add(new SetCardInfo("Oaken Siren", 66, Rarity.COMMON, mage.cards.o.OakenSiren.class));
cards.add(new SetCardInfo("Ojer Axonil, Deepest Might", 158, Rarity.MYTHIC, mage.cards.o.OjerAxonilDeepestMight.class));
cards.add(new SetCardInfo("Ojer Kaslem, Deepest Growth", 204, Rarity.MYTHIC, mage.cards.o.OjerKaslemDeepestGrowth.class));
cards.add(new SetCardInfo("Ojer Pakpatiq, Deepest Epoch", 67, Rarity.MYTHIC, mage.cards.o.OjerPakpatiqDeepestEpoch.class));
cards.add(new SetCardInfo("Ojer Taq, Deepest Foundation", 26, Rarity.MYTHIC, mage.cards.o.OjerTaqDeepestFoundation.class));
cards.add(new SetCardInfo("Oltec Archaeologists", 27, Rarity.COMMON, mage.cards.o.OltecArchaeologists.class));
cards.add(new SetCardInfo("Oltec Cloud Guard", 28, Rarity.COMMON, mage.cards.o.OltecCloudGuard.class));
@ -301,6 +302,7 @@ public final class TheLostCavernsOfIxalan extends ExpansionSet {
cards.add(new SetCardInfo("Tectonic Hazard", 169, Rarity.COMMON, mage.cards.t.TectonicHazard.class));
cards.add(new SetCardInfo("Temple of Civilization", 26, Rarity.MYTHIC, mage.cards.t.TempleOfCivilization.class));
cards.add(new SetCardInfo("Temple of Cultivation", 204, Rarity.MYTHIC, mage.cards.t.TempleOfCultivation.class));
cards.add(new SetCardInfo("Temple of Cyclical Time", 67, Rarity.MYTHIC, mage.cards.t.TempleOfCyclicalTime.class));
cards.add(new SetCardInfo("Temple of Power", 158, Rarity.MYTHIC, mage.cards.t.TempleOfPower.class));
cards.add(new SetCardInfo("Temple of the Dead", 88, Rarity.MYTHIC, mage.cards.t.TempleOfTheDead.class));
cards.add(new SetCardInfo("Tendril of the Mycotyrant", 215, Rarity.UNCOMMON, mage.cards.t.TendrilOfTheMycotyrant.class));