Keen-Eyed Curator - fixed not working boost effect (#13022)

This commit is contained in:
Oleg Agafonov 2024-10-24 22:18:29 +04:00
parent 14e14f5ba8
commit c265e640bb
2 changed files with 31 additions and 47 deletions

View file

@ -1,12 +1,14 @@
package mage.cards.k; package mage.cards.k;
import mage.MageInt; import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.Condition; import mage.abilities.condition.Condition;
import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.decorator.ConditionalContinuousEffect; import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
import mage.abilities.hint.Hint; import mage.abilities.hint.Hint;
@ -26,9 +28,6 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileTargetForSourceEffect;
import mage.constants.Outcome;
/** /**
* @author TheElk801 * @author TheElk801
@ -46,8 +45,8 @@ public final class KeenEyedCurator extends CardImpl {
// As long as there are four or more card types among cards exiled with Keen-Eyed Curator, it gets +4/+4 and has trample. // As long as there are four or more card types among cards exiled with Keen-Eyed Curator, it gets +4/+4 and has trample.
Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect( Ability ability = new SimpleStaticAbility(new ConditionalContinuousEffect(
new BoostSourceEffect(4, 4, Duration.WhileOnBattlefield), new BoostSourceEffect(4, 4, Duration.WhileOnBattlefield),
KeenEyedCuratorCondition.instance, "as long as there are four or " KeenEyedCuratorCondition.instance, "as long as there are four or " +
+ "more card types among cards exiled with {this}, it gets +4/+4" "more card types among cards exiled with {this}, it gets +4/+4"
)); ));
ability.addEffect(new ConditionalContinuousEffect( ability.addEffect(new ConditionalContinuousEffect(
new GainAbilitySourceEffect(TrampleAbility.getInstance()), new GainAbilitySourceEffect(TrampleAbility.getInstance()),
@ -56,7 +55,7 @@ public final class KeenEyedCurator extends CardImpl {
this.addAbility(ability.addHint(KeenEyedCuratorHint.instance)); this.addAbility(ability.addHint(KeenEyedCuratorHint.instance));
// {1}: Exile target card from a graveyard. // {1}: Exile target card from a graveyard.
ability = new SimpleActivatedAbility(new KeenEyedCuratorEffect(), new GenericManaCost(1)); ability = new SimpleActivatedAbility(new ExileTargetForSourceEffect(), new GenericManaCost(1));
ability.addTarget(new TargetCardInGraveyard()); ability.addTarget(new TargetCardInGraveyard());
this.addAbility(ability); this.addAbility(ability);
} }
@ -71,40 +70,17 @@ public final class KeenEyedCurator extends CardImpl {
} }
} }
class KeenEyedCuratorEffect extends OneShotEffect {
KeenEyedCuratorEffect() {
super(Outcome.Benefit);
staticText = "Exile target card from a graveyard";
}
private KeenEyedCuratorEffect(final KeenEyedCuratorEffect effect) {
super(effect);
}
@Override
public KeenEyedCuratorEffect copy() {
return new KeenEyedCuratorEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
// condition does not work well with passing source.getSourceObjectZoneChangeCounter(), so we store the exileId to the gamestate
ExileTargetForSourceEffect exileTarget = new ExileTargetForSourceEffect();
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter());
String keenEyedKey = source.getSourceObject(game).toString() + source.getSourceCardIfItStillExists(game).getZoneChangeCounter(game);
game.getState().setValue(keenEyedKey, exileId);
return exileTarget.apply(game, source);
}
}
enum KeenEyedCuratorCondition implements Condition { enum KeenEyedCuratorCondition implements Condition {
instance; instance;
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
String keenEyedKey = source.getSourceObject(game).toString() + source.getSourceCardIfItStillExists(game).getZoneChangeCounter(game); MageObject sourceObject = source.getSourceObject(game);
UUID exileId = (UUID) game.getState().getValue(keenEyedKey); if (sourceObject == null) {
return false;
}
// must use object's zcc cause static and activated abilities init in diff time with diff zcc (see #13022)
UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), sourceObject.getZoneChangeCounter(game));
ExileZone exileZone = game.getExile().getExileZone(exileId); ExileZone exileZone = game.getExile().getExileZone(exileId);
return exileZone != null && exileZone.getCards(game) return exileZone != null && exileZone.getCards(game)
.stream() .stream()
@ -120,27 +96,27 @@ enum KeenEyedCuratorHint implements Hint {
@Override @Override
public String getText(Game game, Ability ability) { public String getText(Game game, Ability ability) {
List<String> types = new ArrayList<>(); MageObject sourceObject = ability.getSourceObject(game);
String keenEyedKey = ability.getSourceObject(game).toString() + ability.getSourceCardIfItStillExists(game).getZoneChangeCounter(game); if (sourceObject == null) {
if (keenEyedKey == null) {
return "Card types exiled: 0";
}
UUID exileId = (UUID) game.getState().getValue(keenEyedKey);
if (exileId == null) {
return "Card types exiled: 0"; return "Card types exiled: 0";
} }
// must use object's zcc cause static and activated abilities init in diff time with diff zcc (see #13022)
UUID exileId = CardUtil.getExileZoneId(game, ability.getSourceId(), sourceObject.getZoneChangeCounter(game));
ExileZone exileZone = game.getExile().getExileZone(exileId); ExileZone exileZone = game.getExile().getExileZone(exileId);
if (exileZone != null) { if (exileZone == null) {
types = exileZone.getCards(game).stream() return "Card types exiled: 0";
}
List<String> types = exileZone.getCards(game).stream()
.map(card -> card.getCardType(game)) .map(card -> card.getCardType(game))
.flatMap(Collection::stream) .flatMap(Collection::stream)
.distinct() .distinct()
.map(CardType::toString) .map(CardType::toString)
.sorted() .sorted()
.collect(Collectors.toList()); .collect(Collectors.toList());
} String details = types.isEmpty() ? "" : " (" + String.join(", ", types) + ")";
return "Card types exiled: " + types.size() return "Card types exiled: " + types.size() + details;
+ (!types.isEmpty() ? " (" + String.join(", ", types) + ')' : "");
} }
@Override @Override

View file

@ -599,6 +599,14 @@ public final class CardUtil {
return getExileZoneId(getCardZoneString(SOURCE_EXILE_ZONE_TEXT, sourceId, game, previous), game); return getExileZoneId(getCardZoneString(SOURCE_EXILE_ZONE_TEXT, sourceId, game, previous), game);
} }
/**
* Find exiled zone due source object's zcc
* <p>
* Warning, carefully use it from static abilities, cause:
* - static abilities init from start of the game, e.g. zcc = 0
* - activated abilities init on usage, e.g. zcc = 123
* - if you need to share some data between diff type of effects then find actual object's zcc manually
*/
public static UUID getExileZoneId(Game game, Ability source) { public static UUID getExileZoneId(Game game, Ability source) {
return getExileZoneId(game, source, 0); return getExileZoneId(game, source, 0);
} }