- Adding Manifest effect

This commit is contained in:
Sol
2015-01-02 22:48:47 +00:00
parent 37029fd2b9
commit 06801023b5
7 changed files with 167 additions and 14 deletions

View File

@@ -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),

View File

@@ -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);
}
}
}
}
}
}

View File

@@ -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--) {

View File

@@ -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")),

View File

@@ -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"));

View File

@@ -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));