[NEO] Implemented Kumano Faces Kakkazan / Etching of Kumano (#8674)

* [NEO] Implemented Kumano Faces Kakkazan / Etching of Kumano

* [NEO] Etching of Kumano - Clean up watcher controller check

Co-authored-by: Evan Kranzler <theelk801@gmail.com>
This commit is contained in:
Daniel Bomar 2022-02-12 14:05:04 -06:00 committed by GitHub
parent cff38b74b9
commit 0694fd3ef7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 311 additions and 0 deletions

View file

@ -0,0 +1,88 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.constants.*;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.watchers.common.DamagedByControlledWatcher;
/**
*
* @author weirddan455
*/
public final class EtchingOfKumano extends CardImpl {
public EtchingOfKumano(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.SHAMAN);
this.power = new MageInt(2);
this.toughness = new MageInt(2);
this.color.setRed(true);
this.nightCard = true;
// Haste
this.addAbility(HasteAbility.getInstance());
// If a creature dealt damage this turn by a source you controlled would die, exile it instead.
this.addAbility(new SimpleStaticAbility(new EtchingOfKumanoReplacementEffect()), new DamagedByControlledWatcher());
}
private EtchingOfKumano(final EtchingOfKumano card) {
super(card);
}
@Override
public EtchingOfKumano copy() {
return new EtchingOfKumano(this);
}
}
class EtchingOfKumanoReplacementEffect extends ReplacementEffectImpl {
public EtchingOfKumanoReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Exile);
this.staticText = "If a creature dealt damage this turn by a source you controlled would die, exile it instead";
}
private EtchingOfKumanoReplacementEffect(final EtchingOfKumanoReplacementEffect effect) {
super(effect);
}
@Override
public EtchingOfKumanoReplacementEffect copy() {
return new EtchingOfKumanoReplacementEffect(this);
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
((ZoneChangeEvent) event).setToZone(Zone.EXILED);
return false;
}
@Override
public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
ZoneChangeEvent zce = (ZoneChangeEvent) event;
if (zce.isDiesEvent()) {
DamagedByControlledWatcher watcher = game.getState().getWatcher(DamagedByControlledWatcher.class, source.getControllerId());
if (watcher != null) {
return watcher.wasDamaged(zce.getTarget(), game);
}
}
return false;
}
}

View file

