mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18:01 +00:00
- Adding Manifest effect
This commit is contained in:
@@ -77,6 +77,7 @@ public enum ApiType {
|
||||
LosesGame (GameLossEffect.class),
|
||||
Mana (ManaEffect.class),
|
||||
ManaReflected (ManaReflectedEffect.class),
|
||||
Manifest (ManifestEffect.class),
|
||||
Mill (MillEffect.class),
|
||||
MoveCounter (CountersMoveEffect.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) {
|
||||
return;
|
||||
}
|
||||
final PlayerZone lib = player.getZone(ZoneType.Library);
|
||||
int maxCards = lib.size();
|
||||
// If library is smaller than N, only show that many cards
|
||||
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));
|
||||
}
|
||||
|
||||
CardCollection topCards = player.getTopXCardsFromLibrary(numCards);
|
||||
int maxCards = topCards.size();
|
||||
|
||||
CardCollectionView orderedCards = activator.getController().orderMoveToZoneList(topCards, ZoneType.Library);
|
||||
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 int monstrosityNum = 0;
|
||||
|
||||
private boolean manifested = false;
|
||||
|
||||
private long bestowTimestamp = -1;
|
||||
private boolean suspendCast = 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) {
|
||||
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.
|
||||
}
|
||||
|
||||
@@ -346,6 +349,11 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cleared tests, about to change states
|
||||
if (currentStateName.equals(CardStateName.FaceDown) && state.equals(CardStateName.Original)) {
|
||||
this.setManifested(false);
|
||||
}
|
||||
|
||||
currentStateName = state;
|
||||
currentState = states.get(state);
|
||||
|
||||
@@ -404,16 +412,52 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
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() {
|
||||
if (!isDoubleFaced()) {
|
||||
return turnFaceDown(false);
|
||||
}
|
||||
|
||||
public boolean turnFaceDown(boolean override) {
|
||||
if (override || !isDoubleFaced()) {
|
||||
preFaceDownState = currentStateName;
|
||||
return setState(CardStateName.FaceDown, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean turnFaceUp() {
|
||||
public boolean turnFaceUp() {
|
||||
return turnFaceUp(false);
|
||||
}
|
||||
|
||||
public boolean turnFaceUp(boolean manifestPaid) {
|
||||
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);
|
||||
if (result) {
|
||||
getGame().getTriggerHandler().registerActiveTrigger(this, false);
|
||||
@@ -1544,6 +1588,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
if (monstrous) {
|
||||
sb.append("Monstrous\r\n");
|
||||
}
|
||||
if (manifested) {
|
||||
sb.append("Manifested\r\n");
|
||||
}
|
||||
sb.append(keywordsToText(getUnhiddenKeywords(state)));
|
||||
|
||||
// Give spellText line breaks for easier reading
|
||||
@@ -5672,6 +5719,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
monstrosityNum = num;
|
||||
}
|
||||
|
||||
public final boolean isManifested() {
|
||||
return manifested;
|
||||
}
|
||||
public final void setManifested(final boolean manifested) {
|
||||
this.manifested = manifested;
|
||||
}
|
||||
|
||||
public final void animateBestow() {
|
||||
bestowTimestamp = getGame().getNextTimestamp();
|
||||
addChangedCardTypes(new CardType(Arrays.asList("Aura")),
|
||||
|
||||
@@ -166,6 +166,47 @@ public class CardFactoryUtil {
|
||||
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) {
|
||||
SpellAbility sa = new SpellAbility.EmptySa(card);
|
||||
sa.getMapParams().put("AILogic", card.getSVar("AgendaLogic"));
|
||||
|
||||
@@ -1330,6 +1330,21 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
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) {
|
||||
final CardCollection list = new CardCollection(getCardsIn(ZoneType.Library));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user