It is currently 29 Oct 2025, 13:30
   
Text Size

Return to Ravnica Spoiler Season

Post MTG Forge Related Programming Questions Here

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

Re: Return to Ravnica Spoiler Season

Postby Sloth » 30 Sep 2012, 20:43

ArsenalNut wrote:Here's the script I came up with for Jarad's Orders
Jarad's Orders | Open
Name:Jarad's Orders
ManaCost:2 B G
Types:Sorcery
Text:no text
A:SP$ ChangeZone | Cost$ 2 B G | Origin$ Library | Destination$ Library | ChangeType$ Creature | ChangeNum$ 2 | RememberChanged$ True | SubAbility$ DBChoice | SpellDescription$ Search your library for up to two creature cards and reveal them. Put one into your hand and the other into your graveyard. Then shuffle your library.
SVar:DBChoice:DB$ TwoPiles | Defined$ You | DefinedCards$ Remembered | Separator$ You | ChosenPile$ DBHand | UnchosenPile$ DBGrave
SVar:DBHand:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Hand
SVar:DBGrave:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Graveyard
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/jarads_orders.jpg
End

The script works but I want to see if there so unintended consequence I am missing. Also the actual play of the card is very menu intensive.
I think i can come up with a version that is more user (and AI) friendly.

EDIT: Here is my version:
Jarad's Orders | Open
Code: Select all
Name:Jarad's Orders
ManaCost:2 B G
Types:Sorcery
Text:no text
A:SP$ ChangeZone | Cost$ 2 B G | Origin$ Library | Destination$ Library | ChangeType$ Creature | ChangeNum$ 2 | RememberChanged$ True | Reveal$ True | Shuffle$ False | StackDescription$ SpellDescription | SubAbility$ DBChangeZone1 | SpellDescription$ Search your library for up to two creature cards and reveal them. Put one into your hand and the other into your graveyard. Then shuffle your library.
SVar:DBChangeZone1:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Creature.IsRemembered | ChangeNum$ 1 | Mandatory$ True | NoLooking$ True | SelectPrompt$ Select a card for your hand | Shuffle$ False | SubAbility$ DBChangeZone2 | StackDescription$ None
SVar:DBChangeZone2:DB$ ChangeZone | Origin$ Library | Destination$ Graveyard | ChangeType$ Creature.IsRemembered | Mandatory$ True | NoLooking$ True | SelectPrompt$ Select a card for your graveyard | StackDescription$ None | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/jarads_orders.jpg
End
There are a lots of new parameters (and lots of parameter options i have never used before). My only concern is the case with only one creature in the library. Do you have to put it into your hand or can you put it into your graveyard? If i'm reading the card, i think the former is correct. What do you think?
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Return to Ravnica Spoiler Season

Postby friarsol » 30 Sep 2012, 21:08

Sloth wrote:My only concern is the case with only one creature in the library. Do you have to put it into your hand or can you put it into your graveyard? If i'm reading the card, i think the former is correct. What do you think?
If there's only one valid choice it goes into your hand. It's kinda like a dig, but with cards you choose from your library.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Return to Ravnica Spoiler Season

Postby moomarc » 01 Oct 2012, 03:51

Shouldn't there be Min/MaxTarget params in there seeing as you can search for up to two creatures?
-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: Return to Ravnica Spoiler Season

Postby ArsenalNut » 01 Oct 2012, 04:50

moomarc wrote:Shouldn't there be Min/MaxTarget params in there seeing as you can search for up to two creatures?
No because you can cancel out of the initial choices to only select one card or no cards. There is a bug that the reveal box freezes the game if you don't select any cards.

Edit: I fixed the bug by adding a check on the list size
Last edited by ArsenalNut on 01 Oct 2012, 05:04, edited 1 time in total.
So many cards, so little time
User avatar
ArsenalNut
 
Posts: 512
Joined: 08 Jul 2011, 03:49
Has thanked: 27 times
Been thanked: 121 times

Re: Return to Ravnica Spoiler Season

Postby ArsenalNut » 01 Oct 2012, 04:57

I thought I had Grave Betrayal worked out.

