implement [BLB] Dragonhawk, Festival of Embers, Jackdaw Savior, Infamous Cruelclaw (#12906)

* [BLB] Dragonhawk, Fate's Tempest

* [BLB] Festival of Embers

* [BLB] Jackdaw Savior + test

* [BLB] The Infamous Cruelclaw

* Dragonhawk changes

* Create generic GraveyardFromAnywhereExileReplacementEffect

* Hide Cruelclaw Menace reminder text

* fix style errors
This commit is contained in:
ssk97 2024-10-12 11:07:52 -07:00 committed by GitHub
parent 9fd3f91388
commit be745cb096
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 675 additions and 443 deletions

View file

@ -56,19 +56,12 @@ public class DiesThisOrAnotherTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (zEvent.isDiesEvent()) {
if (zEvent.getTarget() != null) {
if (!applyFilterOnSource && zEvent.getTarget().getId().equals(this.getSourceId())) {
// TODO: remove this workaround for Basri's Lieutenant
return true;
} else {
if (filter.match(zEvent.getTarget(), getControllerId(), this, game)) {
return true;
}
}
}
if (!zEvent.isDiesEvent() || zEvent.getTarget() == null) {
return false;
}
return false;
// TODO: remove applyFilterOnSource workaround for Basri's Lieutenant
return ((!applyFilterOnSource && zEvent.getTarget().getId().equals(this.getSourceId()))
|| filter.match(zEvent.getTarget(), getControllerId(), this, game));
}
@Override

View file

@ -32,7 +32,7 @@ public class ExileTopXMayPlayUntilEffect extends OneShotEffect {
makeText(amount.toString().equals("1") ? "that card" : "those cards", duration == Duration.EndOfTurn);
}
private ExileTopXMayPlayUntilEffect(final ExileTopXMayPlayUntilEffect effect) {
protected ExileTopXMayPlayUntilEffect(final ExileTopXMayPlayUntilEffect effect) {
super(effect);
this.amount = effect.amount.copy();
this.duration = effect.duration;
@ -60,10 +60,15 @@ public class ExileTopXMayPlayUntilEffect extends OneShotEffect {
if (!cards.isEmpty()) {
game.addEffect(new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, duration)
.setTargetPointer(new FixedTargets(cards, game)), source);
effectCards(game, source, cards);
}
return true;
}
protected void effectCards(Game game, Ability source, Set<Card> cards) {
//Do nothing, used for derived classes
}
/**
* [Until end of turn, ] you may play [refCardText] [this turn]
*/
@ -76,7 +81,11 @@ public class ExileTopXMayPlayUntilEffect extends OneShotEffect {
String text = "exile the top ";
boolean singular = amount.toString().equals("1");
text += singular ? "card" : CardUtil.numberToText(amount.toString()) + " cards";
text += " of your library. ";
if (amount.toString().equals("X")) {
text += " of your library, where X is " + amount.getMessage() + ". ";
} else {
text += " of your library. ";
}
if (durationRuleAtEnd) {
text += "You may play " + refCardText + ' ' + (duration == Duration.EndOfTurn ? "this turn" : duration.toString());
} else {

View file

@ -0,0 +1,92 @@
package mage.abilities.effects.common.replacement;
import mage.abilities.Ability;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.Card;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.util.CardUtil;
/**
* @author notgreat
*/
public class GraveyardFromAnywhereExileReplacementEffect extends ReplacementEffectImpl {
private final FilterCard filter;
private final boolean onlyYou;
private final boolean tokens;
public GraveyardFromAnywhereExileReplacementEffect(FilterCard filter, boolean onlyYou) {
this(Duration.WhileOnBattlefield, filter, onlyYou, false);
}
public GraveyardFromAnywhereExileReplacementEffect(boolean onlyYou, boolean tokens) {
this(Duration.WhileOnBattlefield, StaticFilters.FILTER_CARD_A, onlyYou, tokens);
}
public GraveyardFromAnywhereExileReplacementEffect(Duration duration) {
this(duration, StaticFilters.FILTER_CARD_A, true, false);
}
protected GraveyardFromAnywhereExileReplacementEffect(Duration duration, FilterCard filter, boolean onlyYou, boolean tokens) {
super(duration, Outcome.Exile);
this.filter = filter;
this.onlyYou = onlyYou;
this.tokens = tokens;
this.setText();
}
private GraveyardFromAnywhereExileReplacementEffect(final GraveyardFromAnywhereExileReplacementEffect effect) {
super(effect);
this.filter = effect.filter;
this.onlyYou = effect.onlyYou;
this.tokens = effect.tokens;
}
private void setText() {
this.staticText = "If " + CardUtil.addArticle(filter.getMessage()) + (tokens ? " or token" : "")
+ " would be put into " + (onlyYou ? "your" : "a") + " graveyard from anywhere"
+ (duration == Duration.EndOfTurn ? " this turn" : "") + ", exile "
+ ((filter == StaticFilters.FILTER_CARD_A && !tokens) ? "that card" : "it") + " instead";
}
@Override
public GraveyardFromAnywhereExileReplacementEffect copy() {
return new GraveyardFromAnywhereExileReplacementEffect(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 zEvent = (ZoneChangeEvent) event;
if (zEvent.getToZone() != Zone.GRAVEYARD) {
return false;
}
Card card = game.getCard(event.getTargetId());
if (card != null && (!onlyYou || card.isOwnedBy(source.getControllerId())) && (filter == null || filter.match(card, game))) {
return true;
}
Permanent token = game.getPermanent(event.getTargetId());
if (tokens && (token instanceof PermanentToken && (!onlyYou || token.isOwnedBy(source.getControllerId())))) {
return true;
}
return false;
}
}