mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
- Adding Manifest effect
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -387,6 +387,7 @@ forge-game/src/main/java/forge/game/ability/effects/LifeSetEffect.java -text
|
|||||||
forge-game/src/main/java/forge/game/ability/effects/LookAtEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/LookAtEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java -text
|
||||||
|
forge-game/src/main/java/forge/game/ability/effects/ManifestEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/MillEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/MillEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java -text
|
||||||
forge-game/src/main/java/forge/game/ability/effects/MustAttackEffect.java -text
|
forge-game/src/main/java/forge/game/ability/effects/MustAttackEffect.java -text
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ public enum ApiType {
|
|||||||
LosesGame (GameLossEffect.class),
|
LosesGame (GameLossEffect.class),
|
||||||
Mana (ManaEffect.class),
|
Mana (ManaEffect.class),
|
||||||
ManaReflected (ManaReflectedEffect.class),
|
ManaReflected (ManaReflectedEffect.class),
|
||||||
|
Manifest (ManifestEffect.class),
|
||||||
Mill (MillEffect.class),
|
Mill (MillEffect.class),
|
||||||
MoveCounter (CountersMoveEffect.class),
|
MoveCounter (CountersMoveEffect.class),
|
||||||
MultiplePiles (MultiplePilesEffect.class),
|
MultiplePiles (MultiplePilesEffect.class),
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import forge.card.CardStateName;
|
||||||
|
import forge.game.ability.AbilityUtils;
|
||||||
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
|
import forge.game.card.CardCollectionView;
|
||||||
|
import forge.game.card.CardLists;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.spellability.TargetRestrictions;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ManifestEffect extends SpellAbilityEffect {
|
||||||
|
@Override
|
||||||
|
public void resolve(SpellAbility sa) {
|
||||||
|
final Card source = sa.getHostCard();
|
||||||
|
// Usually a number leaving possibility for X, Sacrifice X land: Manifest X creatures.
|
||||||
|
final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(sa.getHostCard(),
|
||||||
|
sa.getParam("Amount"), sa) : 1;
|
||||||
|
// Most commonly "defined" is Top of Library
|
||||||
|
final String defined = sa.hasParam("Defined") ? sa.getParam("Defined") : "TopOfLibrary";
|
||||||
|
|
||||||
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
|
for (final Player p : getTargetPlayers(sa, "DefinedPlayer")) {
|
||||||
|
if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
||||||
|
CardCollection tgtCards;
|
||||||
|
if ("TopOfLibrary".equals(defined)) {
|
||||||
|
tgtCards = p.getTopXCardsFromLibrary(amount);
|
||||||
|
} else {
|
||||||
|
tgtCards = getTargetCards(sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sa.hasParam("Shuffle")) {
|
||||||
|
CardLists.shuffle(tgtCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Card c : tgtCards) {
|
||||||
|
Card rem = c.manifest(p);
|
||||||
|
if (sa.hasParam("RememberManifested") && rem != null) {
|
||||||
|
source.addRemembered(rem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -109,18 +109,9 @@ public class RearrangeTopOfLibraryEffect extends SpellAbilityEffect {
|
|||||||
if (activator == null) {
|
if (activator == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final PlayerZone lib = player.getZone(ZoneType.Library);
|
|
||||||
int maxCards = lib.size();
|
CardCollection topCards = player.getTopXCardsFromLibrary(numCards);
|
||||||
// If library is smaller than N, only show that many cards
|
int maxCards = topCards.size();
|
||||||
maxCards = Math.min(maxCards, numCards);
|
|
||||||
if (maxCards == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final CardCollection topCards = new CardCollection();
|
|
||||||
// show top n cards:
|
|
||||||
for (int j = 0; j < maxCards; j++) {
|
|
||||||
topCards.add(lib.get(j));
|
|
||||||
}
|
|
||||||
|
|
||||||
CardCollectionView orderedCards = activator.getController().orderMoveToZoneList(topCards, ZoneType.Library);
|
CardCollectionView orderedCards = activator.getController().orderMoveToZoneList(topCards, ZoneType.Library);
|
||||||
for (int i = maxCards - 1; i >= 0; i--) {
|
for (int i = maxCards - 1; i >= 0; i--) {
|
||||||
|
|||||||
@@ -162,6 +162,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private boolean monstrous = false;
|
private boolean monstrous = false;
|
||||||
private int monstrosityNum = 0;
|
private int monstrosityNum = 0;
|
||||||
|
|
||||||
|
private boolean manifested = false;
|
||||||
|
|
||||||
private long bestowTimestamp = -1;
|
private long bestowTimestamp = -1;
|
||||||
private boolean suspendCast = false;
|
private boolean suspendCast = false;
|
||||||
private boolean suspend = false;
|
private boolean suspend = false;
|
||||||
@@ -334,6 +336,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
public boolean setState(final CardStateName state, boolean updateView) {
|
public boolean setState(final CardStateName state, boolean updateView) {
|
||||||
if (state == CardStateName.FaceDown && isDoubleFaced()) {
|
if (state == CardStateName.FaceDown && isDoubleFaced()) {
|
||||||
|
// TODO I believe No longer true with Manifest, needs to be tested out
|
||||||
return false; // Doublefaced cards can't be turned face-down.
|
return false; // Doublefaced cards can't be turned face-down.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,6 +349,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cleared tests, about to change states
|
||||||
|
if (currentStateName.equals(CardStateName.FaceDown) && state.equals(CardStateName.Original)) {
|
||||||
|
this.setManifested(false);
|
||||||
|
}
|
||||||
|
|
||||||
currentStateName = state;
|
currentStateName = state;
|
||||||
currentState = states.get(state);
|
currentState = states.get(state);
|
||||||
|
|
||||||
@@ -404,8 +412,32 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
preFaceDownState = preCharacteristic;
|
preFaceDownState = preCharacteristic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Card manifest(Player p) {
|
||||||
|
// Turn Face Down (even if it's DFC).
|
||||||
|
ManaCost cost = this.getManaCost();
|
||||||
|
|
||||||
|
// Sometimes cards are manifested while already being face down
|
||||||
|
if (!turnFaceDown(true) && currentStateName != CardStateName.FaceDown) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Move to p's battlefield
|
||||||
|
Card c = p.getGame().getAction().moveToPlay(this, p);
|
||||||
|
c.setPreFaceDownState(CardStateName.Original);
|
||||||
|
// Mark this card as "manifested"
|
||||||
|
c.setManifested(true);
|
||||||
|
|
||||||
|
// Add manifest demorph static ability for creatures?
|
||||||
|
c.addSpellAbility(CardFactoryUtil.abilityManifestFaceUp(c, cost));
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean turnFaceDown() {
|
public boolean turnFaceDown() {
|
||||||
if (!isDoubleFaced()) {
|
return turnFaceDown(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean turnFaceDown(boolean override) {
|
||||||
|
if (override || !isDoubleFaced()) {
|
||||||
preFaceDownState = currentStateName;
|
preFaceDownState = currentStateName;
|
||||||
return setState(CardStateName.FaceDown, true);
|
return setState(CardStateName.FaceDown, true);
|
||||||
}
|
}
|
||||||
@@ -413,7 +445,19 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean turnFaceUp() {
|
public boolean turnFaceUp() {
|
||||||
|
return turnFaceUp(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean turnFaceUp(boolean manifestPaid) {
|
||||||
if (currentStateName == CardStateName.FaceDown) {
|
if (currentStateName == CardStateName.FaceDown) {
|
||||||
|
if (manifestPaid && this.isManifested() && !this.getRules().getType().isCreature()) {
|
||||||
|
// If we've manifested a non-creature and we're demanifesting disallow it
|
||||||
|
|
||||||
|
// Unless this creature also has a Morph ability
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
boolean result = setState(preFaceDownState, true);
|
boolean result = setState(preFaceDownState, true);
|
||||||
if (result) {
|
if (result) {
|
||||||
getGame().getTriggerHandler().registerActiveTrigger(this, false);
|
getGame().getTriggerHandler().registerActiveTrigger(this, false);
|
||||||
@@ -1544,6 +1588,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
if (monstrous) {
|
if (monstrous) {
|
||||||
sb.append("Monstrous\r\n");
|
sb.append("Monstrous\r\n");
|
||||||
}
|
}
|
||||||
|
if (manifested) {
|
||||||
|
sb.append("Manifested\r\n");
|
||||||
|
}
|
||||||
sb.append(keywordsToText(getUnhiddenKeywords(state)));
|
sb.append(keywordsToText(getUnhiddenKeywords(state)));
|
||||||
|
|
||||||
// Give spellText line breaks for easier reading
|
// Give spellText line breaks for easier reading
|
||||||
@@ -5672,6 +5719,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
monstrosityNum = num;
|
monstrosityNum = num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final boolean isManifested() {
|
||||||
|
return manifested;
|
||||||
|
}
|
||||||
|
public final void setManifested(final boolean manifested) {
|
||||||
|
this.manifested = manifested;
|
||||||
|
}
|
||||||
|
|
||||||
public final void animateBestow() {
|
public final void animateBestow() {
|
||||||
bestowTimestamp = getGame().getNextTimestamp();
|
bestowTimestamp = getGame().getNextTimestamp();
|
||||||
addChangedCardTypes(new CardType(Arrays.asList("Aura")),
|
addChangedCardTypes(new CardType(Arrays.asList("Aura")),
|
||||||
|
|||||||
@@ -166,6 +166,47 @@ public class CardFactoryUtil {
|
|||||||
return morphUp;
|
return morphUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static AbilityStatic abilityManifestFaceUp(final Card sourceCard, final ManaCost manaCost) {
|
||||||
|
final Cost cost = new Cost(manaCost, false);
|
||||||
|
|
||||||
|
final AbilityStatic manifestUp = new AbilityStatic(sourceCard, cost, null) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
if (sourceCard.turnFaceUp(true)) {
|
||||||
|
String sb = this.getActivatingPlayer() + " has unmanifested " + sourceCard.getName();
|
||||||
|
sourceCard.getGame().getGameLog().add(GameLogEntryType.STACK_RESOLVE, sb);
|
||||||
|
sourceCard.getGame().fireEvent(new GameEventCardStatsChanged(sourceCard));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlay() {
|
||||||
|
return sourceCard.getController().equals(this.getActivatingPlayer()) && sourceCard.isFaceDown()
|
||||||
|
&& sourceCard.isInPlay() && sourceCard.isManifested();
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // morph_up
|
||||||
|
|
||||||
|
String costDesc = cost.toString();
|
||||||
|
// get rid of the ": " at the end
|
||||||
|
costDesc = costDesc.substring(0, costDesc.length() - 2);
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Unmanifest");
|
||||||
|
if (!cost.isOnlyManaCost()) {
|
||||||
|
sb.append(" -");
|
||||||
|
}
|
||||||
|
sb.append(" ").append(costDesc).append(" (Turn this face up any time for its mana cost.)");
|
||||||
|
manifestUp.setDescription(sb.toString());
|
||||||
|
|
||||||
|
final StringBuilder sbStack = new StringBuilder();
|
||||||
|
sbStack.append(sourceCard.getName()).append(" - turn this card face up.");
|
||||||
|
manifestUp.setStackDescription(sbStack.toString());
|
||||||
|
//manifestUp.setIsMorphUp(true);
|
||||||
|
|
||||||
|
return manifestUp;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean handleHiddenAgenda(Player player, Card card) {
|
public static boolean handleHiddenAgenda(Player player, Card card) {
|
||||||
SpellAbility sa = new SpellAbility.EmptySa(card);
|
SpellAbility sa = new SpellAbility.EmptySa(card);
|
||||||
sa.getMapParams().put("AILogic", card.getSVar("AgendaLogic"));
|
sa.getMapParams().put("AILogic", card.getSVar("AgendaLogic"));
|
||||||
|
|||||||
@@ -1330,6 +1330,21 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
return milled;
|
return milled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final CardCollection getTopXCardsFromLibrary(int amount) {
|
||||||
|
final CardCollection topCards = new CardCollection();
|
||||||
|
final PlayerZone lib = this.getZone(ZoneType.Library);
|
||||||
|
int maxCards = lib.size();
|
||||||
|
// If library is smaller than N, only get that many cards
|
||||||
|
maxCards = Math.min(maxCards, amount);
|
||||||
|
|
||||||
|
// show top n cards:
|
||||||
|
for (int j = 0; j < maxCards; j++) {
|
||||||
|
topCards.add(lib.get(j));
|
||||||
|
}
|
||||||
|
|
||||||
|
return topCards;
|
||||||
|
}
|
||||||
|
|
||||||
public final void shuffle(final SpellAbility sa) {
|
public final void shuffle(final SpellAbility sa) {
|
||||||
final CardCollection list = new CardCollection(getCardsIn(ZoneType.Library));
|
final CardCollection list = new CardCollection(getCardsIn(ZoneType.Library));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user