Merge branch 'tokencards' into 'master'

Add Time Sidewalk and Bone Rattler

See merge request core-developers/forge!4690
This commit is contained in:
Michael Kamensky
2021-05-11 16:48:08 +00:00
11 changed files with 82 additions and 4 deletions

View File

@@ -98,6 +98,7 @@ public enum SpellApiToAi {
.put(ApiType.Learn, LearnAi.class)
.put(ApiType.LoseLife, LifeLoseAi.class)
.put(ApiType.LosesGame, GameLossAi.class)
.put(ApiType.MakeCard, AlwaysPlayAi.class)
.put(ApiType.Mana, ManaEffectAi.class)
.put(ApiType.ManaReflected, CannotPlayAi.class)
.put(ApiType.Manifest, ManifestAi.class)

View File

@@ -97,6 +97,7 @@ public enum ApiType {
LookAt (LookAtEffect.class),
LoseLife (LifeLoseEffect.class),
LosesGame (GameLossEffect.class),
MakeCard (MakeCardEffect.class),
Mana (ManaEffect.class),
ManaReflected (ManaReflectedEffect.class),
Manifest (ManifestEffect.class),

View File

@@ -0,0 +1,38 @@
package forge.game.ability.effects;
import forge.StaticData;
import forge.game.Game;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
public class MakeCardEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
final Player player = sa.getActivatingPlayer();
final Game game = player.getGame();
final String name = sa.hasParam("Name") ? sa.getParam("Name") : sa.getHostCard().getName();
final ZoneType zone = ZoneType.smartValueOf(sa.getParamOrDefault("Zone", "Library"));
int amount = sa.hasParam("Amount") ? Integer.parseInt(sa.getParam("Amount")) : 1;
CardCollection cards = new CardCollection();
while (amount > 0) {
Card card = Card.fromPaperCard(StaticData.instance().getCommonCards().getUniqueByName(name), player);
if (!sa.hasParam("NotToken")) { card.setTokenCard(true); }
cards.add(card);
amount--;
}
for (final Card c : cards) {
game.getAction().moveTo(zone, c, sa);
}
if (zone.equals(ZoneType.Library)) {
player.shuffle(sa);
}
}
}

View File

@@ -222,6 +222,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private boolean tapped = false;
private boolean sickness = true; // summoning sickness
private boolean token = false;
private boolean tokenCard = false;
private Card copiedPermanent = null;
private boolean copiedSpell = false;
@@ -2921,6 +2922,18 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
view.updateToken(this);
}
public final boolean isTokenCard() {
if (isInZone(ZoneType.Battlefield) && hasMergedCard()) {
return getTopMergedCard().tokenCard;
}
return tokenCard;
}
public final void setTokenCard(boolean tokenC) {
if (tokenCard = tokenC) { return; }
tokenCard = tokenC;
view.updateTokenCard(this);
}
public final Card getCopiedPermanent() {
return copiedPermanent;
}

View File

@@ -608,7 +608,7 @@ public final class CardPredicates {
public static final Predicate<Card> NON_TOKEN = new Predicate<Card>() {
@Override
public boolean apply(Card c) {
return !c.isToken();
return !(c.isToken() || c.isTokenCard());
}
};
/**
@@ -617,7 +617,7 @@ public final class CardPredicates {
public static final Predicate<Card> TOKEN = new Predicate<Card>() {
@Override
public boolean apply(Card c) {
return c.isToken();
return c.isToken() || c.isTokenCard();
}
};
/**

View File

@@ -1370,11 +1370,11 @@ public class CardProperty {
return false;
}
} else if (property.startsWith("token")) {
if (!card.isToken()) {
if (!card.isToken() && !card.isTokenCard()) {
return false;
}
} else if (property.startsWith("nonToken")) {
if (card.isToken()) {
if (card.isToken() || card.isTokenCard()) {
return false;
}
} else if (property.startsWith("copiedSpell")) {

View File

@@ -233,6 +233,9 @@ public class CardView extends GameEntityView {
set(TrackableProperty.Token, c.isToken());
}
public boolean isTokenCard() { return get(TrackableProperty.TokenCard); }
void updateTokenCard(Card c) { set(TrackableProperty.TokenCard, c.isTokenCard()); }
public boolean isCommander() {
return get(TrackableProperty.IsCommander);
}

View File

@@ -47,6 +47,7 @@ public enum TrackableProperty {
Sickness(TrackableTypes.BooleanType),
Tapped(TrackableTypes.BooleanType),
Token(TrackableTypes.BooleanType),
TokenCard(TrackableTypes.BooleanType),
IsCommander(TrackableTypes.BooleanType),
CommanderAltType(TrackableTypes.StringType),
Damage(TrackableTypes.IntegerType),

View File

@@ -0,0 +1,10 @@
Name:Bone Rattler
ManaCost:3 B B
Types:Creature Skeleton
PT:4/4
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Graveyard | Execute$ TrigExile | TriggerDescription$ When CARDNAME is put into a graveyard from anywhere, exile it. If you do, create four Reassembling Skeleton token cards and put them into your graveyard.
SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | RememberChanged$ True | SubAbility$ DBMakeCard
SVar:DBMakeCard:DB$ MakeCard | Name$ Reassembling Skeleton | Zone$ Graveyard | Amount$ 4 | SubAbility$ DBCleanup | ConditionDefined$ Remembered | ConditionPresent$ Card.Self | ConditionCompare$ GE1
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
DeckHas:Ability$Graveyard
Oracle:When Bone Rattler is put into a graveyard from anywhere, exile it. If you do, create four Reassembling Skeleton token cards and put them into your graveyard.

View File

@@ -0,0 +1,9 @@
Name:Time Sidewalk
ManaCost:4 U U U U
Types:Sorcery
K:MayEffectFromOpeningHand:ExileCard
A:SP$ AddTurn | Cost$ 4 U U U U | NumTurns$ 1 | SpellDescription$ Take an extra turn after this one.
SVar:ExileCard:DB$ ChangeZone | Defined$ Self | Origin$ Hand | Destination$ Exile | RememberChanged$ True | SubAbility$ DBMakeCard | SpellDescription$ If this card is in your opening hand, you may exile it. If you do, create four Time Walk token cards and shuffle them into your deck.
SVar:DBMakeCard:DB$ MakeCard | Name$ Time Walk | Amount$ 4 | Zone$ Library | SubAbility$ DBCleanup | ConditionDefined$ Remembered | ConditionPresent$ Card.Self | ConditionCompare$ GE1
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
Oracle:Take an extra turn after this one.\nIf this card is in your opening hand, you may exile it. If you do, create four Time Walk token cards and shuffle them into your deck.

View File

@@ -280,6 +280,8 @@ public class CardDetailUtil {
area.append("Emblem");
else
area.append("Token");
} else if (card.isTokenCard()) {
area.append("Token card");
}
// card text