@ -0,0 +1,176 @@
package mage.cards.k;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.common.SagaAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.ExileSagaAndReturnTransformedEffect;
import mage.abilities.keyword.TransformAbility;
import mage.constants.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.counters.CounterType;
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;
/**
*
* @author weirddan455
*/
public final class KumanoFacesKakkazan extends CardImpl {
public KumanoFacesKakkazan(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}");
this.subtype.add(SubType.SAGA);
this.secondSideCardClazz = mage.cards.e.EtchingOfKumano.class;
// (As this Saga enters and after your draw step, add a lore counter.)
SagaAbility sagaAbility = new SagaAbility(this);
// I Kumano Faces Kakkazan deals 1 damage to each opponent and each planeswalker they control.
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_I, new KumanoFacesKakkazanDamageEffect());
// II When you cast your next creature spell this turn, that creature enters the battlefield with an additional +1/+1 counter on it.
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_II, new CreateDelayedTriggeredAbilityEffect(new KumanoFacesKakkazanTriggeredAbility()));
// III Exile this Saga, then return it to the battlefield transformed under your control.
this.addAbility(new TransformAbility());
sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, new ExileSagaAndReturnTransformedEffect());
this.addAbility(sagaAbility);
}
private KumanoFacesKakkazan(final KumanoFacesKakkazan card) {
super(card);
}
@Override
public KumanoFacesKakkazan copy() {
return new KumanoFacesKakkazan(this);
}
}
class KumanoFacesKakkazanDamageEffect extends OneShotEffect {
public KumanoFacesKakkazanDamageEffect() {
super(Outcome.Damage);
this.staticText = "{this} deals 1 damage to each opponent and each planeswalker they control";
}
private KumanoFacesKakkazanDamageEffect(final KumanoFacesKakkazanDamageEffect effect) {
super(effect);
}
@Override
public KumanoFacesKakkazanDamageEffect copy() {
return new KumanoFacesKakkazanDamageEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Set<UUID> opponents = game.getOpponents(source.getControllerId());
if (opponents.isEmpty()) {
return false;
}
for (UUID opponentId : opponents) {
Player opponent = game.getPlayer(opponentId);
if (opponent != null) {
opponent.damage(1, source, game);
}
}
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.PLANESWALKER, game)) {
if (opponents.contains(permanent.getControllerId())) {
permanent.damage(1, source, game);
}
}
return true;
}
}
class KumanoFacesKakkazanTriggeredAbility extends DelayedTriggeredAbility {
public KumanoFacesKakkazanTriggeredAbility() {
super(null, Duration.EndOfTurn);
}
private KumanoFacesKakkazanTriggeredAbility(final KumanoFacesKakkazanTriggeredAbility ability) {
super(ability);
}
@Override
public KumanoFacesKakkazanTriggeredAbility copy() {
return new KumanoFacesKakkazanTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (this.isControlledBy(event.getPlayerId())) {
Spell spell = game.getSpell(event.getTargetId());
if (spell != null && spell.isCreature(game)) {
this.getEffects().clear();
this.getEffects().add(new KumanoFacesKakkazanCounterEffect(spell.getSourceId()));
return true;
}
}
return false;
}
@Override
public String getRule() {
return "When you cast your next creature spell this turn, that creature enters the battlefield with an additional +1/+1 counter on it.";
}
}
class KumanoFacesKakkazanCounterEffect extends ReplacementEffectImpl {
private final UUID spellCastId;
public KumanoFacesKakkazanCounterEffect(UUID spellCastId) {
super(Duration.EndOfTurn, Outcome.BoostCreature);
this.spellCastId = spellCastId;
}
private KumanoFacesKakkazanCounterEffect(final KumanoFacesKakkazanCounterEffect effect) {
super(effect);
this.spellCastId = effect.spellCastId;
}
@Override
public KumanoFacesKakkazanCounterEffect copy() {
return new KumanoFacesKakkazanCounterEffect(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 spellCastId.equals(event.getTargetId());
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
if (creature != null) {
creature.addCounters(CounterType.P1P1.createInstance(), source.getControllerId(), source, game, event.getAppliedEffects());
}
return false;
}
}

View file

@ -89,6 +89,7 @@ public final class KamigawaNeonDynasty extends ExpansionSet {
cards.add(new SetCardInfo("Enthusiastic Mechanaut", 218, Rarity.UNCOMMON, mage.cards.e.EnthusiasticMechanaut.class));
cards.add(new SetCardInfo("Era of Enlightenment", 11, Rarity.COMMON, mage.cards.e.EraOfEnlightenment.class));
cards.add(new SetCardInfo("Essence Capture", 52, Rarity.UNCOMMON, mage.cards.e.EssenceCapture.class));
cards.add(new SetCardInfo("Etching of Kumano", 152, Rarity.UNCOMMON, mage.cards.e.EtchingOfKumano.class));
cards.add(new SetCardInfo("Experimental Synthesizer", 138, Rarity.COMMON, mage.cards.e.ExperimentalSynthesizer.class));
cards.add(new SetCardInfo("Explosive Entry", 139, Rarity.COMMON, mage.cards.e.ExplosiveEntry.class));
cards.add(new SetCardInfo("Explosive Singularity", 140, Rarity.MYTHIC, mage.cards.e.ExplosiveSingularity.class));
@ -165,6 +166,7 @@ public final class KamigawaNeonDynasty extends ExpansionSet {
cards.add(new SetCardInfo("Kitsune Ace", 22, Rarity.COMMON, mage.cards.k.KitsuneAce.class));
cards.add(new SetCardInfo("Kodama of the West Tree", 199, Rarity.MYTHIC, mage.cards.k.KodamaOfTheWestTree.class));
cards.add(new SetCardInfo("Kotose, the Silent Spider", 351, Rarity.RARE, mage.cards.k.KotoseTheSilentSpider.class));
cards.add(new SetCardInfo("Kumano Faces Kakkazan", 152, Rarity.UNCOMMON, mage.cards.k.KumanoFacesKakkazan.class));
cards.add(new SetCardInfo("Kura, the Boundless Sky", 200, Rarity.MYTHIC, mage.cards.k.KuraTheBoundlessSky.class));
cards.add(new SetCardInfo("Kyodai, Soul of Kamigawa", 23, Rarity.RARE, mage.cards.k.KyodaiSoulOfKamigawa.class));
cards.add(new SetCardInfo("Leech Gauntlet", 106, Rarity.UNCOMMON, mage.cards.l.LeechGauntlet.class));

View file

@ -0,0 +1,45 @@
package mage.watchers.common;
import mage.MageObjectReference;
import mage.constants.WatcherScope;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.watchers.Watcher;
import java.util.HashSet;
/**
*
* @author weirddan455
*/
public class DamagedByControlledWatcher extends Watcher {
private final HashSet<MageObjectReference> damagedPermanents = new HashSet<>();
public DamagedByControlledWatcher() {
super(WatcherScope.PLAYER);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGED_PERMANENT) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent != null && permanent.isCreature(game)) {
if (controllerId != null && controllerId.equals(game.getControllerId(event.getSourceId()))) {
damagedPermanents.add(new MageObjectReference(event.getTargetId(), game));
}
}
}
}
@Override
public void reset() {
super.reset();
damagedPermanents.clear();
}
public boolean wasDamaged(Permanent permanent, Game game) {
return damagedPermanents.contains(new MageObjectReference(permanent, game));
}
}