It is currently 06 Jun 2024, 04:10
   
Text Size

Ability_Cost discussion

Post MTG Forge Related Programming Questions Here

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

Re: Ability_Cost discussion

Postby friarsol » 15 Sep 2010, 01:22

Rob Cashwalker wrote:friarsol,

I've added "TgtV" and some support functionality for it. However I'm not sure how to adapt CardFactoryUtil.input_targetValid like targetPlayer, etc. Could you pickup from where I left off in r2056?
Sure thing. It looked like you were mostly there, just needed to pass in SpellAbility_Requirements so the finishedTargeting could be called on done() or cancel().

I'll poke through tomorrow and see if I can get it working so you can finish up your keyword.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost discussion

Postby Rob Cashwalker » 15 Sep 2010, 02:34

Precisely...

I tried just linking to the original CardFactoryUtil, I didn't realize what the difference between your Inputs, and the original ones.
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 discussion

Postby friarsol » 15 Sep 2010, 16:24

Alright I just submitted r2073. You should be able to just attach your ability right up. I added a little bit of code in abDamage to make it compatible with Targets and the V parameter.

There really was only three lines to make it compatible, the rest of it was making sure Drawback was accounted for differently if we were taking a parameter for targeting.

Don't forget to set ValidTgts Array after the Target object is made. Better yet, just create a second constructor that takes them on creation.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost discussion

Postby Rob Cashwalker » 15 Sep 2010, 18:17

I actually got it all to work with what I had, except for the sacrifice cost, because the cost_payment didn't have the correct input, I was trying to use the old CardFactoryUtil one.
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 discussion

Postby Rob Cashwalker » 16 Sep 2010, 00:04

Well, now it asks to sacrifice twice, and it shows up on the stack twice.

Here's my ability
Code: Select all
        // Generic destroy target ___ activated ability
        if (hasKeyword(card, "abDestroyTgtV") != -1)
        {
           int n = hasKeyword(card, "abDestroyTgtV");
           
           String parse = card.getKeyword().get(n).toString();
           card.removeIntrinsicKeyword(parse);
           
           String k[] = parse.split(":");
           
           String tmpCost = k[0].substring(13);
           final Ability_Cost abCost = new Ability_Cost(tmpCost, card.getName(), true);
           
           final Target tgtDstryTgt = new Target("TgtV");
           final String Tgts[] = k[1].split(",");
           tgtDstryTgt.setValidTgts(Tgts);
           
           final boolean NoRegen[] = {false};
           final String Drawback[] = {"none"};
           final String spDesc[] = {"none"};
           
           if (k[2].equals("NoRegen"))
           {
              NoRegen[0] = true;
              
              if (k.length > 3)
              {
                 if (k[3].startsWith("Drawback$"))
                    Drawback[0] = k[3].substring(9);
                 else
                    spDesc[0] = k[3];
              }
           }
           else if (k[2].startsWith("Drawback$"))
           {
              Drawback[0] = k[2].substring(9);
              
              if (k.length > 3)
                 spDesc[0] = k[3];
           }
           else
              spDesc[0] = k[2];
           
           String tmpDesc = spDesc[0].substring(15);
           int i = tmpDesc.indexOf(".");
           tmpDesc = tmpDesc.substring(0, i);
           //final String Selec = "Select target " + tmpDesc + " to destroy.";
           tgtDstryTgt.setVTSelection("Select target " + tmpDesc + " to destroy.");
           
           spDesc[0] = abCost.toString() + spDesc[0];
           
           final SpellAbility AbDstryTgt = new Ability_Activated(card, abCost.getMana())
           {
              private static final long serialVersionUID = -141142183348756081L;
              
                @Override
                public boolean canPlayAI() {
                    if (!ComputerUtil.canPayCost(this))
                       return false;
                   
                    CardList hCards = getTargets();
                   
                    hCards = hCards.filter(new CardListFilter(){
                       public boolean addCard(Card c)
                       {
                          return !c.getKeyword().contains("Indestructible");
                       }
                    });
                   
                    Random r = new Random();
                    boolean rr = false;
                    if (r.nextFloat() <= Math.pow(.6667, card.getAbilityUsed()))
                       rr = true;
                   
                    if(hCards.size() > 0) {
                       Card c = null;
                       CardList dChoices = new CardList();
                       
                        for(int i = 0; i < Tgts.length; i++) {
                           if (Tgts[i].startsWith("Creature"))
                           {
                              c = CardFactoryUtil.AI_getBestCreature(hCards);
                              if (c != null)
                                 dChoices.add(c);
                           }
                           
                           CardListUtil.sortByTextLen(hCards);
                           dChoices.add(hCards.get(0));
                           
                           CardListUtil.sortCMC(hCards);
                           dChoices.add(hCards.get(0));
                        }
                       
                        c = dChoices.get(CardUtil.getRandomIndex(dChoices));
                        setTargetCard(c);
                       
                        return rr;
                    }
                   
                    return false;
                }
               
                CardList getTargets() {
                    CardList tmpList = new CardList();
                    tmpList.addAll(AllZone.Human_Play.getCards());
                    tmpList = tmpList.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return (CardFactoryUtil.canTarget(card, c));
                        }
                    });
                   
                    return tmpList.getValidCards(Tgts);
                }
               
                @Override
                public boolean canPlay(){
                   Cost_Payment pay = new Cost_Payment(abCost, this);
                    return (pay.canPayAdditionalCosts() && CardFactoryUtil.canUseAbility(card) && super.canPlay());
                }

               
                @Override
                public void resolve()
                {
                   Card tgtC = getTargetCard();
                    if(AllZone.GameAction.isCardInPlay(tgtC) && CardFactoryUtil.canTarget(card, tgtC))
                    {
                       if(NoRegen[0])
                          AllZone.GameAction.destroyNoRegeneration(tgtC);
                       else
                          AllZone.GameAction.destroy(tgtC);
                       
                       if (!Drawback[0].equals("none"))
                          CardFactoryUtil.doDrawBack(Drawback[0], 0, card.getController(), AllZone.GameAction.getOpponent(card.getController()), tgtC.getController(), card, tgtC, this);
                    }
                }

           }; //AbDstryTgt
           
           AbDstryTgt.setPayCosts(abCost);
           
           //Input InGetTarget = CardFactoryUtil.input_targetValid(AbDstryTgt, Tgts, Selec);
           
            //AbDstryTgt.setBeforePayMana(InGetTarget);
            AbDstryTgt.setTarget(tgtDstryTgt);
           
           AbDstryTgt.setDescription(spDesc[0]);
           
           card.addSpellAbility(AbDstryTgt);
           card.setSVar("PlayMain1", "TRUE");
        }
