[TLA] Implement Fire Nation Attacks

This commit is contained in:
theelk801 2025-08-12 17:50:23 -04:00
parent b552c850f4
commit e93d95d7a0
7 changed files with 180 additions and 7 deletions

View file

@ -0,0 +1,36 @@
package mage.cards.f;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.keyword.FlashbackAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.game.permanent.token.SoldierFirebendingToken;
import java.util.UUID;
/**
* @author TheElk801
*/
public final class FireNationAttacks extends CardImpl {
public FireNationAttacks(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{R}");
// Create two 2/2 red Soldier creature tokens with firebending 1.
this.getSpellAbility().addEffect(new CreateTokenEffect(new SoldierFirebendingToken(), 2));
// Flashback {8}{R}
this.addAbility(new FlashbackAbility(this, new ManaCostsImpl<>("{8}{R}")));
}
private FireNationAttacks(final FireNationAttacks card) {
super(card);
}
@Override
public FireNationAttacks copy() {
return new FireNationAttacks(this);
}
}

View file

@ -23,6 +23,7 @@ public final class AvatarTheLastAirbender extends ExpansionSet {
cards.add(new SetCardInfo("Avatar Enthusiasts", 11, Rarity.COMMON, mage.cards.a.AvatarEnthusiasts.class)); cards.add(new SetCardInfo("Avatar Enthusiasts", 11, Rarity.COMMON, mage.cards.a.AvatarEnthusiasts.class));
cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class)); cards.add(new SetCardInfo("Earthbending Lesson", 176, Rarity.COMMON, mage.cards.e.EarthbendingLesson.class));
cards.add(new SetCardInfo("Fire Nation Attacks", 133, Rarity.UNCOMMON, mage.cards.f.FireNationAttacks.class));
cards.add(new SetCardInfo("Katara, the Fearless", 230, Rarity.RARE, mage.cards.k.KataraTheFearless.class)); cards.add(new SetCardInfo("Katara, the Fearless", 230, Rarity.RARE, mage.cards.k.KataraTheFearless.class));
cards.add(new SetCardInfo("Sokka's Haiku", 71, Rarity.UNCOMMON, mage.cards.s.SokkasHaiku.class)); cards.add(new SetCardInfo("Sokka's Haiku", 71, Rarity.UNCOMMON, mage.cards.s.SokkasHaiku.class));
cards.add(new SetCardInfo("Southern Air Temple", 36, Rarity.UNCOMMON, mage.cards.s.SouthernAirTemple.class)); cards.add(new SetCardInfo("Southern Air Temple", 36, Rarity.UNCOMMON, mage.cards.s.SouthernAirTemple.class));

View file

@ -0,0 +1,91 @@
package mage.abilities.keyword;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;
import java.util.Collections;
/**
* @author TheElk801
*/
public class FirebendingAbility extends AttacksTriggeredAbility {
private final DynamicValue amount;
public FirebendingAbility(int amount) {
this(StaticValue.get(amount));
}
public FirebendingAbility(DynamicValue amount) {
super(new FirebendingAbilityEffect(amount));
this.amount = amount;
}
private FirebendingAbility(final FirebendingAbility ability) {
super(ability);
this.amount = ability.amount;
}
@Override
public FirebendingAbility copy() {
return new FirebendingAbility(this);
}
@Override
public String getRule() {
if (amount instanceof StaticValue) {
return "firebending " + amount +
" <i>(Whenever this creature attacks, add " +
String.join("", Collections.nCopies(((StaticValue) amount).getValue(), "{R}")) +
". This mana lasts until end of combat.)</i>";
}
return "firebending X, where X is " + amount.getMessage() +
". <i>(Whenever this creature attacks, add X {R}. This mana lasts until end of combat.)</i>";
}
}
class FirebendingAbilityEffect extends OneShotEffect {
private final DynamicValue amount;
FirebendingAbilityEffect(DynamicValue amount) {
super(Outcome.Benefit);
this.amount = amount;
}
private FirebendingAbilityEffect(final FirebendingAbilityEffect effect) {
super(effect);
this.amount = effect.amount;
}
@Override
public FirebendingAbilityEffect copy() {
return new FirebendingAbilityEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
int amount = Math.max(this.amount.calculate(game, source, this), 0);
if (amount > 0) {
player.getManaPool().addMana(Mana.RedMana(amount), game, source, Duration.EndOfCombat);
}
game.fireEvent(GameEvent.getEvent(
GameEvent.EventType.FIREBENDED, source.getSourceId(),
source, source.getControllerId(), amount
));
return true;
}
}

View file

