mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
Merge branch 'tokencards' into 'master'
Add Time Sidewalk and Bone Rattler See merge request core-developers/forge!4690
This commit is contained in:
@@ -98,6 +98,7 @@ public enum SpellApiToAi {
|
|||||||
.put(ApiType.Learn, LearnAi.class)
|
.put(ApiType.Learn, LearnAi.class)
|
||||||
.put(ApiType.LoseLife, LifeLoseAi.class)
|
.put(ApiType.LoseLife, LifeLoseAi.class)
|
||||||
.put(ApiType.LosesGame, GameLossAi.class)
|
.put(ApiType.LosesGame, GameLossAi.class)
|
||||||
|
.put(ApiType.MakeCard, AlwaysPlayAi.class)
|
||||||
.put(ApiType.Mana, ManaEffectAi.class)
|
.put(ApiType.Mana, ManaEffectAi.class)
|
||||||
.put(ApiType.ManaReflected, CannotPlayAi.class)
|
.put(ApiType.ManaReflected, CannotPlayAi.class)
|
||||||
.put(ApiType.Manifest, ManifestAi.class)
|
.put(ApiType.Manifest, ManifestAi.class)
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ public enum ApiType {
|
|||||||
LookAt (LookAtEffect.class),
|
LookAt (LookAtEffect.class),
|
||||||
LoseLife (LifeLoseEffect.class),
|
LoseLife (LifeLoseEffect.class),
|
||||||
LosesGame (GameLossEffect.class),
|
LosesGame (GameLossEffect.class),
|
||||||
|
MakeCard (MakeCardEffect.class),
|
||||||
Mana (ManaEffect.class),
|
Mana (ManaEffect.class),
|
||||||
ManaReflected (ManaReflectedEffect.class),
|
ManaReflected (ManaReflectedEffect.class),
|
||||||
Manifest (ManifestEffect.class),
|
Manifest (ManifestEffect.class),
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -222,6 +222,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
private boolean tapped = false;
|
private boolean tapped = false;
|
||||||
private boolean sickness = true; // summoning sickness
|
private boolean sickness = true; // summoning sickness
|
||||||
private boolean token = false;
|
private boolean token = false;
|
||||||
|
private boolean tokenCard = false;
|
||||||
private Card copiedPermanent = null;
|
private Card copiedPermanent = null;
|
||||||
private boolean copiedSpell = false;
|
private boolean copiedSpell = false;
|
||||||
|
|
||||||
@@ -2921,6 +2922,18 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
|||||||
view.updateToken(this);
|
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() {
|
public final Card getCopiedPermanent() {
|
||||||
return copiedPermanent;
|
return copiedPermanent;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -608,7 +608,7 @@ public final class CardPredicates {
|
|||||||
public static final Predicate<Card> NON_TOKEN = new Predicate<Card>() {
|
public static final Predicate<Card> NON_TOKEN = new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Card c) {
|
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>() {
|
public static final Predicate<Card> TOKEN = new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Card c) {
|
public boolean apply(Card c) {
|
||||||
return c.isToken();
|
return c.isToken() || c.isTokenCard();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1370,11 +1370,11 @@ public class CardProperty {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("token")) {
|
} else if (property.startsWith("token")) {
|
||||||
if (!card.isToken()) {
|
if (!card.isToken() && !card.isTokenCard()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("nonToken")) {
|
} else if (property.startsWith("nonToken")) {
|
||||||
if (card.isToken()) {
|
if (card.isToken() || card.isTokenCard()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("copiedSpell")) {
|
} else if (property.startsWith("copiedSpell")) {
|
||||||
|
|||||||
@@ -233,6 +233,9 @@ public class CardView extends GameEntityView {
|
|||||||
set(TrackableProperty.Token, c.isToken());
|
set(TrackableProperty.Token, c.isToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTokenCard() { return get(TrackableProperty.TokenCard); }
|
||||||
|
void updateTokenCard(Card c) { set(TrackableProperty.TokenCard, c.isTokenCard()); }
|
||||||
|
|
||||||
public boolean isCommander() {
|
public boolean isCommander() {
|
||||||
return get(TrackableProperty.IsCommander);
|
return get(TrackableProperty.IsCommander);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ public enum TrackableProperty {
|
|||||||
Sickness(TrackableTypes.BooleanType),
|
Sickness(TrackableTypes.BooleanType),
|
||||||
Tapped(TrackableTypes.BooleanType),
|
Tapped(TrackableTypes.BooleanType),
|
||||||
Token(TrackableTypes.BooleanType),
|
Token(TrackableTypes.BooleanType),
|
||||||
|
TokenCard(TrackableTypes.BooleanType),
|
||||||
IsCommander(TrackableTypes.BooleanType),
|
IsCommander(TrackableTypes.BooleanType),
|
||||||
CommanderAltType(TrackableTypes.StringType),
|
CommanderAltType(TrackableTypes.StringType),
|
||||||
Damage(TrackableTypes.IntegerType),
|
Damage(TrackableTypes.IntegerType),
|
||||||
|
|||||||
10
forge-gui/res/cardsfolder/b/bone_rattler.txt
Normal file
10
forge-gui/res/cardsfolder/b/bone_rattler.txt
Normal 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.
|
||||||
9
forge-gui/res/cardsfolder/t/time_sidewalk.txt
Normal file
9
forge-gui/res/cardsfolder/t/time_sidewalk.txt
Normal 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.
|
||||||
@@ -280,6 +280,8 @@ public class CardDetailUtil {
|
|||||||
area.append("Emblem");
|
area.append("Emblem");
|
||||||
else
|
else
|
||||||
area.append("Token");
|
area.append("Token");
|
||||||
|
} else if (card.isTokenCard()) {
|
||||||
|
area.append("Token card");
|
||||||
}
|
}
|
||||||
|
|
||||||
// card text
|
// card text
|
||||||
|
|||||||
Reference in New Issue
Block a user