and the test card:
Code: Select all
Name:Daraja Griffin
ManaCost:3 W
Types:Creature Griffin
Text:no text
PT:2/2
K:Flying
K:abDestroyTgtV 0 Sac-CARDNAME:Creature.Black:Destroy target black creature.
K:SVar:Picture:http://www.wizards.com/global/images/magic/general/daraja_griffin.jpg
K:SVar:Rarity:Uncommon
End
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 discussion

Postby friarsol » 16 Sep 2010, 04:43

I took your code straight up and it worked without double sacrificing and double adding to the stack for me. You shouldn't need to change anything in Cost_Payment, but your last post implies that you might have?

What are your changes there? Maybe that's what's causing the double sacrifice. There really shouldn't be a reason to change anything there, since everything was working before.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost discussion

Postby Rob Cashwalker » 16 Sep 2010, 10:54

OK... I changed the deck I was testing against. I was testing against Deathgreeter. Testing against Stone-Throwing Devils works fine.
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 discussion

Postby friarsol » 16 Sep 2010, 14:03

That does reveal a clash between the Whenever keyword and Cost_Payment. I'll look into it and see what's going on.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost discussion

Postby Rob Cashwalker » 16 Sep 2010, 15:06

Question though, why do you throw up a yes/no prompt for the sac cost?
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 discussion

Postby friarsol » 16 Sep 2010, 15:34

Rob Cashwalker wrote:Question though, why do you throw up a yes/no prompt for the sac cost?
Well, if you click on a card by accident (or thought you were in the attack phase but weren't) it won't automatically sacrifice itself if that is the only cost. I would be pretty frustrated if I was trying to block with a Bottle Gnomes and all of a sudden it was in my graveyard instead of blocking.

Most of the other costs have a way to cancel out of them if you misclicked/changed your mind. But SacThis and PayLife do not. SubCounters doesn't either I guess, but that doesn't have a Popup. I guess losing a permanent, or losing life have a much stronger game state influence in my mind than just losing a counter from a permanent.

If there is enough support for tweaking the popups, we can change it based on what people want. Maybe if a cost with a prompt is the first cost we'll ask the user. But if they already had a chance to cancel out then just go through with it?
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost discussion

Postby Rob Cashwalker » 16 Sep 2010, 21:07

Why not use the prompt text box with Cancel and OK on the top-left? That way the OK (default) would react to the space bar.
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 discussion

Postby friarsol » 16 Sep 2010, 21:27

Probably cause I hadn't even considered it. I'll take a look and see if I can switch the prompt into an Input_Prompt. Hopefully it won't be too terrible.
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Ability_Cost discussion

Postby Rob Cashwalker » 16 Sep 2010, 21:38

Suggestion - Use "Q" for untap cost, as it is the official abbreviation.

And if you're not doing it right now, you should also throw together a brief on usage of Target, since you mention its requirement in the other abCost thread.
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 discussion

Postby zerker2000 » 17 Sep 2010, 06:37

Would it be at all possible to group all the "ab" keywords?
I'm still not cured of my romantics about
Comp. rule 602.1 wrote:"[Cost]: [Effect.] [Activation instructions (if any).]"
O forest, hold thy wand'ring son
Though fears assail the door.
O foliage, cloak thy ravaged one
In vestments cut for war.


--Eladamri, the Seed of Freyalise
zerker2000
Programmer
 
Posts: 569
Joined: 09 May 2009, 21:40
Location: South Pasadena, CA
Has thanked: 0 time
Been thanked: 0 time

Re: Ability_Cost discussion

Postby Rob Cashwalker » 17 Sep 2010, 11:21

Sure, it's plausible, but very difficult. There needs to be dedicated AI for each effect. The best we're going to have is a more dynamic framework for parsing the keywords.
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

PreviousNext

Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 17 guests


Who is online

In total there are 17 users online :: 0 registered, 0 hidden and 17 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: No registered users and 17 guests

Login Form