MagicStack: ThisTurnActivated

This commit is contained in:
Hans Mackowiak
2024-04-13 19:11:08 +02:00
parent abba1c7230
commit d6422688b8
11 changed files with 53 additions and 69 deletions

View File

@@ -2269,14 +2269,6 @@ public class AbilityUtils {
return doXMath(player.getOpponentsGreatestLifeTotal(), expr, c, ctb);
}
if (sq[0].equals("YouCycledThisTurn")) {
return doXMath(player.getCycledThisTurn(), expr, c, ctb);
}
if (sq[0].equals("YouEquippedThisTurn")) {
return doXMath(player.getEquippedThisTurn(), expr, c, ctb);
}
if (sq[0].equals("YouDrewThisTurn")) {
return doXMath(player.getNumDrawnThisTurn(), expr, c, ctb);
}
@@ -2727,6 +2719,12 @@ public class AbilityUtils {
someCards = CardUtil.getLastTurnCast(validFilter, c, ctb, player);
}
}
if (sq[0].startsWith("ThisTurnActivated")) {
final String[] workingCopy = paidparts[0].split("_");
final String validFilter = workingCopy[1];
// use objectXCount ?
return CardUtil.getThisTurnActivated(validFilter, c, ctb, player).size();
}
// Count$ThisTurnEntered <ZoneDestination> [from <ZoneOrigin>] <Valid>
if (sq[0].startsWith("ThisTurnEntered") || sq[0].startsWith("LastTurnEntered")) {

View File

@@ -3679,7 +3679,6 @@ public class CardFactoryUtil {
sb.append("| SpellDescription$ (").append(inst.getReminderText()).append(")");
SpellAbility sa = AbilityFactory.getAbility(sb.toString(), card);
sa.setAlternativeCost(AlternativeCost.Cycling);
sa.setIntrinsic(intrinsic);
inst.addSpellAbility(sa);
} else if (keyword.startsWith("TypeCycling")) {
@@ -3704,7 +3703,6 @@ public class CardFactoryUtil {
sb.append(" | SpellDescription$ (").append(inst.getReminderText()).append(")");
SpellAbility sa = AbilityFactory.getAbility(sb.toString(), card);
sa.setAlternativeCost(AlternativeCost.Cycling);
sa.setIntrinsic(intrinsic);
inst.addSpellAbility(sa);
}

View File

@@ -21,6 +21,7 @@ import java.util.List;
import java.util.Set;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -36,6 +37,7 @@ import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityPredicates;
import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType;
import forge.util.TextUtil;
@@ -138,6 +140,10 @@ public final class CardUtil {
return CardLists.getValidCardsAsList(src.getGame().getStack().getSpellsCastLastTurn(), valid, controller, src, ctb);
}
public static List<SpellAbility> getThisTurnActivated(final String valid, final Card src, final CardTraitBase ctb, final Player controller) {
return Lists.newArrayList(Iterables.filter(src.getGame().getStack().getAbilityActivatedThisTurn(), SpellAbilityPredicates.isValid(valid.split(","), controller, src, ctb)));
}
public static CardCollection getRadiance(final SpellAbility sa) {
SpellAbility targetSA = sa.getSATargetingCard();
if (targetSA == null || !targetSA.usesTargeting() || !targetSA.hasParam("Radiance")) {

View File

@@ -92,8 +92,6 @@ public class Player extends GameEntity implements Comparable<Player> {
private int landsPlayedLastTurn;
private int investigatedThisTurn;
private int surveilThisTurn;
private int cycledThisTurn;
private int equippedThisTurn;
private int lifeLostThisTurn;
private int lifeLostLastTurn;
private int lifeGainedThisTurn;
@@ -2482,8 +2480,6 @@ public class Player extends GameEntity implements Comparable<Player> {
resetLandsPlayedThisTurn();
resetInvestigatedThisTurn();
resetSurveilThisTurn();
resetCycledThisTurn();
resetEquippedThisTurn();
resetDiscardedThisTurn();
resetSacrificedThisTurn();
resetVenturedThisTurn();
@@ -2969,23 +2965,23 @@ public class Player extends GameEntity implements Comparable<Player> {
public boolean allCardsUniqueManaSymbols() {
for (final Card c : getCardsIn(ZoneType.Library)) {
Set<CardStateName> cardStateNames = c.isSplitCard() ? EnumSet.of(CardStateName.LeftSplit, CardStateName.RightSplit) : EnumSet.of(CardStateName.Original);
Set<ManaCostShard> coloredManaSymbols = new HashSet<>();
Set<Integer> genericManaSymbols = new HashSet<>();
Set<ManaCostShard> coloredManaSymbols = new HashSet<>();
Set<Integer> genericManaSymbols = new HashSet<>();
for (final CardStateName cardStateName : cardStateNames) {
final ManaCost manaCost = c.getState(cardStateName).getManaCost();
for (final ManaCostShard manaSymbol : manaCost) {
if (!coloredManaSymbols.add(manaSymbol)) {
return false;
}
}
int generic = manaCost.getGenericCost();
if (generic > 0 || manaCost.getCMC() == 0) {
if (!genericManaSymbols.add(Integer.valueOf(generic))) {
return false;
}
}
}
for (final CardStateName cardStateName : cardStateNames) {
final ManaCost manaCost = c.getState(cardStateName).getManaCost();
for (final ManaCostShard manaSymbol : manaCost) {
if (!coloredManaSymbols.add(manaSymbol)) {
return false;
}
}
int generic = manaCost.getGenericCost();
if (generic > 0 || manaCost.getCMC() == 0) {
if (!genericManaSymbols.add(Integer.valueOf(generic))) {
return false;
}
}
}
}
return true;
}
@@ -3028,9 +3024,9 @@ public class Player extends GameEntity implements Comparable<Player> {
legalCompanions.add(c);
}
} else if (specialRules.equals("UniqueManaSymbols")) {
if (this.allCardsUniqueManaSymbols()) {
legalCompanions.add(c);
}
if (this.allCardsUniqueManaSymbols()) {
legalCompanions.add(c);
}
} else if (specialRules.equals("DeckSizePlus20")) {
// +20 deck size to min deck size
if (deckSize >= minSize + 20) {
@@ -3114,7 +3110,7 @@ public class Player extends GameEntity implements Comparable<Player> {
else if (game.getRules().hasAppliedVariant(GameType.Oathbreaker)) {
moved += " | Destination$ Graveyard,Exile,Hand,Library | Description$ If a commander would be exiled or put into hand, graveyard, or library from anywhere, that player may put it into the command zone instead.";
} else {
// rule 903.9b
// rule 903.9b
moved += " | Destination$ Hand,Library | Description$ If a commander would be put into its owner's hand or library from anywhere, its owner may put it into the command zone instead.";
}
ReplacementEffect re = ReplacementHandler.parseReplacement(moved, eff, true);
@@ -3154,7 +3150,7 @@ public class Player extends GameEntity implements Comparable<Player> {
SpellAbility planarRoll = AbilityFactory.getAbility(specialA, eff);
planarRoll.setSVar("X", "Count$PlanarDiceSpecialActionThisTurn");
eff.addSpellAbility(planarRoll);
eff.updateStateForView();
com.add(eff);
this.updateZoneForView(com);
@@ -3691,33 +3687,13 @@ public class Player extends GameEntity implements Comparable<Player> {
}
public void addCycled(SpellAbility sp) {
cycledThisTurn++;
Map<AbilityKey, Object> cycleParams = AbilityKey.mapFromCard(CardCopyService.getLKICopy(game.getCardState(sp.getHostCard())));
cycleParams.put(AbilityKey.Cause, sp);
cycleParams.put(AbilityKey.Player, this);
cycleParams.put(AbilityKey.FirstTime, cycledThisTurn == 1);
cycleParams.put(AbilityKey.FirstTime, CardUtil.getThisTurnActivated("Activated.Cycling+YouCtrl", sp.getHostCard(), sp, this).size() == 1);
game.getTriggerHandler().runTrigger(TriggerType.Cycled, cycleParams, false);
}
public int getCycledThisTurn() {
return cycledThisTurn;
}
public void resetCycledThisTurn() {
cycledThisTurn = 0;
}
public void addEquipped() { equippedThisTurn++; }
public int getEquippedThisTurn() {
return equippedThisTurn;
}
public void resetEquippedThisTurn() {
equippedThisTurn = 0;
}
public boolean hasUrzaLands() {
final CardCollectionView landsControlled = getCardsIn(ZoneType.Battlefield);
return Iterables.any(landsControlled, Predicates.and(CardPredicates.isType("Urza's"), CardPredicates.isType("Mine")))

View File

@@ -4,7 +4,6 @@ public enum AlternativeCost {
Awaken,
Bestow,
Blitz,
Cycling, // ActivatedAbility
Dash,
Disturb,
Emerge,

View File

@@ -560,7 +560,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
}
public boolean isCycling() {
return isAlternativeCost(AlternativeCost.Cycling);
return isKeyword(Keyword.CYCLING) || isKeyword(Keyword.TYPECYCLING);
}
public boolean isBackup() {

View File

@@ -85,6 +85,8 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
private final List<Card> thisTurnCast = Lists.newArrayList();
private List<Card> lastTurnCast = Lists.newArrayList();
private final List<SpellAbility> abilitiesActivatedThisTurn = Lists.newArrayList();
private Card curResolvingCard = null;
private final Map<String, List<GameCommand>> commandList = Maps.newHashMap();
@@ -263,7 +265,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
if (sp.isManaAbility()) { // Mana Abilities go straight through
if (!sp.isCopied() && !sp.isTrigger()) {
// Copied abilities aren't activated, so they shouldn't change these values
source.addAbilityActivated(sp);
addAbilityActivatedThisTurn(sp, source);
}
Map<AbilityKey, Object> runParams = AbilityKey.mapFromPlayer(source.getController());
runParams.put(AbilityKey.Cost, sp.getPayCosts());
@@ -336,7 +338,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
}
if (sp.isAbility() && !sp.isCopied() && !sp.isTrigger()) {
source.addAbilityActivated(sp);
addAbilityActivatedThisTurn(sp, source);
}
if (sp instanceof AbilityStatic || (sp.isTrigger() && sp.getTrigger().getOverridingAbility() instanceof AbilityStatic)) {
@@ -390,11 +392,6 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
activator.addCycled(sp);
}
// Log number of Equips
if (sp.isEquip()) {
activator.addEquipped();
}
if (sp.hasParam("Crew")) {
// Trigger crews!
runParams.put(AbilityKey.Vehicle, sp.getHostCard());
@@ -894,6 +891,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
public final void onNextTurn() {
game.getStackZone().resetCardsAddedThisTurn();
this.abilitiesActivatedThisTurn.clear();
if (thisTurnCast.isEmpty()) {
lastTurnCast = Lists.newArrayList();
return;
@@ -907,6 +905,15 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
return lastTurnCast;
}
public void addAbilityActivatedThisTurn(SpellAbility sa, final Card source) {
source.addAbilityActivated(sa);
abilitiesActivatedThisTurn.add(sa.copy(CardCopyService.getLKICopy(source), true));
}
public List<SpellAbility> getAbilityActivatedThisTurn() {
return abilitiesActivatedThisTurn;
}
public final void addCastCommand(final String valid, final GameCommand c) {
if (commandList.containsKey(valid)) {
commandList.get(valid).add(0, c);