It is currently 09 Sep 2025, 22:20
   
Text Size

Profane Command

Post MTG Forge Related Programming Questions Here

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

Re: Profane Command

Postby 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
Good luck and let me know if I seem to have forgotten something. I also made some last minute changes to allow for the comparison of the svars, so hope I didn't break it further. 8-[
-Marc
User avatar
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

Postby 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
Here's also the revised patch after the recent code changes:
ProfaneCommand patch.txt
(19.59 KiB) Downloaded 241 times
-Marc
User avatar
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

Postby 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)?
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Profane Command

Postby moomarc » 14 Oct 2012, 20:39

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)?
I just didn't know how or where to add something like that. :D
-Marc
User avatar
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

Postby Sloth » 14 Oct 2012, 20:55

moomarc wrote:
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)?
I just didn't know how or where to add something like that. :D
I think it could go into fillRequirements in the SpellAbilityRequirements class.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Profane Command

Postby 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:

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

Postby 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
User avatar
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

Postby friarsol » 15 Feb 2013, 02:16

Ok, that NPE is fixed. And it seems like it should work except X is 0 during resolution
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Profane Command

Postby 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

Postby Sloth » 16 Feb 2013, 19:49

friarsol wrote:Ok, that NPE is fixed. And it seems like it should work except X is 0 during resolution
I fixed this by also storing the SVars on the card. This is not very elegant, but it worked.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Previous

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 78 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 78 users online :: 0 registered, 0 hidden and 78 guests (based on users active over the past 10 minutes)
Most users ever online was 7303 on 15 Jul 2025, 20:46

Users browsing this forum: No registered users and 78 guests

Login Form