[TLA] Implement The Last Agni Kai

This commit is contained in:
theelk801 2025-11-19 13:19:11 -05:00
parent 80d58a35f7
commit 4772658527
7 changed files with 141 additions and 35 deletions

View file

@ -92,7 +92,7 @@ class EzurisPredationEffect extends OneShotEffect {
Permanent opponentCreature = creaturesOfOpponents.iterator().next();
creaturesOfOpponents.remove(opponentCreature);
// can be multiple tokens, so must be used custom BATCH_FIGHT event
token.fight(opponentCreature, source, game, false);
token.fightWithExcess(opponentCreature, source, game, false);
morSet.add(new MageObjectReference(token, game));
morSet.add(new MageObjectReference(opponentCreature, game));
game.informPlayers(token.getLogName() + " fights " + opponentCreature.getLogName());

View file

@ -4,50 +4,40 @@ import mage.abilities.Ability;
import mage.abilities.common.delayed.ReflexiveTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DestroyTargetEffect;
import mage.abilities.effects.common.FightTargetsEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterArtifactPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.TargetPermanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author Jmlundeen
*/
public final class RhinosRampage extends CardImpl {
private static final FilterPermanent filter = new FilterCreaturePermanent("creature an opponent controls");
static {
filter.add(TargetController.OPPONENT.getControllerPredicate());
}
public RhinosRampage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{R/G}");
// Target creature you control gets +1/+0 until end of turn. It fights target creature an opponent controls. When excess damage is dealt to the creature an opponent controls this way, destroy up to one target noncreature artifact with mana value 3 or less.
this.getSpellAbility().addEffect(new BoostTargetEffect(1, 0));
this.getSpellAbility().addEffect(new FightTargetsEffect()
.setText("It fights target creature an opponent controls"));
this.getSpellAbility().addEffect(new RhinosRampageEffect());
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addTarget(new TargetPermanent(filter));
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent());
}
private RhinosRampage(final RhinosRampage card) {
@ -62,10 +52,17 @@ public final class RhinosRampage extends CardImpl {
class RhinosRampageEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterArtifactPermanent("noncreature artifact with mana value 3 or less");
static {
filter.add(Predicates.not(CardType.CREATURE.getPredicate()));
filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 3));
}
RhinosRampageEffect() {
super(Outcome.BoostCreature);
staticText = "When excess damage is dealt to the creature an opponent controls this way, destroy up to one target noncreature " +
"artifact with mana value 3 or less";
staticText = "it fights target creature an opponent controls. When excess damage is dealt to the creature " +
"an opponent controls this way, destroy up to one target noncreature artifact with mana value 3 or less.";
}
protected RhinosRampageEffect(final RhinosRampageEffect effect) {
@ -79,14 +76,20 @@ class RhinosRampageEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanentOrLKIBattlefield(source.getTargets().get(1).getFirstTarget());
if (permanent == null || permanent.getDamage() <= permanent.getToughness().getBaseValue()) {
List<Permanent> permanents = this
.getTargetPointer()
.getTargets(game, source)
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (permanents.size() < 2) {
return false;
}
FilterPermanent filter = new FilterArtifactPermanent("noncreature artifact with mana value 3 or less");
filter.add(Predicates.not(CardType.CREATURE.getPredicate()));
filter.add(new ManaValuePredicate(ComparisonType.OR_LESS, 3));
int excess = permanents.get(0).fightWithExcess(permanents.get(1), source, game, true);
if (excess < 1) {
return true;
}
ReflexiveTriggeredAbility ability = new ReflexiveTriggeredAbility(new DestroyTargetEffect(), false);
ability.addTarget(new TargetPermanent(0, 1, filter));
game.fireReflexiveTriggeredAbility(ability, source);

View file

@ -0,0 +1,92 @@
package mage.cards.t;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.YouDontLoseManaEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.ManaType;
import mage.constants.Outcome;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.target.common.TargetOpponentsCreaturePermanent;
import mage.target.targetpointer.EachTargetPointer;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author TheElk801
*/
public final class TheLastAgniKai extends CardImpl {
public TheLastAgniKai(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
// Target creature you control fights target creature an opponent controls. If the creature the opponent controls is dealt excess damage this way, add that much {R}.
this.getSpellAbility().addEffect(new TheLastAgniKaiEffect());
this.getSpellAbility().addTarget(new TargetControlledCreaturePermanent());
this.getSpellAbility().addTarget(new TargetOpponentsCreaturePermanent());
// Until end of turn, you don't lose unspent red mana as steps and phases end.
this.getSpellAbility().addEffect(new YouDontLoseManaEffect(Duration.EndOfTurn, ManaType.RED).concatBy("<br>"));
}
private TheLastAgniKai(final TheLastAgniKai card) {
super(card);
}
@Override
public TheLastAgniKai copy() {
return new TheLastAgniKai(this);
}
}
class TheLastAgniKaiEffect extends OneShotEffect {
TheLastAgniKaiEffect() {
super(Outcome.Benefit);
staticText = "target creature you control fights target creature an opponent controls. " +
"If the creature the opponent controls is dealt excess damage this way, add that much {R}";
this.setTargetPointer(new EachTargetPointer());
}
private TheLastAgniKaiEffect(final TheLastAgniKaiEffect effect) {
super(effect);
}
@Override
public TheLastAgniKaiEffect copy() {
return new TheLastAgniKaiEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
List<Permanent> permanents = this
.getTargetPointer()
.getTargets(game, source)
.stream()
.map(game::getPermanent)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (permanents.size() < 2) {
return false;
}
int excess = permanents.get(0).fightWithExcess(permanents.get(1), source, game, true);
if (excess > 0) {
Optional.ofNullable(source)
.map(Controllable::getControllerId)
.map(game::getPlayer)
.ifPresent(player -> player.getManaPool().addMana(Mana.RedMana(excess), game, source));
}
return true;
}
}

View file

@ -347,6 +347,8 @@ public final class AvatarTheLastAirbender extends ExpansionSet {
cards.add(new SetCardInfo("The Earth King", 344, Rarity.RARE, mage.cards.t.TheEarthKing.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Fire Nation Drill", 321, Rarity.RARE, mage.cards.t.TheFireNationDrill.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Fire Nation Drill", 98, Rarity.RARE, mage.cards.t.TheFireNationDrill.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Last Agni Kai", 144, Rarity.RARE, mage.cards.t.TheLastAgniKai.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Last Agni Kai", 314, Rarity.RARE, mage.cards.t.TheLastAgniKai.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Legend of Kuruk", 355, Rarity.MYTHIC, mage.cards.t.TheLegendOfKuruk.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Legend of Kuruk", 61, Rarity.MYTHIC, mage.cards.t.TheLegendOfKuruk.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("The Legend of Kyoshi", 186, Rarity.MYTHIC, mage.cards.t.TheLegendOfKyoshi.class, NON_FULL_USE_VARIOUS));

View file

@ -14,8 +14,13 @@ public class YouDontLoseManaEffect extends ContinuousEffectImpl {
private final ManaType manaType;
public YouDontLoseManaEffect(ManaType manaType) {
super(Duration.WhileOnBattlefield, Layer.RulesEffects, SubLayer.NA, Outcome.Detriment);
staticText = "you don't lose unspent " + manaType + " mana as steps and phases end";
this(Duration.WhileOnBattlefield, manaType);
}
public YouDontLoseManaEffect(Duration duration, ManaType manaType) {
super(duration, Layer.RulesEffects, SubLayer.NA, Outcome.Detriment);
staticText = (duration == Duration.EndOfTurn ? "until end of turn, " : "") +
"you don't lose unspent " + manaType + " mana as steps and phases end";
this.manaType = manaType;
}

View file

@ -223,7 +223,10 @@ public interface Permanent extends Card, Controllable {
boolean fight(Permanent fightTarget, Ability source, Game game);
boolean fight(Permanent fightTarget, Ability source, Game game, boolean batchTrigger);
/**
* Resolves a fight and returns the amount of excess damage dealt to fightTarget
*/
int fightWithExcess(Permanent fightTarget, Ability source, Game game, boolean batchTrigger);
boolean entersBattlefield(Ability source, Game game, Zone fromZone, boolean fireEvent);

View file

@ -2024,16 +2024,17 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
@Override
public boolean fight(Permanent fightTarget, Ability source, Game game) {
return this.fight(fightTarget, source, game, true);
this.fightWithExcess(fightTarget, source, game, true);
return true;
}
@Override
public boolean fight(Permanent fightTarget, Ability source, Game game, boolean batchTrigger) {
public int fightWithExcess(Permanent fightTarget, Ability source, Game game, boolean batchTrigger) {
// double fight events for each creature
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, fightTarget.getId(), source, source.getControllerId()));
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.FIGHTED_PERMANENT, getId(), source, source.getControllerId()));
damage(fightTarget.getPower().getValue(), fightTarget.getId(), source, game);
fightTarget.damage(getPower().getValue(), getId(), source, game);
int excess = fightTarget.damageWithExcess(getPower().getValue(), getId(), source, game);
if (batchTrigger) {
Set<MageObjectReference> morSet = new HashSet<>();
@ -2044,7 +2045,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.BATCH_FIGHT, getId(), source, source.getControllerId(), data, 0));
}
return true;
return excess;
}
@Override