Grave Betrayal | Open
Name:Grave Betrayal
ManaCost:5 B B
Types:Enchantment
Text:no text
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.YouDontCtrl | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ Whenever a creature you don't control dies, return it to the battlefield under your control with an additional +1/+1 counter on it at the beginning of the next end step. That creature is a black Zombie in addition to its other colors and types.
SVar:TrigEffect:AB$ Effect | Cost$ 0 | Name$ Grave Betrayal Effect | Triggers$ TrigEOT | SVars$ GBReturn,GBCounter,GBZombify | References$ GBReturn,GBCounter,GBZombify | RememberObjects$ TriggeredCard
SVar:TrigEOT:Mode$ Phase | Phase$ End of Turn | Execute$ GBReturn | TriggerDescription$ Return creature to the battlefield under your control with an additional +1/+1 counter on it at the beginning of the next end step. It is a black Zombie in addition to its other colors and types.
SVar:GBReturn:AB$ ChangeZone | Cost$ 0 | Defined$ Remembered | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | SubAbility$ GBCounter
SVar:GBCounter:DB$ PutCounter | Defined$ Remembered | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ GBZombify
SVar:GBZombify:DB$ Animate | Defined$ Remembered | Types$ Zombie | Colors$ Black | Permanent$ True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/grave_betrayal.jpg
End


The only part that doesn't work is
If a creature you don’t control dies during the end step, that creature won’t return to the battlefield until the beginning of the next end step.
This doesn't work because the effect goes away when the current end step stops instead of the next one. Is this a bug with effects?
So many cards, so little time
User avatar
ArsenalNut
 
Posts: 512
Joined: 08 Jul 2011, 03:49
Has thanked: 27 times
Been thanked: 121 times

Re: Return to Ravnica Spoiler Season

Postby moomarc » 01 Oct 2012, 05:20

ArsenalNut wrote:This doesn't work because the effect goes away when the current end step stops instead of the next one. Is this a bug with effects?
Effects use ExecuteUntil which gets cleared at the cleanup step, so make the effect duration permanent and add an extra subability that exiles the effect to the end of your EOT trigger.
-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: Return to Ravnica Spoiler Season

Postby ArsenalNut » 01 Oct 2012, 05:32

moomarc wrote:
ArsenalNut wrote:This doesn't work because the effect goes away when the current end step stops instead of the next one. Is this a bug with effects?
Effects use ExecuteUntil which gets cleared at the cleanup step, so make the effect duration permanent and add an extra subability that exiles the effect to the end of your EOT trigger.
That did the trick. That's the first card I've scripted that used the Effect AF. Pretty cool stuff.
So many cards, so little time
User avatar
ArsenalNut
 
Posts: 512
Joined: 08 Jul 2011, 03:49
Has thanked: 27 times
Been thanked: 121 times

Re: Return to Ravnica Spoiler Season

Postby ArsenalNut » 01 Oct 2012, 05:35

The RTR event decks just announced are completely supported with the new cards :D
So many cards, so little time
User avatar
ArsenalNut
 
Posts: 512
Joined: 08 Jul 2011, 03:49
Has thanked: 27 times
Been thanked: 121 times

Re: Return to Ravnica Spoiler Season

Postby moomarc » 01 Oct 2012, 05:37

ArsenalNut wrote:
moomarc wrote:
ArsenalNut wrote:This doesn't work because the effect goes away when the current end step stops instead of the next one. Is this a bug with effects?
Effects use ExecuteUntil which gets cleared at the cleanup step, so make the effect duration permanent and add an extra subability that exiles the effect to the end of your EOT trigger.
That did the trick. That's the first card I've scripted that used the Effect AF. Pretty cool stuff.
I know. Pretty powerful with all the params it has now. I did quite a few of them at one stage and got to the point where I now have a tendency to start a script with Effects before realising that it can be done more easily with Animate.
ArsenalNut wrote:The RTR event decks just announced are completely supported with the new cards :D
SWEET! =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: Return to Ravnica Spoiler Season

Postby Sloth » 01 Oct 2012, 07:21

@ArsenalNut: Why did you change the script of Triangle of War? Your version is no longer AI friendly.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Return to Ravnica Spoiler Season

Postby moomarc » 01 Oct 2012, 12:36

I've almost got Nivmagus Elemental working. Only problems are with copied spells [Gatherer ruling (hilariously dated 2004 :P )]
You can exile a copy of an instant or sorcery spell to activate Nivmagus Elemental’s ability if you control the copy.
My test cases are Hunting Pack and a Firebolt imprinted on Isochron Scepter.

The first mission was getting the copied spells to show up in the list of choices, but eventually got that right. Then had a problem where if you activated the Nivmagus using the original (in the case of the Hunting Pack) then you wouldn't be able to activate using any of the copies.

Now the only issue I have left is that the copied stack instances aren't exiled. Can I post a patch, or should I commit and someone can look at it then revert if there's no saving it?

With regards to the AI, it won't use the ability unless you cast something in response to a spell it has on the stack... then it will use it every time. It actually works out quite well because often it means you're countering the spell in which case it's a waste anyway. But added the RemAIDeck:True flag anyway.

