It is currently 08 Sep 2025, 05:32
   
Text Size

Ability_Cost Usage

Post MTG Forge Related Programming Questions Here

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

Ability_Cost Usage

Postby friarsol » 16 Sep 2010, 21:31

So I've done a bunch of work on Ability_Cost in the last two weeks, so I figure I should post about it so people can start adding it in cards, and use it with new keywords.

Ability_Cost has some sweeping changes that override the old setBeforePayMana and setAfterPayMana system. The old system limited how much we could do before an ability was put onto the stack. This limitation led to a lot of cards having costs get paid during resolution and some of them would peak at the stack to prevent you from using an ability if you had already used it.

One of the first cards that irritated me about this was Tradewind Rider. The Rider would tap and go on the stack. But you'd have to wait to resolution to tap your other two creatures. If you didn't have two creatures available to tap on resolution, well your game would be in a dead state that you'd have to concede to get out of. Rider has recently been moved to the abCost system yet. And he's a big reason why it exists right now.

This system is centralized so hopefully we can get a ton of our abilities to run through the same gateway. Not only will it make finding bugs easier, it should make how the player pays for things more consistent.

To my knowledge the following keywords support using abCost instead of just ManaCost:
Code: Select all
abAllPump
abDamageTgt
abDestroyTgt
abPump[Tgt]
The Costs currently supported are: Tap, Untap, Mana, SubtractCounter, Sacrifice, PayLife, Discard, TapXUntapped(Thanks Dennis).

No Parameters:
T
Untap
Mana

Parameters:
tapXType<NumTap/ValidCard>
SubCounter<NumCounters/CounterType>
Sac<NumSacrifices/ValidCard>
PayLife<NumLife>
Discard<NumDiscards/{Hand,Random,Any,ValidCard}

I'll give a sample of just the keyword line for each cost:
Code: Select all
Tap (Prodigal Sorcerer)
K:abDamageTgtCP T:1

Mana + Untap (Merrow Grimeblotter)
K:abPumpTgtC 1 UB Untap:-2/-0

SubtractCounter (Triskelion)
K:abDamageTgtCP SubCounter<1/P1P1>:1

SacrificeType (Atog)
K:abPump Sac<1/Artifact>:+2/+2

SacrificeThis (Fires of Yavimaya)
K:abPumpTgtC Sac<1/CARDNAME>:+2/+2

PayLife (Reckless Assault)
K:abDamageTgtCP 1 PayLife<2>:1

Discard Any (Kris Mage)
K:abDamageTgtCP R T Discard<1/Any>:1

Discard Random (Stormbind)
K:abDamageTgtCP 2 Discard<1/Random>:2

Discard Type (Seismic Assault)
K:abDamageTgtCP 2 Discard<1/Land>:2

Discard Hand (Null Brooch)
K:abCounterTgt 2 Discard<0/Hand>:nonCreature
(Note: abCounterTgt is not a keyword. The number given with Hand is ignored.)

Tap X Untapped (Hand of Justice)
K:abDestroyTgtV T tapXType<3/Creature.White>:Creature:Destroy target creature.
But here are some more costs that seem to appear with some regularity. I'm sure these will be created at some point in the near future.

Code: Select all
Exile Self/<Type>
AddCounter
Mill X
Exile from grave/library
Edit
For those who want to try to make some of the other costs here's a few things to keep in mind. Actions that are easily undoable (tapping cards, paying mana) should happen before things that aren't really undoable (sacrificing lands, discarding cards). Also, we should try to keep payments in the same order as they appear on actual cards. Sometimes it's tough to hunt down what goes where. Paying Mana comes first. Sacrifice always seems to come last, which makes whatever cost you are doing somewhere in the middle.
The cost is also built by the class, so don't forgot about adding some code into the toString() section to display the cost to the player.
/EndEdit

Now if you plan on making a new keyword, or updating an old one with abCost just make sure you also use the new Target class if the ability is targeted. Since setBeforePayMana isn't used anymore, we need to make sure Targeting is taken care of. Otherwise, your abilities probably won't do anything at all.

Your best bet is to check out how it works in abDamageTgt or abDestroyTgt. It's actually not that hard, and a large portion of Targets from here on out should be using the Valid Target portion of the class.

Quick brief on using the Target class.
Either use the set Tgt Paramters {C}{P} like abDamage does. These you don't need to set any extra parameters. The code will handle asking for the target at the appropriate time.
Code: Select all
final Target tgt = new Target("TgtCP");
final Target tgt = new Target("TgtC");
final Target tgt = new Target("TgtP");
If you want to use the Valid options, which funnels through the IsValidCard(restriction) function. For Seal of Cleansing the data would look like this:
Code: Select all
K:abDestroyTgtV Sac<1/CARDNAME>:Artifact,Enchantment
The Artifact,Enchantment will get parsed in the Ability code, and set to Target in this code taken from abDestroy.

