Update getDefinedCards for how it get Valid* cards so the syntax is consistent with other Valid script. Also remove the hacky way to set Effect as mutable for Raging River and Plague of Vermin

This commit is contained in:
Hans Mackowiak
2021-07-18 09:06:47 +00:00
committed by Alumi
parent 52160c9e60
commit e753d45b42
28 changed files with 111 additions and 106 deletions

View File

@@ -229,12 +229,12 @@ public class GameCopier {
private static final boolean USE_FROM_PAPER_CARD = true;
private Card createCardCopy(Game newGame, Player newOwner, Card c) {
if (c.isToken() && !c.isEmblem()) {
if (c.isToken() && !c.isImmutable()) {
Card result = new TokenInfo(c).makeOneToken(newOwner);
CardFactory.copyCopiableCharacteristics(c, result);
return result;
}
if (USE_FROM_PAPER_CARD && !c.isEmblem() && c.getPaperCard() != null) {
if (USE_FROM_PAPER_CARD && !c.isImmutable() && c.getPaperCard() != null) {
Card newCard = Card.fromPaperCard(c.getPaperCard(), newOwner);
newCard.setCommander(c.isCommander());
return newCard;

View File

@@ -58,7 +58,6 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
Conspiracy(false, "conspiracies"),
Creature(true, "creatures"),
Dungeon(false, "dungeons"),
Emblem(false, "emblems"),
Enchantment(true, "enchantments"),
Instant(false, "instants"),
Land(true, "lands"),
@@ -437,11 +436,6 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
return coreTypes.contains(CoreType.Phenomenon);
}
@Override
public boolean isEmblem() {
return coreTypes.contains(CoreType.Emblem);
}
@Override
public boolean isTribal() {
return coreTypes.contains(CoreType.Tribal);
@@ -547,7 +541,7 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
if (!isInstant() && !isSorcery()) {
Iterables.removeIf(subtypes, Predicates.IS_SPELL_TYPE);
}
if (!isPlaneswalker() && !isEmblem()) {
if (!isPlaneswalker()) {
Iterables.removeIf(subtypes, Predicates.IS_WALKER_TYPE);
}
}

View File

@@ -42,7 +42,6 @@ public interface CardTypeView extends Iterable<String>, Serializable {
boolean isBasicLand();
boolean isPlane();
boolean isPhenomenon();
boolean isEmblem();
boolean isTribal();
boolean isDungeon();
CardTypeView getTypeWithChanges(Iterable<CardChangedType> changedCardTypes);

View File

@@ -153,8 +153,7 @@ public final class GameActionUtil {
final StringBuilder sb = new StringBuilder(sa.getDescription());
if (!source.equals(host)) {
sb.append(" by ");
if ((host.isEmblem() || host.getType().hasSubtype("Effect"))
&& host.getEffectSource() != null) {
if ((host.isImmutable()) && host.getEffectSource() != null) {
sb.append(host.getEffectSource());
} else {
sb.append(host);
@@ -542,7 +541,6 @@ public final class GameActionUtil {
final Card eff = new Card(game.nextCardId(), game);
eff.setTimestamp(game.getNextTimestamp());
eff.setName(sourceCard.getName() + "'s Effect");
eff.addType("Effect");
eff.setOwner(controller);
eff.setImageKey(sourceCard.getImageKey());

View File

@@ -112,9 +112,9 @@ public class AbilityUtils {
// Probably will move to One function solution sometime in the future
public static CardCollection getDefinedCards(final Card hostCard, final String def, final CardTraitBase sa) {
CardCollection cards = new CardCollection();
String defined = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self
final String[] incR = defined.split("\\.", 2);
defined = incR[0];
String changedDef = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self
final String[] incR = changedDef.split("\\.", 2);
String defined = incR[0];
final Game game = hostCard.getGame();
Card c = null;
@@ -132,7 +132,7 @@ public class AbilityUtils {
}
}
else if (defined.equals("EffectSource")) {
if (hostCard.isEmblem() || hostCard.getType().hasSubtype("Effect")) {
if (hostCard.isImmutable()) {
c = findEffectRoot(hostCard);
}
}
@@ -346,6 +346,23 @@ public class AbilityUtils {
cards.add(game.getCardState(cardByID));
}
}
} else if (defined.startsWith("Valid")) {
Iterable<Card> candidates;
String validDefined;
if (defined.startsWith("Valid ")) {
candidates = game.getCardsIn(ZoneType.Battlefield);
validDefined = changedDef.substring("Valid ".length());
} else if (defined.startsWith("ValidAll ")) {
candidates = game.getCardsInGame();
validDefined = changedDef.substring("ValidAll ".length());
} else {
String[] s = changedDef.split(" ", 2);
String zone = s[0].substring("Valid".length());
candidates = game.getCardsIn(ZoneType.smartValueOf(zone));
validDefined = s[1];
}
cards.addAll(CardLists.getValidCards(candidates, validDefined.split(","), hostCard.getController(), hostCard, sa));
return cards;
} else {
CardCollection list = null;
if (sa instanceof SpellAbility) {
@@ -377,19 +394,6 @@ public class AbilityUtils {
}
}
if (defined.startsWith("Valid ")) {
String validDefined = defined.substring("Valid ".length());
list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), validDefined.split(","), hostCard.getController(), hostCard, sa);
} else if (defined.startsWith("ValidAll ")) {
String validDefined = defined.substring("ValidAll ".length());
list = CardLists.getValidCards(game.getCardsInGame(), validDefined.split(","), hostCard.getController(), hostCard, sa);
} else if (defined.startsWith("Valid")) {
String[] s = defined.split(" ");
String zone = s[0].substring("Valid".length());
String validDefined = s[1];
list = CardLists.getValidCards(game.getCardsIn(ZoneType.smartValueOf(zone)), validDefined.split(","), hostCard.getController(), hostCard, sa);
}
if (list != null) {
cards.addAll(list);
}
@@ -421,7 +425,7 @@ public class AbilityUtils {
private static Card findEffectRoot(Card startCard) {
Card cc = startCard.getEffectSource();
if (cc != null) {
if (cc.isEmblem() || cc.getType().hasSubtype("Effect")) {
if (cc.isImmutable()) {
return findEffectRoot(cc);
}
return cc;

View File

@@ -13,7 +13,6 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import forge.GameCommand;
import forge.card.CardType;
import forge.card.MagicColor;
import forge.game.Game;
import forge.game.GameEntity;
@@ -457,25 +456,19 @@ public abstract class SpellAbilityEffect {
final Card eff = new Card(game.nextCardId(), game);
eff.setTimestamp(game.getNextTimestamp());
eff.setName(name);
eff.setColor(hostCard.determineColor().getColor());
// if name includes emblem then it should be one
eff.addType(name.startsWith("Emblem") ? "Emblem" : "Effect");
// add Planeswalker types into Emblem for fun
if (name.startsWith("Emblem") && hostCard.isPlaneswalker()) {
for (final String type : hostCard.getType().getSubtypes()) {
if (CardType.isAPlaneswalkerType(type)) {
eff.addType(type);
}
}
if (name.startsWith("Emblem")) {
eff.setEmblem(true);
// Emblem needs to be colorless
eff.setColor(MagicColor.COLORLESS);
}
eff.setOwner(controller);
eff.setSVars(sa.getSVars());
eff.setImageKey(image);
if (eff.getType().hasType(CardType.CoreType.Emblem)) {
eff.setColor(MagicColor.COLORLESS);
} else {
eff.setColor(hostCard.determineColor().getColor());
}
eff.setImmutable(true);
eff.setEffectSource(sa);

View File

@@ -190,11 +190,6 @@ public class AnimateEffect extends AnimateEffectBase {
}
}
// Restore immutable to effect
if (sa.hasParam("Immutable")) {
c.setImmutable(true);
}
game.fireEvent(new GameEventCardStatsChanged(c));
}

View File

@@ -12,7 +12,6 @@ public class DetachedCardEffect extends Card {
card = card0;
setName(name0);
addType("Effect");
setOwner(card0.getOwner());
setImmutable(true);

View File

@@ -140,10 +140,6 @@ public class EffectEffect extends SpellAbilityEffect {
final Card eff = createEffect(sa, controller, name, image);
eff.setSetCode(sa.getHostCard().getSetCode());
eff.setRarity(sa.getHostCard().getRarity());
// For Raging River effect to add attacker "left" or "right" pile later
if (sa.hasParam("Mutable")) {
eff.setImmutable(false);
}
// Abilities and triggers work the same as they do for Token
// Grant abilities

View File

@@ -37,7 +37,7 @@ public class RegenerationEffect extends SpellAbilityEffect {
// Play the Regen sound
game.fireEvent(new GameEventCardRegenerated());
if (host.getType().hasStringType("Effect")) {
if (host.isImmutable()) {
c.subtractShield(host);
host.removeRemembered(c);
}

View File

@@ -47,7 +47,7 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
prevent -= n;
if (!StringUtils.isNumeric(varValue) && card.getSVar(varValue).startsWith("Number$")) {
if (card.getType().hasStringType("Effect") && prevent <= 0) {
if (card.isImmutable() && prevent <= 0) {
game.getAction().exile(card, null);
} else {
card.setSVar(varValue, "Number$" + prevent);

View File

@@ -45,7 +45,7 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
dmg -= n;
prevent -= n;
if (card.getType().hasStringType("Effect") && prevent <= 0) {
if (card.isImmutable() && prevent <= 0) {
game.getAction().exile(card, null);
} else if (!StringUtils.isNumeric(varValue)) {
sa.setSVar(varValue, "Number$" + prevent);

View File

@@ -264,6 +264,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
// for Vanguard / Manapool / Emblems etc.
private boolean isImmutable = false;
private boolean isEmblem = false;
private int exertThisTurn = 0;
private PlayerCollection exertedByPlayer = new PlayerCollection();
@@ -4598,15 +4599,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
public final boolean isPermanent() {
return !isImmutable && (isInZone(ZoneType.Battlefield) || getType().isPermanent());
return !isImmutable() && (isInZone(ZoneType.Battlefield) || getType().isPermanent());
}
public final boolean isSpell() {
return (isInstant() || isSorcery() || (isAura() && !isInZone((ZoneType.Battlefield))));
}
public final boolean isEmblem() { return getType().isEmblem(); }
public final boolean isLand() { return getType().isLand(); }
public final boolean isBasicLand() { return getType().isBasicLand(); }
public final boolean isSnow() { return getType().isSnow(); }
@@ -4865,11 +4864,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
// Takes one argument like Permanent.Blue+withFlying
@Override
public final boolean isValid(final String restriction, final Player sourceController, final Card source, CardTraitBase spellAbility) {
if (isImmutable() && source != null && !source.isRemembered(this) &&
!(restriction.startsWith("Emblem") || restriction.startsWith("Effect"))) { // special case exclusion
return false;
}
// Inclusive restrictions are Card types
final String[] incR = restriction.split("\\.", 2);
@@ -4879,14 +4873,27 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
incR[0] = incR[0].substring(1); // consume negation sign
}
if (incR[0].equals("Spell") && !isSpell()) {
if (incR[0].equals("Spell")) {
if (!isSpell()) {
return testFailed;
}
if (incR[0].equals("Permanent") && !isPermanent()) {
} else if (incR[0].equals("Permanent")) {
if (!isPermanent()) {
return testFailed;
}
if (!incR[0].equals("card") && !incR[0].equals("Card") && !incR[0].equals("Spell")
&& !incR[0].equals("Permanent") && !getType().hasStringType(incR[0])) {
} else if (incR[0].equals("Effect")) {
if (!isImmutable()) {
return testFailed;
}
} else if (incR[0].equals("Emblem")) {
if (!isEmblem()) {
return testFailed;
}
} else if (incR[0].equals("card") || incR[0].equals("Card")) {
if (isImmutable()) {
return testFailed;
}
} else if (!getType().hasStringType(incR[0])) {
return testFailed; // Check for wrong type
}
@@ -4916,6 +4923,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
public final void setImmutable(final boolean isImmutable0) {
isImmutable = isImmutable0;
view.updateImmutable(this);
}
public final boolean isEmblem() {
return isEmblem;
}
public final void setEmblem(final boolean isEmblem0) {
isEmblem = isEmblem0;
view.updateEmblem(this);
}
/*

View File

@@ -357,7 +357,7 @@ public class CardProperty {
return false;
}
} else if (property.equals("EffectSource")) {
if (!source.isEmblem() && !source.getType().hasSubtype("Effect")) {
if (!source.isImmutable()) {
return false;
}

View File

@@ -242,6 +242,7 @@ public final class CardUtil {
newCopy.setToken(in.isToken());
newCopy.setCopiedSpell(in.isCopiedSpell());
newCopy.setImmutable(in.isImmutable());
newCopy.setEmblem(in.isEmblem());
// lock in the current P/T
newCopy.setBasePower(in.getCurrentPower());

View File

@@ -233,6 +233,20 @@ public class CardView extends GameEntityView {
set(TrackableProperty.Token, c.isToken());
}
public boolean isImmutable() {
return get(TrackableProperty.IsImmutable);
}
public void updateImmutable(Card c) {
set(TrackableProperty.IsImmutable, c.isImmutable());
}
public boolean isEmblem() {
return get(TrackableProperty.IsEmblem);
}
public void updateEmblem(Card c) {
set(TrackableProperty.IsEmblem, c.isEmblem());
}
public boolean isTokenCard() { return get(TrackableProperty.TokenCard); }
void updateTokenCard(Card c) { set(TrackableProperty.TokenCard, c.isTokenCard()); }

View File

@@ -3176,6 +3176,7 @@ public class Player extends GameEntity implements Comparable<Player> {
if (monarchEffect == null) {
monarchEffect = new Card(game.nextCardId(), null, game);
monarchEffect.setOwner(this);
monarchEffect.setImmutable(true);
if (set != null) {
monarchEffect.setImageKey("t:monarch_" + set.toLowerCase());
monarchEffect.setSetCode(set);
@@ -3183,7 +3184,6 @@ public class Player extends GameEntity implements Comparable<Player> {
monarchEffect.setImageKey("t:monarch");
}
monarchEffect.setName("The Monarch");
monarchEffect.addType("Effect");
{
final String drawTrig = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Command | " +
@@ -3280,8 +3280,7 @@ public class Player extends GameEntity implements Comparable<Player> {
blessingEffect.setOwner(this);
blessingEffect.setImageKey("t:blessing");
blessingEffect.setName("City's Blessing");
blessingEffect.addType("Effect");
blessingEffect.setImmutable(true);
blessingEffect.updateStateForView();
@@ -3353,7 +3352,6 @@ public class Player extends GameEntity implements Comparable<Player> {
keywordEffect.setOwner(this);
keywordEffect.setName("Keyword Effects");
keywordEffect.setImageKey(ImageKeys.HIDDEN_CARD);
keywordEffect.addType("Effect");
keywordEffect.updateStateForView();

View File

@@ -95,8 +95,7 @@ public class LandAbility extends Ability {
Card source = sta.getHostCard();
if (!source.equals(getHostCard())) {
sb.append(" by ");
if ((source.isEmblem() || source.getType().hasSubtype("Effect"))
&& source.getEffectSource() != null) {
if (source.isImmutable() && source.getEffectSource() != null) {
sb.append(source.getEffectSource());
} else {
sb.append(source);

View File

@@ -24,6 +24,9 @@ public enum TrackableProperty {
Controller(TrackableTypes.PlayerViewType),
Zone(TrackableTypes.EnumType(ZoneType.class)),
IsImmutable(TrackableTypes.BooleanType),
IsEmblem(TrackableTypes.BooleanType),
Flipped(TrackableTypes.BooleanType),
Facedown(TrackableTypes.BooleanType),
Foretold(TrackableTypes.BooleanType),

View File

@@ -311,7 +311,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
final CardStateView state = getCard().getCurrentState();
final CardEdition ed = FModel.getMagicDb().getEditions().get(state.getSetCode());
boolean colorIsSet = false;
if (state.getType().isEmblem() || state.getType().hasStringType("Effect")) {
if (getCard().isImmutable()) {
// Effects are drawn with orange border
g2d.setColor(Color.ORANGE);
colorIsSet = true;

View File

@@ -362,8 +362,7 @@ public class CardImageRenderer {
drawDetails(g, card, gameView, altState, x, y, w, h);
return;
}
if(card.isToken() && card.getCurrentState().getType().hasSubtype("Effect")
&& FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_IMAGES_EFFECT_CARDS)){
if(card.isImmutable() && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_IMAGES_EFFECT_CARDS)){
drawDetails(g, card, gameView, altState, x, y, w, h);
return;
}

View File

@@ -5,7 +5,7 @@ PT:3/4
T:Mode$ Phase | Phase$ EndCombat | Execute$ TrigCounter | TriggerZones$ Battlefield | TriggerDescription$ At end of combat, put a paralyzation counter on each creature blocking or blocked by CARDNAME and tap those creatures. Each of those creatures doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it. Each of those creatures gains "{4}: Remove a paralyzation counter from this creature."
SVar:TrigCounter:DB$ PutCounterAll | CounterType$ PARALYZATION | CounterNum$ 1 | ValidCards$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBTap
SVar:DBTap:DB$ TapAll | ValidCards$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBEffect
SVar:DBEffect:DB$ Effect | RememberObjects$ Valid Creature.blockedBySource,Valid Creature.blockingSource | StaticAbilities$ DontUntap | Duration$ Permanent | ConditionPresent$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBAnimate | ForgetOnMoved$ Battlefield | ForgetCounter$ PARALYZATION
SVar:DBEffect:DB$ Effect | RememberObjects$ Valid Creature.blockedBySource,Creature.blockingSource | StaticAbilities$ DontUntap | Duration$ Permanent | ConditionPresent$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBAnimate | ForgetOnMoved$ Battlefield | ForgetCounter$ PARALYZATION
SVar:DBAnimate:DB$ AnimateAll | ValidCards$ Creature.blockedBySource,Creature.blockingSource | Abilities$ ABRemoveCounter | Duration$ Permanent
SVar:ABRemoveCounter:AB$ RemoveCounter | Defined$ Self | Cost$ 4 | CounterType$ PARALYZATION | CounterNum$ 1 | SpellDescription$ Remove a paralyzation counter from this creature.
SVar:DontUntap:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Card.IsRemembered | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. | Description$ Each of those creatures doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it.

View File

@@ -5,5 +5,5 @@ PT:3/3
K:First Strike
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, exile it and return to the battlefield all artifact and creature cards in your graveyard that were put there from the battlefield this turn.
SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBReturn
SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact,Creature.YouOwn+ThisTurnEnteredFrom_Battlefield
SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact.YouOwn+ThisTurnEnteredFrom_Battlefield,Creature.YouOwn+ThisTurnEnteredFrom_Battlefield
Oracle:First strike\nWhen Gerrard, Weatherlight Hero dies, exile it and return to the battlefield all artifact and creature cards in your graveyard that were put there from the battlefield this turn.

View File

@@ -1,17 +1,16 @@
Name:Plague of Vermin
ManaCost:6 B
Types:Sorcery
A:SP$ Effect | Cost$ 6 B | Name$ Plague of Vermin Life Paid | EffectOwner$ Player | ImprintOnHost$ True | Mutable$ True | Duration$ Permanent | SubAbility$ DBRepeat | StackDescription$ SpellDescription | SpellDescription$ Starting with you, each player may pay any amount of life. Repeat this process until no one pays life. Each player creates a 1/1 black Rat creature token for each 1 life they paid this way.
A:SP$ Effect | Cost$ 6 B | Name$ Plague of Vermin Life Paid | EffectOwner$ Player | ImprintOnHost$ True | Duration$ Permanent | SubAbility$ DBRepeat | StackDescription$ SpellDescription | SpellDescription$ Starting with you, each player may pay any amount of life. Repeat this process until no one pays life. Each player creates a 1/1 black Rat creature token for each 1 life they paid this way.
SVar:DBRepeat:DB$ Repeat | RepeatSubAbility$ DBResetCheck | RepeatCheckSVar$ NumPlayerGiveup | RepeatSVarCompare$ LTTotalPlayer | SubAbility$ DBRepeatToken
SVar:DBResetCheck:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ Number | Expression$ 0 | SubAbility$ DBRepeatChoice
SVar:DBRepeatChoice:DB$ RepeatEach | StartingWithActivator$ True | RepeatSubAbility$ DBChoice | RepeatPlayers$ Player
SVar:DBChoice:DB$ ChooseNumber | Defined$ Player.IsRemembered | Max$ LifeTotal | AILogic$ Vermin | ListTitle$ Pay Any Amount of Life | SubAbility$ DBCheckPaid
SVar:DBCheckPaid:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ CountSVar | Expression$ NumPlayerGiveup/Plus.1 | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ0 | SubAbility$ DBStore
SVar:DBStore:DB$ PutCounter | Defined$ Imprinted.namedPlague of Vermin Life Paid+OwnedBy Player.IsRemembered | CounterNum$ X | Placer$ Player.IsRemembered | CounterType$ PLAGUE | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | UnlessCost$ PayLife<X> | UnlessPayer$ Player.IsRemembered | UnlessSwitched$ True | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DBGiveUp | SpellDescription$ You may pay any amount of life.
SVar:DBStore:DB$ PutCounter | Defined$ ValidCommand Effect.namedPlague of Vermin Life Paid+OwnedBy Player.IsRemembered | CounterNum$ X | Placer$ Player.IsRemembered | CounterType$ PLAGUE | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | UnlessCost$ PayLife<X> | UnlessPayer$ Player.IsRemembered | UnlessSwitched$ True | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DBGiveUp | SpellDescription$ You may pay any amount of life.
SVar:DBGiveUp:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ CountSVar | Expression$ NumPlayerGiveup/Plus.1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1
SVar:DBRepeatToken:DB$ RepeatEach | StartingWithActivator$ True | RepeatSubAbility$ DBToken | RepeatPlayers$ Player | SubAbility$ DBFinalReset
SVar:DBToken:DB$ Token | TokenAmount$ LifePaidAmount | TokenScript$ b_1_1_rat | TokenOwner$ Player.IsRemembered | StackDescription$ None | SubAbility$ DBRestoreImmutable
SVar:DBRestoreImmutable:DB$ Animate | Defined$ Imprinted.namedPlague of Vermin Life Paid+OwnedBy Player.IsRemembered | Duration$ Permanent | Immutable$ True
SVar:DBToken:DB$ Token | TokenAmount$ LifePaidAmount | TokenScript$ b_1_1_rat | TokenOwner$ Player.IsRemembered | StackDescription$ None
SVar:DBFinalReset:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ Number | Expression$ 0 | SubAbility$ DBExileEffect
SVar:DBExileEffect:DB$ ChangeZone | Defined$ Imprinted | Origin$ Command | Destination$ Exile | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True

View File

@@ -3,16 +3,16 @@ ManaCost:R R
Types:Enchantment
T:Mode$ AttackersDeclared | AttackingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRepeatDefender | TriggerDescription$ Whenever one or more creatures you control attack, each defending player divides all creatures without flying they control into a "left" pile and a "right" pile. Then, for each attacking creature you control, choose "left" or "right." That creature can't be blocked this combat except by creatures with flying and creatures in a pile with the chosen label.
SVar:TrigRepeatDefender:DB$ RepeatEach | RepeatPlayers$ TriggeredAttackedTarget | RepeatSubAbility$ DBDefLeftEffect | SubAbility$ DBAtkLeftRight
SVar:DBDefLeftEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Left | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Mutable$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefRightEffect
SVar:DBDefRightEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Right | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Mutable$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefLeftRight
SVar:DBDefLeftEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Left | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefRightEffect
SVar:DBDefRightEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Right | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefLeftRight
SVar:DBCantBlock:Mode$ CantBlockBy | ValidAttacker$ Creature.IsRemembered | ValidBlocker$ Creature.withoutFlying+IsNotImprinted+YouCtrl | EffectZone$ Command
SVar:DBDefLeftRight:DB$ TwoPiles | Defined$ Remembered | Separator$ Remembered | ValidCards$ Creature.withoutFlying+RememberedPlayerCtrl | Zone$ Battlefield | LeftRightPile$ True | ChosenPile$ DBDefLeftPile | UnchosenPile$ DBDefRightPile | AILogic$ Random | SubAbility$ DBClearImprinted
SVar:DBDefLeftPile:DB$ Animate | Defined$ Imprinted.namedRaging River Left | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBLeftPump
SVar:DBDefRightPile:DB$ Animate | Defined$ Imprinted.namedRaging River Right | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBRightPump
SVar:DBDefLeftPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Left+IsImprinted | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBLeftPump
SVar:DBDefRightPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Right+IsImprinted | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBRightPump
SVar:DBClearImprinted:DB$ Cleanup | ClearImprinted$ True
SVar:DBAtkLeftRight:DB$ TwoPiles | Defined$ You | Separator$ You | ValidCards$ Creature.attacking+YouCtrl | Zone$ Battlefield | LeftRightPile$ True | ChosenPile$ DBAtkLeftPile | UnchosenPile$ DBAtkRightPile | AILogic$ Random | SubAbility$ DBCleanup
SVar:DBAtkLeftPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Left | RememberObjects$ RememberedCard | Duration$ Permanent | Immutable$ True | SubAbility$ DBLeftPump
SVar:DBAtkRightPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Right | RememberObjects$ RememberedCard | Duration$ Permanent | Immutable$ True | SubAbility$ DBRightPump
SVar:DBAtkLeftPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Left | RememberObjects$ RememberedCard | Duration$ Permanent | SubAbility$ DBLeftPump
SVar:DBAtkRightPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Right | RememberObjects$ RememberedCard | Duration$ Permanent | SubAbility$ DBRightPump
SVar:DBLeftPump:DB$ Pump | Defined$ Remembered | KW$ "Left" pile | Duration$ UntilEndOfCombat
SVar:DBRightPump:DB$ Pump | Defined$ Remembered | KW$ "Right" pile | Duration$ UntilEndOfCombat
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True

View File

@@ -1,5 +1,5 @@
Name:Second Sunrise
ManaCost:1 W W
Types:Instant
A:SP$ChangeZone | Cost$ 1 W W | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact,Creature,Enchantment,Land.ThisTurnEnteredFrom_Battlefield | SpellDescription$ Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn.
A:SP$ChangeZone | Cost$ 1 W W | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact.ThisTurnEnteredFrom_Battlefield,Creature.ThisTurnEnteredFrom_Battlefield,Enchantment.ThisTurnEnteredFrom_Battlefield,Land.ThisTurnEnteredFrom_Battlefield | SpellDescription$ Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn.
Oracle:Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn.

View File

@@ -121,7 +121,7 @@ public class Puzzle extends GameState implements InventoryItem, Comparable<Puzzl
goalCard.setOwner(human);
goalCard.setImageKey("t:puzzle");
goalCard.setName("Puzzle Goal");
goalCard.addType("Effect");
goalCard.setImmutable(true);
goalCard.setOracleText(getGoalDescription());
int turnCorr = 0;

View File

@@ -221,7 +221,7 @@ public class CardDetailUtil {
String curColors = "";
// do not show current colors for temp effect cards, emblems and the like
if (state.getType().isEmblem() || state.getType().hasSubtype("Effect")) {
if (state.getCard().isImmutable()) {
return "";
}
@@ -275,16 +275,14 @@ public class CardDetailUtil {
// Token
if (card.isToken()) {
if(card.getCurrentState().getType().hasSubtype("Effect"))
area.append("Effect");
else if(card.getCurrentState().getType().isEmblem())
area.append("Emblem");
else
area.append("Token");
} else if (card.isTokenCard()) {
area.append("Token card");
} else if(card.isEmblem()) {
area.append("Emblem");
} else if(card.isImmutable()) {
area.append("Effect");
}
// card text
if (area.length() != 0) {
area.append("\n");