Edit:
Nivmagus Elemental | Open
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
Patch | Open
Index: src/main/java/forge/card/cost/Cost.java
===================================================================
--- src/main/java/forge/card/cost/Cost.java (revision 17191)
+++ src/main/java/forge/card/cost/Cost.java (working copy)
@@ -161,6 +161,7 @@
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 @@
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);
Index: src/main/java/forge/card/cost/CostExile.java
===================================================================
--- src/main/java/forge/card/cost/CostExile.java (revision 17191)
+++ src/main/java/forge/card/cost/CostExile.java (working copy)
@@ -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.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 @@
*/
@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 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);
+ }
+ }
+ }
}
}

@@ -316,9 +334,18 @@
this.done();
}

- this.typeList = sa.getActivatingPlayer().getCardsIn(part.getFrom());
- this.typeList = this.typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(),
- sa.getSourceCard());
+ if (part.getFrom().equals(ZoneType.Stack)) {
+ this.typeList = new CardList();
+ for (int i = 0; i < AllZone.getStack().size(); i++) {
+ this.typeList.add(AllZone.getStack().peekAbility(i).getSourceCard());
+ this.typeList = this.typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(),
+ sa.getSourceCard());
+ }
+ } else {
+ this.typeList = sa.getActivatingPlayer().getCardsIn(part.getFrom());
+ this.typeList = this.typeList.getValidCards(type.split(";"), sa.getActivatingPlayer(),
+ sa.getSourceCard());
+ }

for (int i = 0; i < nNeeded; i++) {
if (this.typeList.size() == 0) {
@@ -336,6 +363,15 @@
if (i == (nNeeded - 1)) {
this.done();
}
+ if (part.getFrom().equals(ZoneType.Stack)) {
+ ArrayList<SpellAbility> spells = c.getSpellAbilities();
+ if (c.isInZone(ZoneType.Exile)) {
+ for (SpellAbility spell : spells) {
+ final SpellAbilityStackInstance si = AllZone.getStack().getInstanceFromSpellAbility(spell);
+ AllZone.getStack().remove(si);
+ }
+ }
+ }
} else {
this.cancel();
break;
@@ -403,6 +439,8 @@

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(),
Index: src/main/java/forge/card/cost/CostUtil.java
===================================================================
--- src/main/java/forge/card/cost/CostUtil.java (revision 17191)
+++ src/main/java/forge/card/cost/CostUtil.java (working copy)
@@ -37,7 +37,7 @@
*/
public class CostUtil {
private static Random r = new Random();
-
+
/**
* Check sacrifice cost.
*
@@ -457,8 +457,7 @@
// 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 @@
return cost2;
}
}
-
+
if (cost2 == null) {
return cost1;
}
-
+
for (final CostPart part : cost1.getCostParts()) {
if (!(part instanceof CostMana)) {
cost2.getCostParts().add(part);
EDIT2: I noticed in testing that Counterspell also can't counter storm copies. Is this meant to be the case?
-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: Return to Ravnica Spoiler Season

Postby ArsenalNut » 01 Oct 2012, 12:56

Sloth wrote:@ArsenalNut: Why did you change the script of Triangle of War? Your version is no longer AI friendly.
I missed the "TargetsFromDifferentZone$" portion and thought you could target two creatures on the same side.
So many cards, so little time
User avatar
ArsenalNut
 
Posts: 512
Joined: 08 Jul 2011, 03:49
Has thanked: 27 times
Been thanked: 121 times

Re: Return to Ravnica Spoiler Season

Postby Sloth » 01 Oct 2012, 16:24

moomarc wrote:EDIT2: I noticed in testing that Counterspell also can't counter storm copies. Is this meant to be the case?
I will take a look at this. As this is a general problem you can probably commit savely.
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Return to Ravnica Spoiler Season

Postby moomarc » 01 Oct 2012, 16:31

Sloth wrote:
moomarc wrote:EDIT2: I noticed in testing that Counterspell also can't counter storm copies. Is this meant to be the case?
I will take a look at this. As this is a general problem you can probably commit savely.
I've actually changed my code a bit now so that ExileFromStack uses a separate input based on SAs instead of cards. It's working perfectly for the human and was about to test for the AI.

Should I carry on with my current method or revert to how it was before? (well for now I suppose I'll keep both versions locally and see what works best after your fix).
-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: Return to Ravnica Spoiler Season

Postby moomarc » 01 Oct 2012, 17:55

Nivmagus Elemental isworking perfectly now, but just want to check one last thing before committing. Am I correct in thinking that exiling a spell from the stack also exiles the card (unless it's a copied spell)? If so I can commit right now.
-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

PreviousNext

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 14 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 14 users online :: 0 registered, 0 hidden and 14 guests (based on users active over the past 10 minutes)
Most users ever online was 9298 on 10 Oct 2025, 12:54

Users browsing this forum: No registered users and 14 guests

Login Form