Code: Select all
final String Tgts[] = k[1].split(",");
final Target tgtDstryTgt = new Target("TgtV");
tgtDstryTgt.setValidTgts(Tgts);
After you create an Ability_Cost and Target in an Ability make sure you set them for the ability. This is very important.

In abDestroy, that looks like this:
Code: Select all
AbDstryTgt.setPayCosts(abCost);
AbDstryTgt.setTarget(tgtDstryTgt);
Hopefully that's a decent primer for anyone who is going to use it.

I'm going to take a break from doing any major abCost updates to work on some other things on the project. So lemme know if you have any questions when trying the new Classes out.
Last edited by friarsol on 17 Sep 2010, 16:31, edited 3 times in total.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost Usage

Postby Sloth » 17 Sep 2010, 05:30

Thanks a lot for this code and primer friarsol!

I guess hundrets of cards can be added, using your Ability_Cost and Target class. =D>

Chapeau!
User avatar
Sloth
Programmer
 
Posts: 3498
Joined: 23 Jun 2009, 19:40
Has thanked: 125 times
Been thanked: 507 times

Re: Ability_Cost Usage

Postby DennisBergkamp » 17 Sep 2010, 06:49

Cool stuff, I'll play around with it, and see if I can add some new functionality :)
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Ability_Cost Usage

Postby DennisBergkamp » 17 Sep 2010, 08:44

Alright, I've played around with this for a bit and I think I have some beginnings for Tradewind Rider (it seems to work so far, anyway - but it still doesn't work exclusively through keywords).
Maybe you could look at some of the code I've added for this, friarsol, and make sure it's all correct.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Ability_Cost Usage

Postby Chris H. » 17 Sep 2010, 10:21

This is interesting. It may take me awhile to absorb all of this, but I like what I see so far. I have managed to add a few of Rob's new abDestroyTgt cards.

Oh, and a question. Will this new Ability_Cost system make the old setBeforePayMana and setAfterPayMana systems obsolete?
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Ability_Cost Usage

Postby Rob Cashwalker » 17 Sep 2010, 11:25

This is not exactly a "one class fits all" solution. But it is mutually exclusive. Using Ability_Cost will require using the Target class. Likewise, I don't think the Target class can be used without the Ability_Cost... yet. Checkout GameAction.PlaySpellAbility to see how it works.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Ability_Cost Usage

Postby friarsol » 17 Sep 2010, 16:25

DennisBergkamp wrote:Alright, I've played around with this for a bit and I think I have some beginnings for Tradewind Rider (it seems to work so far, anyway - but it still doesn't work exclusively through keywords).
Maybe you could look at some of the code I've added for this, friarsol, and make sure it's all correct.
Looks solid. I moved the location of the keyword before SubCounter (in a few spots) because Coral Reef has the tapping cost before a remove counter cost. And I think it'd be best if we try to keep all of the costs consistent with how the costs appear in Oracle. I think I added one or two lines as precautionary measures. I also added in a section for building the cost for the string description.
I hadn't really mentioned those before, so overall great job!

The only thing left for this Cost would be to fill out the CancelPayment for it. It's usable now without being able to undo it, but it's always handy to have a way to backtrack if you tap the wrong card.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost Usage

Postby DennisBergkamp » 17 Sep 2010, 16:44

Thanks, I didn't forget about the cancel payment, but didn't have time... I'll add it (shouldn't be too difficult).
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Ability_Cost Usage

Postby DennisBergkamp » 18 Sep 2010, 20:42

Rob Cashwalker wrote:This is not exactly a "one class fits all" solution. But it is mutually exclusive. Using Ability_Cost will require using the Target class. Likewise, I don't think the Target class can be used without the Ability_Cost... yet. Checkout GameAction.PlaySpellAbility to see how it works.
Unless there's no target, of course, just using Ability_Cost seems to work fine with Voice of the Woods.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Ability_Cost Usage

Postby friarsol » 18 Sep 2010, 20:57

DennisBergkamp wrote:
Rob Cashwalker wrote:This is not exactly a "one class fits all" solution. But it is mutually exclusive. Using Ability_Cost will require using the Target class. Likewise, I don't think the Target class can be used without the Ability_Cost... yet. Checkout GameAction.PlaySpellAbility to see how it works.
Unless there's no target, of course, just using Ability_Cost seems to work fine with Voice of the Woods.
Yea I think Rob was more implying that if there is a target and you want to use abCost you have to use the Target class with it. With abPump creatures that Pump themselves like Atog, there isn't a need to run through the Target Selection process.

You and Chris have been like workhorses putting all these cards together. That's good motivation for adding in big projects like abCost were.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times


Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 43 guests

Main Menu

User Menu

Our Partners


Who is online

In total there are 43 users online :: 0 registered, 0 hidden and 43 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 43 guests

Login Form