Profane Command
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
25 posts
• Page 2 of 2 • 1, 2
Re: Profane Command
by moomarc » 05 Oct 2012, 16:57
I didn't get to test stuff out again after getting things back to how they were (working except for the calculate amount bit), so hopefully I didn't miss anything. The following patch should patch the Profane Command script as well as the other code additions/changes:

- Code: Select all
Index: res/cardsfolder/p/profane_command.txt
===================================================================
--- res/cardsfolder/p/profane_command.txt (revision 17341)
+++ res/cardsfolder/p/profane_command.txt (working copy)
@@ -2,6 +2,14 @@
ManaCost:X B B
Types:Sorcery
Text:Choose two - Target player loses X life; or return target creature card with converted mana cost X or less from your graveyard to the battlefield; or target creature gets -X/-X until end of turn; or up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
+A:SP$ Charm | Cost$ XNotLessThan<Y,Z> X B B | Choices$ DBLose,DBChange,DBWeaken,DBSearch | CharmNum$ 2 | References$ X,Y,Z | SpellDescription$ Choose two - Target player loses X life; or return target creature card with converted mana cost X or less from your graveyard to the battlefield; or target creature gets -X/-X until end of turn; or up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
+SVar:DBLose:DB$ LoseLife | ValidTgts$ Player | TgtPrompt$ Select target player to lose life | LifeAmount$ X | References$ X | SpellDescription$ Target player loses X life.
+SVar:DBChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature in your graveyard | ValidTgts$ Creature.YouCtrl | XCountRefsThis$ True | SpellDescription$ Return target creature card with converted mana cost X or less from your graveyard to the battlefield.
+SVar:DBWeaken:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature | IsCurse$ True | NumAtt$ -X | NumDef$ -X | References$ X | SpellDescription$ Target creature gets -X/-X until end of turn.
+SVar:DBSearch:DB$ Pump | Cost$ 0 | ValidTgts$ Creature | TargetMin$ 0 | XCountRefsThis$ True | KW$ Fear | TgtPrompt$ Select target creature | SpellDescription$ Up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
+SVar:X:Count$xPaid
+SVar:Y:SpecificTargeted$CardManaCost
+SVar:Z:SpecificTargeted$Amount
SVar:RemAIDeck:True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/profane_command.jpg
Index: src/main/java/forge/card/cardfactory/CardFactorySorceries.java
===================================================================
--- src/main/java/forge/card/cardfactory/CardFactorySorceries.java (revision 17341)
+++ src/main/java/forge/card/cardfactory/CardFactorySorceries.java (working copy)
@@ -503,7 +503,7 @@
Singletons.getModel().getGameAction().exile(c);
}
}
- };
+ };
}
private final static SpellAbility getDonate( final Card card ) {
@@ -897,7 +897,7 @@
};
}
- private final static SpellAbility getProfaneCommand( final Card card ) {
+/* private final static SpellAbility getProfaneCommand( final Card card ) {
// not sure what to call variables, so I just made up something
final Player[] ab0player = new Player[1];
final Card[] ab1card = new Card[1];
@@ -1319,7 +1319,7 @@
spell.setBeforePayMana(chooseTwoInput);
card.setSpellWithChoices(true);
return spell;
- }
+ }*/
private final static SpellAbility getTransmuteArtifact( final Card card ) {
/*
@@ -1415,7 +1415,7 @@
} else if (cardName.equals("Patriarch's Bidding")) { card.addSpellAbility(getPatriarchsBidding(card));
} else if (cardName.equals("Leeches")) { card.addSpellAbility(getLeeches(card));
} else if (cardName.equals("Sanity Grinding")) { card.addSpellAbility(getSanityGrinding(card));
- } else if (cardName.equals("Profane Command")) { card.addSpellAbility(getProfaneCommand(card));
+ //} else if (cardName.equals("Profane Command")) { card.addSpellAbility(getProfaneCommand(card));
} else if (cardName.equals("Transmute Artifact")) { card.addSpellAbility(getTransmuteArtifact(card));
}
} // getCard
Index: src/main/java/forge/card/cost/Cost.java
===================================================================
--- src/main/java/forge/card/cost/Cost.java (revision 17341)
+++ src/main/java/forge/card/cost/Cost.java (working copy)
@@ -166,6 +166,7 @@
private static final String RETURN_STR = "Return<";
private static final String REVEAL_STR = "Reveal<";
private static final String XCANTBE0_STR = "XCantBe0";
+ private static final String XNOTLESSTHAN_STR = "XNotLessThan<";
public Cost(final Card card, CardManaCost cost, final boolean bAbility) {
this(card, cost.toString(), bAbility);
@@ -338,6 +339,15 @@
this.costParts.add(new CostReveal(splitStr[0], splitStr[1], description));
}
+ boolean xNotLessThan = parse.contains(XNOTLESSTHAN_STR);
+
+ String xGE = "";
+ while (parse.contains(Cost.XNOTLESSTHAN_STR)) {
+ final String[] splitStr = this.abCostParse(parse, Cost.XNOTLESSTHAN_STR, 1);
+ parse = this.abUpdateParse(parse, Cost.XNOTLESSTHAN_STR);
+ xGE = splitStr[0];
+ }
+
int manaLocation = 0;
// These won't show up with multiples
if (parse.contains("Untap")) {
@@ -364,7 +374,7 @@
if (xCantBe0) {
parse = parse.replaceAll(XCANTBE0_STR, "");
}
-
+
final String stripXCost = parse.replaceAll("X", "");
final int amountX = parse.length() - stripXCost.length();
@@ -375,7 +385,7 @@
}
if ((amountX > 0) || !mana.equals("0")) {
- this.costParts.add(manaLocation, new CostMana(mana, amountX, xCantBe0));
+ this.costParts.add(manaLocation, new CostMana(mana, amountX, xCantBe0, xNotLessThan, xGE));
}
}
@@ -447,11 +457,11 @@
if (!costChanged) {
// Spells with a cost of 0 should be affected too
final ManaCost changedCost = Singletons.getModel().getGameAction().getSpellCostChange(sa, new ManaCost("0"));
- this.costParts.add(new CostMana(changedCost.toString(), 0, false));
+ this.costParts.add(new CostMana(changedCost.toString(), 0, false, false, ""));
}
}
- public final CostMana getCostMana () {
+ public final CostMana getCostMana() {
// TODO: Change where ChangeCost happens
for (final CostPart part : this.costParts) {
if (part instanceof CostMana) {
Index: src/main/java/forge/card/cost/CostMana.java
===================================================================
--- src/main/java/forge/card/cost/CostMana.java (revision 17341)
+++ src/main/java/forge/card/cost/CostMana.java (working copy)
@@ -45,6 +45,8 @@
private int amountX = 0;
private String adjustedMana = "";
private boolean xCantBe0 = false;
+ private boolean xNotLessThan = false;
+ private String xGENum = "";
/**
* Gets the mana.
@@ -128,6 +130,39 @@
}
/**
+ * @return the boolean xNotLessThan
+ */
+ public boolean isxNotLessThan() {
+ return xNotLessThan;
+ }
+
+ /**
+ * @param bXNotLessThan the xNotLessThan to set
+ */
+ public void setxNotLessThan(boolean bXNotLessThan) {
+ this.xNotLessThan = bXNotLessThan;
+ }
+
+ /**
+ * Gets the String X must be greater than.
+ *
+ * @return the String X must be greater than
+ */
+ public final String getxGENum() {
+ return this.xGENum;
+ }
+
+ /**
+ * Sets the String X must be greater than.
+ *
+ * @param xGE
+ * the String X must be greater than
+ */
+ public final void setxGENum(final String xGE) {
+ this.xGENum = xGE;
+ }
+
+ /**
* Gets the mana to pay.
*
* @return the mana to pay
@@ -149,13 +184,19 @@
* @param amount
* the amount
* @param xCantBe0 TODO
+ * @param xNotLessThan
+ * the boolean xNotLessThan
+ * @param xGE
+ * X must be greater than this int
*/
- public CostMana(final String mana, final int amount, boolean xCantBe0) {
+ public CostMana(final String mana, final int amount, boolean xCantBe0, boolean xNotLessThan, String xGE) {
this.mana = mana.trim();
this.amountX = amount;
this.setUndoable(true);
this.setReusable(true);
this.setxCantBe0(xCantBe0);
+ this.setxNotLessThan(xNotLessThan);
+ this.xGENum = xGE;
}
/*
@@ -171,7 +212,7 @@
if (!this.mana.equals("0")) {
sb.append(this.mana);
}
-
+
return sb.toString().trim();
}
@@ -279,24 +320,41 @@
private String colorsPaid = sa.getSourceCard().getColorsPaid();
private ManaCost manaCost = new ManaCost(Integer.toString(numX));
+ private int xGE = 0;
+ private String[] xGESplit = costMana.getxGENum().split(",");
+
@Override
public void showMessage() {
- if ((xPaid == 0 && costMana.isxCantBe0()) ||
- !this.manaCost.toString().equals(Integer.toString(numX))) {
+ for (final String xGEvar : xGESplit) {
+ int amount = AbilityFactory.calculateAmount(sa.getSourceCard(), xGEvar, sa);
+ if (amount > xGE) {
+ xGE = amount;
+ }
+ }
+ if ((xPaid == 0 && costMana.isxCantBe0()
+ && xPaid < xGE && costMana.isxNotLessThan())
+ || !this.manaCost.toString().equals(Integer.toString(numX))) {
ButtonUtil.enableOnlyCancel();
// only cancel if partially paid an X value
// or X is 0, and x can't be 0
+ } else if ((xPaid < xGE) && costMana.isxNotLessThan()) {
+ ButtonUtil.enableOnlyCancel();
} else {
ButtonUtil.enableAll();
}
-
+ System.out.println("xGE = " + costMana.getxGENum());
+
StringBuilder msg = new StringBuilder("Pay X Mana Cost for ");
msg.append(sa.getSourceCard().getName()).append("\n").append(this.xPaid);
msg.append(" Paid so far.");
if (costMana.isxCantBe0()) {
msg.append(" X Can't be 0.");
}
-
+ if (costMana.isxNotLessThan() && (xPaid < xGE)) {
+ final int remaining = xGE - xPaid;
+ msg.append(" X must be at least " + xGE + " (" + remaining + " left)");
+ }
+
CMatchUI.SINGLETON_INSTANCE.showMessage(msg.toString());
}
Index: src/main/java/forge/card/cost/CostPayment.java
===================================================================
--- src/main/java/forge/card/cost/CostPayment.java (revision 17341)
+++ src/main/java/forge/card/cost/CostPayment.java (working copy)
@@ -293,7 +293,7 @@
final ArrayList<CostPart> parts = this.cost.getCostParts();
if (this.getCost().getCostMana() == null) {
- parts.add(new CostMana("0", 0, false));
+ parts.add(new CostMana("0", 0, false, false, ""));
}
// Set all of the decisions before attempting to pay anything

-Marc
-
moomarc - Pixel Commander
- Posts: 2091
- Joined: 04 Jun 2010, 15:22
- Location: Johannesburg, South Africa
- Has thanked: 371 times
- Been thanked: 372 times
Re: Profane Command
by moomarc » 07 Oct 2012, 12:24
I got around to testing a bit further and using SVar:Y:SpecificNumber$3 and SVar:Z:SpecificNumber$4 I can confirm that everything is working except for replacing the sa in calculateAmount with a specific one.
- Final script for Profane Command | Open
- Code: Select all
Name:Profane Command
ManaCost:X B B
Types:Sorcery
Text:Choose two - Target player loses X life; or return target creature card with converted mana cost X or less from your graveyard to the battlefield; or target creature gets -X/-X until end of turn; or up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
A:SP$ Charm | Cost$ XNotLessThan<Y,Z> X B B | Choices$ DBLose,DBChange,DBWeaken,DBSearch | CharmNum$ 2 | References$ X,Y,Z | SpellDescription$ Choose two - Target player loses X life; or return target creature card with converted mana cost X or less from your graveyard to the battlefield; or target creature gets -X/-X until end of turn; or up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
SVar:DBLose:DB$ LoseLife | ValidTgts$ Player | TgtPrompt$ Select target player to lose life | LifeAmount$ X | References$ X | SpellDescription$ Target player loses X life.
SVar:DBChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature in your graveyard | ValidTgts$ Creature.YouCtrl | XCountRefsThis$ True | SpellDescription$ Return target creature card with converted mana cost X or less from your graveyard to the battlefield.
SVar:DBWeaken:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature to get -X/-X | IsCurse$ True | NumAtt$ -X | NumDef$ -X | References$ X | SpellDescription$ Target creature gets -X/-X until end of turn.
SVar:DBSearch:DB$ Pump | Cost$ 0 | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ TgtMax | References$ TgtMax | XCountRefsThis$ True | KW$ Fear | TgtPrompt$ Select target creature to gain Fear | SpellDescription$ Up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
SVar:X:Count$xPaid
SVar:Y:SpecificTargeted$CardManaCost
SVar:Z:SpecificTargeted$Amount
#Test parameters below
#SVar:Y:SpecificNumber$3
#SVar:Z:SpecificNumber$4
SVar:TgtMax:Count$TypeOnBattlefield.Creature
SVar:RemAIDeck:True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/profane_command.jpg
SetInfo:LRW|Rare|http://magiccards.info/scans/en/lw/135.jpg
Oracle:Choose two - Target player loses X life; or return target creature card with converted mana cost X or less from your graveyard to the battlefield; or target creature gets -X/-X until end of turn; or up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
End
ProfaneCommand patch.txt
- (19.59 KiB) Downloaded 241 times
-Marc
-
moomarc - Pixel Commander
- Posts: 2091
- Joined: 04 Jun 2010, 15:22
- Location: Johannesburg, South Africa
- Has thanked: 371 times
- Been thanked: 372 times
Re: Profane Command
by Sloth » 14 Oct 2012, 20:01
This may be a bit late:
What about adding a parameter like "ChooseXInAdvance" that forces the player to choose X before targeting anything (like the rules actually work)?
What about adding a parameter like "ChooseXInAdvance" that forces the player to choose X before targeting anything (like the rules actually work)?
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Profane Command
by moomarc » 14 Oct 2012, 20:39
I just didn't know how or where to add something like that.Sloth wrote:This may be a bit late:
What about adding a parameter like "ChooseXInAdvance" that forces the player to choose X before targeting anything (like the rules actually work)?

-Marc
-
moomarc - Pixel Commander
- Posts: 2091
- Joined: 04 Jun 2010, 15:22
- Location: Johannesburg, South Africa
- Has thanked: 371 times
- Been thanked: 372 times
Re: Profane Command
by Sloth » 14 Oct 2012, 20:55
I think it could go into fillRequirements in the SpellAbilityRequirements class.moomarc wrote:I just didn't know how or where to add something like that.Sloth wrote:This may be a bit late:
What about adding a parameter like "ChooseXInAdvance" that forces the player to choose X before targeting anything (like the rules actually work)?
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Profane Command
by friarsol » 14 Feb 2013, 04:16
Hey marc,
I haven't had a chance to test this with Announce, but using the script you came up with before and trimming out some of the unnecessary bits, it probably would look something like:
I haven't had a chance to test this with Announce, but using the script you came up with before and trimming out some of the unnecessary bits, it probably would look something like:
- Code: Select all
Name:Profane Command
ManaCost:X B B
Types:Sorcery
Text:no text
A:SP$ Charm | Announce$ X | Cost$ X B B | Choices$ DBLose,DBChange,DBWeaken,DBSearch | CharmNum$ 2 | References$ X | SpellDescription$ Choose two - Target player loses X life; or return target creature card with converted mana cost X or less from your graveyard to the battlefield; or target creature gets -X/-X until end of turn; or up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
SVar:DBLose:DB$ LoseLife | ValidTgts$ Player | TgtPrompt$ Select target player to lose life | LifeAmount$ X | References$ X | SpellDescription$ Target player loses X life.
SVar:DBChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | References$ X | TgtPrompt$ Choose target creature in your graveyard | ValidTgts$ Creature.YouCtrl+cmcLEX | SpellDescription$ Return target creature card with converted mana cost X or less from your graveyard to the battlefield.
SVar:DBWeaken:DB$ Pump | ValidTgts$ Creature | TgtPrompt$ Select target creature to get -X/-X | IsCurse$ True | NumAtt$ -X | NumDef$ -X | References$ X | SpellDescription$ Target creature gets -X/-X until end of turn.
SVar:DBSearch:DB$ Pump | Cost$ 0 | ValidTgts$ Creature | TargetMin$ 0 | TargetMax$ X | References$ X | KW$ Fear | TgtPrompt$ Select target creature to gain Fear | SpellDescription$ Up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
SVar:X:Count$xPaid
#X Will get overwritten by Announce
SVar:RemAIDeck:True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/profane_command.jpg
SetInfo:LRW|Rare|http://magiccards.info/scans/en/lw/135.jpg
Oracle:Choose two - Target player loses X life; or return target creature card with converted mana cost X or less from your graveyard to the battlefield; or target creature gets -X/-X until end of turn; or up to X target creatures gain fear until end of turn. (They can't be blocked except by artifact creatures and/or black creatures.)
End
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Profane Command
by moomarc » 14 Feb 2013, 09:49
Thanks sol, but unfortunately it crashes with NPE at TargetSelection.getUniqueTargets(TargetSelection.java:245). Here's the crash report:
- | Open
- java.lang.NullPointerException
at forge.card.spellability.TargetSelection.getUniqueTargets(TargetSelection.java:245)
at forge.card.spellability.TargetSelection.chooseValidInput(TargetSelection.java:274)
at forge.card.spellability.TargetSelection.chooseTargets(TargetSelection.java:228)
at forge.card.spellability.TargetSelection.chooseTargets(TargetSelection.java:217)
at forge.card.spellability.SpellAbilityRequirements.fillRequirements(SpellAbilityRequirements.java:136)
at forge.card.spellability.SpellAbilityRequirements.fillRequirements(SpellAbilityRequirements.java:96)
at forge.game.GameActionPlay.playSpellAbility(GameActionPlay.java:397)
at forge.game.player.Player.playSpellAbility(Player.java:3101)
at forge.control.input.InputPassPriority.selectCard(InputPassPriority.java:87)
at forge.gui.GuiInput.selectCard(GuiInput.java:115)
at forge.gui.match.nonsingleton.CHand.cardclickAction(CHand.java:188)
at forge.gui.match.nonsingleton.CHand.access$0(CHand.java:182)
at forge.gui.match.nonsingleton.CHand$1.mousePressed(CHand.java:60)
at java.awt.AWTEventMulticaster.mousePressed(Unknown Source)
-Marc
-
moomarc - Pixel Commander
- Posts: 2091
- Joined: 04 Jun 2010, 15:22
- Location: Johannesburg, South Africa
- Has thanked: 371 times
- Been thanked: 372 times
Re: Profane Command
by swordshine » 15 Feb 2013, 02:49
Thanks for the fix, I think I can script Bioshift in a simple way.
- swordshine
- Posts: 682
- Joined: 11 Jul 2010, 02:37
- Has thanked: 116 times
- Been thanked: 87 times
Re: Profane Command
by Sloth » 16 Feb 2013, 19:49
I fixed this by also storing the SVars on the card. This is not very elegant, but it worked.friarsol wrote:Ok, that NPE is fixed. And it seems like it should work except X is 0 during resolution
-
Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
25 posts
• Page 2 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 78 guests