@ -696,6 +696,7 @@ public class GameEvent implements Serializable {
*/ */
PAY_SACRIFICE_COST, PAY_SACRIFICE_COST,
EARTHBENDED, EARTHBENDED,
FIREBENDED,
// custom events - must store some unique data to track // custom events - must store some unique data to track
CUSTOM_EVENT; CUSTOM_EVENT;

View file

@ -0,0 +1,30 @@
package mage.game.permanent.token;
import mage.MageInt;
import mage.abilities.keyword.FirebendingAbility;
import mage.constants.CardType;
import mage.constants.SubType;
/**
* @author TheElk801
*/
public final class SoldierFirebendingToken extends TokenImpl {
public SoldierFirebendingToken() {
super("Soldier Token", "2/2 red Soldier creature token with firebending 1");
cardType.add(CardType.CREATURE);
color.setRed(true);
subtype.add(SubType.SOLDIER);
power = new MageInt(2);
toughness = new MageInt(2);
this.addAbility(new FirebendingAbility(1));
}
private SoldierFirebendingToken(final SoldierFirebendingToken token) {
super(token);
}
public SoldierFirebendingToken copy() {
return new SoldierFirebendingToken(this);
}
}

View file

@ -9,6 +9,7 @@ import mage.abilities.costs.Cost;
import mage.abilities.effects.mana.ManaEffect; import mage.abilities.effects.mana.ManaEffect;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.ManaType; import mage.constants.ManaType;
import mage.constants.PhaseStep;
import mage.constants.TurnPhase; import mage.constants.TurnPhase;
import mage.filter.Filter; import mage.filter.Filter;
import mage.filter.FilterMana; import mage.filter.FilterMana;
@ -302,10 +303,18 @@ public class ManaPool implements Serializable {
} }
private int emptyItem(ManaPoolItem item, Emptiable toEmpty, Game game, ManaType manaType) { private int emptyItem(ManaPoolItem item, Emptiable toEmpty, Game game, ManaType manaType) {
if (item.getDuration() == Duration.EndOfTurn switch (item.getDuration()) {
&& game.getTurnPhaseType() != TurnPhase.END) { case EndOfTurn:
if (game.getTurnPhaseType() != TurnPhase.END) {
return 0; return 0;
} }
break;
case EndOfCombat:
if (game.getTurnPhaseType() != TurnPhase.COMBAT
|| game.getTurnStepType() != PhaseStep.END_COMBAT) {
return 0;
}
}
if (manaBecomesBlack) { if (manaBecomesBlack) {
int amount = toEmpty.get(manaType); int amount = toEmpty.get(manaType);
toEmpty.clear(manaType); toEmpty.clear(manaType);
@ -366,6 +375,10 @@ public class ManaPool implements Serializable {
} }
public void addMana(Mana manaToAdd, Game game, Ability source, boolean dontLoseUntilEOT) { public void addMana(Mana manaToAdd, Game game, Ability source, boolean dontLoseUntilEOT) {
addMana(manaToAdd, game, source, dontLoseUntilEOT ? Duration.EndOfTurn : null);
}
public void addMana(Mana manaToAdd, Game game, Ability source, Duration duration) {
if (manaToAdd != null) { if (manaToAdd != null) {
Mana mana = manaToAdd.copy(); Mana mana = manaToAdd.copy();
if (!game.replaceEvent(new ManaEvent(EventType.ADD_MANA, source.getId(), source, playerId, mana))) { if (!game.replaceEvent(new ManaEvent(EventType.ADD_MANA, source.getId(), source, playerId, mana))) {
@ -376,8 +389,8 @@ public class ManaPool implements Serializable {
source.getSourceObject(game), source.getSourceObject(game),
conditionalMana.getManaProducerOriginalId() != null ? conditionalMana.getManaProducerOriginalId() : source.getOriginalId() conditionalMana.getManaProducerOriginalId() != null ? conditionalMana.getManaProducerOriginalId() : source.getOriginalId()
); );
if (dontLoseUntilEOT) { if (duration != null) {
item.setDuration(Duration.EndOfTurn); item.setDuration(duration);
} }
this.manaItems.add(item); this.manaItems.add(item);
} else { } else {
@ -392,8 +405,8 @@ public class ManaPool implements Serializable {
source.getOriginalId(), source.getOriginalId(),
mana.getFlag() mana.getFlag()
); );
if (dontLoseUntilEOT) { if (duration != null) {
item.setDuration(Duration.EndOfTurn); item.setDuration(duration);
} }
this.manaItems.add(item); this.manaItems.add(item);
} }

View file

@ -52,6 +52,7 @@ Exploit|new|
Extort|new| Extort|new|
Fabricate|number| Fabricate|number|
Fear|instance| Fear|instance|
Firebending|number|
First strike|instance| First strike|instance|
Flanking|new| Flanking|new|
Flash|instance| Flash|instance|