- Added Nicmagus Elemental (RtR)

This commit is contained in:
moomarc
2012-10-01 18:19:41 +00:00
parent 5c11cbe5d2
commit 34efd19d3a
6 changed files with 176 additions and 14 deletions

1
.gitattributes vendored
View File

@@ -6657,6 +6657,7 @@ res/cardsfolder/n/niv_mizzet_the_firemind.txt svneol=native#text/plain
res/cardsfolder/n/niveous_wisps.txt svneol=native#text/plain
res/cardsfolder/n/nivix_aerie_of_the_firemind.txt -text
res/cardsfolder/n/nivix_guildmage.txt -text
res/cardsfolder/n/nivmagus_elemental.txt -text
res/cardsfolder/n/no_dachi.txt svneol=native#text/plain
res/cardsfolder/n/no_mercy.txt svneol=native#text/plain
res/cardsfolder/n/no_rest_for_the_wicked.txt -text

View File

@@ -0,0 +1,12 @@
Name:Nivmagus Elemental
ManaCost:UR
Types:Creature Elemental
Text:no text
PT:1/2
A:AB$ PutCounter | Cost$ ExileFromStack<1/Spell.Instant+YouCtrl;Spell.Sorcery+YouCtrl/instant or sorcery spell> | CostDesc$ Exile an instant or sorcery spell you control: | CounterType$ P1P1 | CounterNum$ 2 | SpellDescription$ Put two +1/+1 counters on CARDNAME. (That spell won't resolve.)
SVar:RemAIDeck:True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/nivmagus_elemental.jpg
SetInfo:RTR|Rare|http://magiccards.info/scans/en/rtr/219.jpg
Oracle:Exile an instant or sorcery spell you control: Put two +1/+1 counters on Nivmagus Elemental. (That spell won't resolve.)
End

View File

@@ -161,6 +161,7 @@ public class Cost {
private static final String EXILE_STR = "Exile<";
private static final String EXILE_FROM_HAND_STR = "ExileFromHand<";
private static final String EXILE_FROM_GRAVE_STR = "ExileFromGrave<";
private static final String EXILE_FROM_STACK_STR = "ExileFromStack<";
private static final String EXILE_FROM_TOP_STR = "ExileFromTop<";
private static final String RETURN_STR = "Return<";
private static final String REVEAL_STR = "Reveal<";
@@ -305,6 +306,14 @@ public class Cost {
this.costParts.add(new CostExile(splitStr[0], splitStr[1], description, ZoneType.Graveyard));
}
while (parse.contains(Cost.EXILE_FROM_STACK_STR)) {
final String[] splitStr = this.abCostParse(parse, Cost.EXILE_FROM_STACK_STR, 3);
parse = this.abUpdateParse(parse, Cost.EXILE_FROM_STACK_STR);
final String description = splitStr.length > 2 ? splitStr[2] : null;
this.costParts.add(new CostExile(splitStr[0], splitStr[1], description, ZoneType.Stack));
}
while (parse.contains(Cost.EXILE_FROM_TOP_STR)) {
final String[] splitStr = this.abCostParse(parse, Cost.EXILE_FROM_TOP_STR, 3);
parse = this.abUpdateParse(parse, Cost.EXILE_FROM_TOP_STR);

View File

@@ -17,6 +17,7 @@
*/
package forge.card.cost;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JOptionPane;
@@ -28,6 +29,7 @@ import forge.GameActionUtil;
import forge.Singletons;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityStackInstance;
import forge.control.input.Input;
import forge.game.player.ComputerUtil;
import forge.game.player.Player;
@@ -142,7 +144,14 @@ public class CostExile extends CostPartWithList {
*/
@Override
public final boolean canPay(final SpellAbility ability, final Card source, final Player activator, final Cost cost) {
CardList typeList = activator.getCardsIn(this.getFrom());
CardList typeList = new CardList();
if (this.getFrom().equals(ZoneType.Stack)) {
for (int i = 0; i < AllZone.getStack().size(); i++) {
typeList.add(AllZone.getStack().peekAbility(i).getSourceCard());
}
} else {
typeList = activator.getCardsIn(this.getFrom());
}
if (!this.getThis()) {
typeList = typeList.getValidCards(this.getType().split(";"), activator, source);
@@ -167,6 +176,15 @@ public class CostExile extends CostPartWithList {
public final void payAI(final SpellAbility ability, final Card source, final CostPayment payment) {
for (final Card c : this.getList()) {
Singletons.getModel().getGameAction().exile(c);
if (this.from.equals(ZoneType.Stack)) {
ArrayList<SpellAbility> spells = c.getSpellAbilities();
for (SpellAbility spell : spells) {
if (c.isInZone(ZoneType.Exile)) {
final SpellAbilityStackInstance si = AllZone.getStack().getInstanceFromSpellAbility(spell);
AllZone.getStack().remove(si);
}
}
}
}
}
@@ -199,6 +217,8 @@ public class CostExile extends CostPartWithList {
CostUtil.setInput(CostExile.exileThis(ability, payment, this));
} else if (this.from.equals(ZoneType.Battlefield) || this.from.equals(ZoneType.Hand)) {
CostUtil.setInput(CostExile.exileType(ability, this, this.getType(), payment, c));
} else if (this.from.equals(ZoneType.Stack)) {
CostUtil.setInput(CostExile.exileFromStack(ability, this, this.getType(), payment, c));
} else if (this.from.equals(ZoneType.Library)) {
CostExile.exileFromTop(ability, this, payment, c);
} else {
@@ -362,6 +382,98 @@ public class CostExile extends CostPartWithList {
return target;
} // exileFrom()
/**
* Exile from Stack.
*
* @param sa
* the sa
* @param part
* the part
* @param type
* the type
* @param payment
* the payment
* @param nNeeded
* the n needed
* @return the input
*/
public static Input exileFromStack(final SpellAbility sa, final CostExile part, final String type,
final CostPayment payment, final int nNeeded) {
final Input target = new Input() {
private static final long serialVersionUID = 734256837615635021L;
private ArrayList<SpellAbility> saList;
private ArrayList<String> descList;
@Override
public void showMessage() {
if (nNeeded == 0) {
this.done();
}
saList = new ArrayList<SpellAbility>();
descList = new ArrayList<String>();
for (int i = 0; i < AllZone.getStack().size(); i++) {
final Card stC = AllZone.getStack().peekAbility(i).getSourceCard();
final SpellAbility stSA = AllZone.getStack().peekAbility(i).getRootSpellAbility();
if (stC.isValid(type.split(";"), sa.getActivatingPlayer(), sa.getSourceCard()) && stSA.isSpell()) {
this.saList.add(stSA);
if (stC.isCopiedSpell()) {
this.descList.add(stSA.getStackDescription() + " (Copied Spell)");
} else {
this.descList.add(stSA.getStackDescription());
}
}
}
for (int i = 0; i < nNeeded; i++) {
if (this.saList.size() == 0) {
this.cancel();
}
//Have to use the stack descriptions here because some copied spells have no description otherwise
final String o = GuiUtils
.chooseOneOrNone("Exile from " + part.getFrom(), this.descList);
if (o != null) {
final SpellAbility toExile = this.saList.get(descList.indexOf(o));
final Card c = toExile.getSourceCard();
this.saList.remove(toExile);
part.addToList(c);
if (!c.isCopiedSpell()) {
Singletons.getModel().getGameAction().exile(c);
}
if (i == (nNeeded - 1)) {
this.done();
}
final SpellAbilityStackInstance si = AllZone.getStack().getInstanceFromSpellAbility(toExile);
AllZone.getStack().remove(si);
} else {
this.cancel();
break;
}
}
}
@Override
public void selectButtonCancel() {
this.cancel();
}
public void done() {
this.stop();
part.addListToHash(sa, "Exiled");
payment.paidCost(part);
}
public void cancel() {
this.stop();
payment.cancelCost();
}
};
return target;
} // exileFrom()
/**
* <p>
* exileType.
@@ -403,6 +515,8 @@ public class CostExile extends CostPartWithList {
if (part.getFrom().equals(ZoneType.Hand)) {
msg.append(" from your Hand");
} else if (part.getFrom().equals(ZoneType.Stack)) {
msg.append(" from the Stack");
}
this.typeList = sa.getActivatingPlayer().getCardsIn(part.getFrom());
this.typeList = this.typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(),

View File

@@ -37,7 +37,7 @@ import forge.gui.GuiUtils;
*/
public class CostUtil {
private static Random r = new Random();
/**
* Check sacrifice cost.
*
@@ -457,8 +457,7 @@ public class CostUtil {
// Just a shortcut..
AllZone.getInputControl().setInput(in, true);
}
public static Cost combineCosts(Cost cost1, Cost cost2) {
if (cost1 == null) {
if (cost2 == null) {
@@ -467,11 +466,11 @@ public class CostUtil {
return cost2;
}
}
if (cost2 == null) {
return cost1;
}
for (final CostPart part : cost1.getCostParts()) {
if (!(part instanceof CostMana)) {
cost2.getCostParts().add(part);

View File

@@ -1330,7 +1330,7 @@ public class ComputerUtil {
if (sa.getPayCosts() != null) {
for (CostPart part : sa.getPayCosts().getCostParts()) {
if (part instanceof CostDiscard) {
return false;
return false;
}
}
}
@@ -1338,7 +1338,6 @@ public class ComputerUtil {
}
}
}
landList = landList.filter(new Predicate<Card>() {
@Override
@@ -1481,7 +1480,7 @@ public class ComputerUtil {
// priority 5 the highest
final int priority = 6 - ip;
for (Card c : typeList) {
if (priority == 3 && c.isLand()
if (priority == 3 && c.isLand()
&& !AllZone.getComputerPlayer().getCardsIn(ZoneType.Battlefield, "Crucible of Worlds").isEmpty()) {
return c;
}
@@ -1491,7 +1490,7 @@ public class ComputerUtil {
}
}
// Discard lands
// Discard lands
final CardList landsInHand = typeList.getType("Land");
if (!landsInHand.isEmpty()) {
final CardList landsInPlay = AllZone.getComputerPlayer().getCardsIn(ZoneType.Battlefield).getType("Land");
@@ -1626,7 +1625,7 @@ public class ComputerUtil {
continue;
}
List<Card> aiCards = AllZone.getComputerPlayer().getCardsIn(ZoneType.Battlefield);
final int numLandsInPlay = Iterables.size(Iterables.filter(aiCards, CardPredicates.Presets.LANDS));
final int numLandsInPlay = Iterables.size(Iterables.filter(aiCards, CardPredicates.Presets.LANDS));
final CardList landsInHand = hand.filter(CardPredicates.Presets.LANDS);
final int numLandsInHand = landsInHand.size();
@@ -1636,7 +1635,7 @@ public class ComputerUtil {
|| (numLandsInHand > 0 && numLandsInPlay > 5)) {
discardList.add(landsInHand.get(0));
hand.remove(landsInHand.get(0));
} else { // Discard other stuff
} else { // Discard other stuff
CardListUtil.sortCMC(hand);
int numLandsAvailable = numLandsInPlay;
if (numLandsInHand > 0) {
@@ -1716,6 +1715,26 @@ public class ComputerUtil {
return ComputerUtil.chooseExileFrom(ZoneType.Graveyard, type, activate, target, amount);
}
/**
* <p>
* chooseExileFromStackType.
* </p>
*
* @param type
* a {@link java.lang.String} object.
* @param activate
* a {@link forge.Card} object.
* @param target
* a {@link forge.Card} object.
* @param amount
* a int.
* @return a {@link forge.CardList} object.
*/
public static CardList chooseExileFromStackType(final String type, final Card activate, final Card target,
final int amount) {
return ComputerUtil.chooseExileFrom(ZoneType.Stack, type, activate, target, amount);
}
/**
* <p>
* chooseExileFrom.
@@ -1735,8 +1754,16 @@ public class ComputerUtil {
*/
public static CardList chooseExileFrom(final ZoneType zone, final String type, final Card activate,
final Card target, final int amount) {
CardList typeList = AllZone.getComputerPlayer().getCardsIn(zone);
typeList = typeList.getValidCards(type.split(","), activate.getController(), activate);
CardList typeList = new CardList();
if (zone.equals(ZoneType.Stack)) {
for (int i = 0; i < AllZone.getStack().size(); i++) {
typeList.add(AllZone.getStack().peekAbility(i).getSourceCard());
typeList = typeList.getValidCards(type.split(","), activate.getController(), activate);
}
} else {
typeList = AllZone.getComputerPlayer().getCardsIn(zone);
typeList = typeList.getValidCards(type.split(","), activate.getController(), activate);
}
if ((target != null) && target.getController().isComputer() && typeList.contains(target)) {
typeList.remove(target); // don't exile the card we're pumping
}