forked from External/mage
[FIC] Implement G'raha Tia, Scion Reborn, rework DoIfCostPaid and "do only once" effects (#13660)
* rework effects with DoIfCostPaid and "do this only once each turn" * [FIC] Implement G'raha Tia, Scion Reborn * [FIC] Implement Emet Selch of the Third Seat * rework Emet-Selch * add test * add static methods to handle whether ability was used this turn
This commit is contained in:
parent
71c4be03fb
commit
40d24869a8
11 changed files with 361 additions and 50 deletions
|
|
@ -3,7 +3,9 @@ package mage.abilities;
|
|||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -97,8 +99,6 @@ public interface TriggeredAbility extends Ability {
|
|||
|
||||
boolean isOptional();
|
||||
|
||||
TriggeredAbility setOptional();
|
||||
|
||||
/**
|
||||
* Allow trigger to fire after source leave the battlefield (example: will use LKI on itself sacrifice)
|
||||
*/
|
||||
|
|
@ -131,4 +131,34 @@ public interface TriggeredAbility extends Ability {
|
|||
TriggeredAbility setTriggerPhrase(String triggerPhrase);
|
||||
|
||||
String getTriggerPhrase();
|
||||
|
||||
static String makeDidThisTurnString(Ability ability, Game game) {
|
||||
return CardUtil.getCardZoneString("lastTurnUsed" + ability.getOriginalId(), ability.getSourceId(), game);
|
||||
}
|
||||
|
||||
static void setDidThisTurn(Ability ability, Game game) {
|
||||
game.getState().setValue(makeDidThisTurnString(ability, game), game.getTurnNum());
|
||||
}
|
||||
|
||||
/**
|
||||
* For abilities which say "Do this only once each turn".
|
||||
* Most of the time this is handled automatically by calling setDoOnlyOnceEachTurn(true),
|
||||
* but sometimes the ability will need a way to clear whether it's been used this turn within an effect.
|
||||
*
|
||||
* @param ability
|
||||
* @param game
|
||||
*/
|
||||
static void clearDidThisTurn(Ability ability, Game game) {
|
||||
game.getState().removeValue(makeDidThisTurnString(ability, game));
|
||||
}
|
||||
|
||||
static boolean checkDidThisTurn(Ability ability, Game game) {
|
||||
return Optional
|
||||
.ofNullable(makeDidThisTurnString(ability, game))
|
||||
.map(game.getState()::getValue)
|
||||
.filter(Integer.class::isInstance)
|
||||
.map(Integer.class::cast)
|
||||
.filter(x -> x == game.getTurnNum())
|
||||
.isPresent();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,13 +156,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
|
||||
@Override
|
||||
public boolean checkUsedAlready(Game game) {
|
||||
if (!doOnlyOnceEachTurn) {
|
||||
return false;
|
||||
}
|
||||
Integer lastTurnUsed = (Integer) game.getState().getValue(
|
||||
CardUtil.getCardZoneString("lastTurnUsed" + getOriginalId(), sourceId, game)
|
||||
);
|
||||
return lastTurnUsed != null && lastTurnUsed == game.getTurnNum();
|
||||
return doOnlyOnceEachTurn && TriggeredAbility.checkDidThisTurn(this, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -209,7 +203,9 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
@Override
|
||||
public TriggeredAbility setDoOnlyOnceEachTurn(boolean doOnlyOnce) {
|
||||
this.doOnlyOnceEachTurn = doOnlyOnce;
|
||||
setOptional();
|
||||
if (CardUtil.castStream(this.getAllEffects(), DoIfCostPaid.class).noneMatch(DoIfCostPaid::isOptional)) {
|
||||
this.optional = true;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
@ -268,11 +264,9 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (doOnlyOnceEachTurn) {
|
||||
game.getState().setValue(CardUtil.getCardZoneString(
|
||||
"lastTurnUsed" + getOriginalId(), sourceId, game
|
||||
), game.getTurnNum());
|
||||
if (doOnlyOnceEachTurn) {
|
||||
TriggeredAbility.setDidThisTurn(this, game);
|
||||
}
|
||||
}
|
||||
//20091005 - 603.4
|
||||
if (!super.resolve(game)) {
|
||||
|
|
@ -387,6 +381,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
|
||||
private static boolean startsWithVerb(String ruleLow) {
|
||||
return ruleLow.startsWith("attach")
|
||||
|| ruleLow.startsWith("cast")
|
||||
|| ruleLow.startsWith("change")
|
||||
|| ruleLow.startsWith("counter")
|
||||
|| ruleLow.startsWith("create")
|
||||
|
|
@ -501,20 +496,6 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
return optional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriggeredAbility setOptional() {
|
||||
this.optional = true;
|
||||
|
||||
if (getEffects().stream().anyMatch(
|
||||
effect -> effect instanceof DoIfCostPaid && ((DoIfCostPaid) effect).isOptional())) {
|
||||
throw new IllegalArgumentException(
|
||||
"DoIfCostPaid effect must have only one optional settings, but it have two (trigger + DoIfCostPaid): "
|
||||
+ this.getClass().getSimpleName());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriggeredAbilityImpl setAbilityWord(AbilityWord abilityWord) {
|
||||
super.setAbilityWord(abilityWord);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,11 @@ public class AttacksWithCreaturesTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
public AttacksWithCreaturesTriggeredAbility(Zone zone, Effect effect, int minAttackers, FilterPermanent filter, boolean setTargetPointer) {
|
||||
super(zone, effect);
|
||||
this(zone, effect, minAttackers, filter, setTargetPointer, false);
|
||||
}
|
||||
|
||||
public AttacksWithCreaturesTriggeredAbility(Zone zone, Effect effect, int minAttackers, FilterPermanent filter, boolean setTargetPointer, boolean optional) {
|
||||
super(zone, effect, optional);
|
||||
this.filter = filter;
|
||||
this.minAttackers = minAttackers;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package mage.abilities.effects.common;
|
|||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.TriggeredAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
|
@ -110,6 +111,7 @@ public class DoIfCostPaid extends OneShotEffect {
|
|||
didPay = true;
|
||||
game.informPlayers(player.getLogName() + " paid for " + mageObject.getLogName() + " - " + message);
|
||||
applyEffects(game, source, executingEffects);
|
||||
TriggeredAbility.setDidThisTurn(source, game);
|
||||
player.resetStoredBookmark(game); // otherwise you can e.g. undo card drawn with Mentor of the Meek
|
||||
} else {
|
||||
// Paying cost was cancels so try to undo payment so far
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue