Page 1 of 2

spLoseLifeGainLife keyword

PostPosted: 18 Sep 2009, 18:02
by Chris H.
A new keyword, spLoseLifeGainLife. It uses the form:

spLoseLifeGainLife:{num}

I converted the spells Last Caress, Morsel Theft and Soul Feast to use these new keyword. I tested all three cards and they work. The code built without any errors or warnings. I think it is ready.

This code is added to CardFactory.java with the other code which checks for a matching keyword:

Code: Select all
    // spLoseLifeGainLife

   private final int shouldSpLoseLifeGainLife(Card c){
          ArrayList<String> a = c.getKeyword();
          for (int i = 0; i < a.size(); i++)
             if (a.get(i).toString().startsWith("spLoseLifeGainLife"))
                return i;
          
          return -1;
   }
.
This code is added to CardFactory.java with the other code which creates the spell abilities for the keyword cards:

Code: Select all
    //Spell gain life lose life cards (like Soul Feast)
    if (shouldSpLoseLifeGainLife(card)  != -1)
    {
       int n = shouldSpLoseLifeGainLife(card);
       if (n != -1)
       {
           String parse = card.getKeyword().get(n).toString();
          card.removeIntrinsicKeyword(parse);
         
          card.clearSpellAbility();
         
          String k[] = parse.split(":");
          final String lfdmg = k[1];
         
          final SpellAbility spell = new Spell(card)
          {
           private static final long serialVersionUID = -8277174319360648715L;

           public void resolve()
             {
             final int n = Integer.parseInt(lfdmg);
             
                AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(n);
                PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController());
                life.addLife(n);
             }//resolve()
          };//SpellAbility

          spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
          spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));

          card.clearSpellAbility();
          card.addSpellAbility(spell);

          return card;
       }
    }// spLoseLifeGainLife
.
The original code for these spells can be commented out fairly easily:

Code: Select all
    /*
    ////////////////////////////////////////////////////////////
    if (cardName.equals("Soul Feast") || cardName.equals("Last Caress"))
    {
      final SpellAbility spell = new Spell(card)
      {
      private static final long serialVersionUID = -8277174319360648715L;

      public void resolve()
        {
          int n = 4;
         
          if (cardName.equals("Last Caress"))
             n = 1;

          AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(n);
          PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController());
          life.addLife(n);
        }//resolve()
      };//SpellAbility

      spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
      spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));

      card.clearSpellAbility();
      card.addSpellAbility(spell);

      return card;
    }
    //////////////////////////////////////////////////////////
    */

    /*
    ////////////////////////////////////////////////////////////
    if(cardName.equals("Morsel Theft")) // missing Prowl
    {
      final SpellAbility spell = new Spell(card)
      {
      private static final long serialVersionUID = -6361475064894444152L;

      public void resolve()
        {
          int n = 3;


          AllZone.GameAction.getPlayerLife(getTargetPlayer()).subtractLife(n);
          PlayerLife life = AllZone.GameAction.getPlayerLife(card.getController());
          life.addLife(n);
        }//resolve()
      };//SpellAbility

      spell.setChooseTargetAI(CardFactoryUtil.AI_targetHuman());
      spell.setBeforePayMana(CardFactoryUtil.input_targetPlayer(spell));

      card.clearSpellAbility();
      card.addSpellAbility(spell);

      return card;
    }
    //////////////////////////////////////////////////////////
     */
.
The card entries for these three cards located in cards.txt will need to be changed:

Code: Select all
Last Caress
2 B
Sorcery
Target player loses 1 life and you gain 1 life. Draw a card.
spLoseLifeGainLife:1
Cantrip

Morsel Theft
2 B B
Sorcery
Target player loses 3 life and you gain 3 life. (NOTE: "Prowl" is not implemented.)
spLoseLifeGainLife:3

Soul Feast
3 B B
Sorcery
Target player loses 4 life and you gain 4 life.
spLoseLifeGainLife:4

Re: spLoseLifeGainLife keyword

PostPosted: 19 Sep 2009, 19:38
by Chris H.
Abe submitted two cards which can use this keyword. :)

Add this to cards.txt:

Code: Select all
Kiss of Death
4 B B
Sorcery
Kiss of Death deals 4 damage to target opponent. You gain 4 life.
spLoseLifeGainLife:4

Stolen Grain
4 B B
Sorcery
Stolen Grain deals 5 damage to target opponent. You gain 5 life.
spLoseLifeGainLife:5
.
Add this to cards-pictures.txt:
.

Re: spLoseLifeGainLife keyword

PostPosted: 19 Sep 2009, 20:25
by Sloth
Well you shouldn't be able to target yourself with Kiss of Death and Stolen Grain, but it's no big deal.
So if you accept this you can also add:

Code: Select all
Vampiric Feast
4 B B
Sorcery
Vampiric Feast deals 4 damage to target opponent. You gain 4 life.
spLoseLifeGainLife:4

Vampiric Touch
2 B
Sorcery
Vampiric Touch deals 2 damage to target opponent and you gain 2 life.
spLoseLifeGainLife:2

Re: spLoseLifeGainLife keyword

PostPosted: 19 Sep 2009, 20:31
by mtgrares
Thanks for the code. :)

Re: spLoseLifeGainLife keyword

PostPosted: 19 Sep 2009, 21:23
by Chris H.
Sloth wrote:Well you shouldn't be able to target yourself with Kiss of Death and Stolen Grain, but it's no big deal.
So if you accept this you can also add:
Rob mentioned that he planned at some point to do a life gaining keyword. :-k I wonder if this future keyword would have a parameter to handle these spells.

Rob, what do you think? Would you like to hold off on these 4 spells for now and add them at a later time?

Re: spLoseLifeGainLife keyword

PostPosted: 21 Sep 2009, 01:46
by Rob Cashwalker
I'm working on an expanded damage spell which includes the "draw back" of gaining life.

Also, damage and loss of life need to be separate, because we may have effects that can trigger off damage.. or we might someday....

Re: spLoseLifeGainLife keyword

PostPosted: 21 Sep 2009, 09:43
by silly freak
i'd say we should have different methods for that, but can make them work the same (damage() calling loseLife() or such) as long as there's no difference. when there's a change, we don't have to track it in card factory

Re: spLoseLifeGainLife keyword

PostPosted: 21 Sep 2009, 10:24
by Chris H.
While I was constructing the keyword, I wondered about the targeting issue. Soul Feast allows you to target yourself. I can't at this time come up for a reason to do this, but things could change at some point in the future.

Re: spLoseLifeGainLife keyword

PostPosted: 21 Sep 2009, 17:59
by Rob Cashwalker
I can revise it in the future when I apply some more abstraction to some existing keywords. Like the number of life on Tendrils of Corruption is a variable that I can calculate like in spDrawCards. I'm in the middle of tweaking some of that code into a generic CountX function that is to be reused in my revised spDamage code and multiple other places.

Re: spLoseLifeGainLife keyword

PostPosted: 22 Sep 2009, 06:38
by Marek14
Chris H. wrote:While I was constructing the keyword, I wondered about the targeting issue. Soul Feast allows you to target yourself. I can't at this time come up for a reason to do this, but things could change at some point in the future.
Mindslaver.

Re: spLoseLifeGainLife keyword

PostPosted: 22 Sep 2009, 11:01
by Chris H.
Marek14 wrote:Mindslaver.
Yeah, that is an interesting card. It may be next to impossible to implement in Forge. :)

Re: spLoseLifeGainLife keyword

PostPosted: 23 Sep 2009, 08:00
by Marek14
Chris H. wrote:
Marek14 wrote:Mindslaver.
Yeah, that is an interesting card. It may be next to impossible to implement in Forge. :)
You know, people always say that, but is it really true? If a Human uses it, he just gains control of the decision - AI is off for one turn. If AI uses it, it's in complete control for one turn, can use your resources, but its goal is still to better itself.

Re: spLoseLifeGainLife keyword

PostPosted: 26 Sep 2009, 00:14
by zerker2000
Chris H. wrote:While I was constructing the keyword, I wondered about the targeting issue. Soul Feast allows you to target yourself. I can't at this time come up for a reason to do this, but things could change at some point in the future.
Transcendence

Re: spLoseLifeGainLife keyword

PostPosted: 26 Sep 2009, 16:26
by Marek14
And, of course, Deflection.

Re: spLoseLifeGainLife keyword

PostPosted: 13 Dec 2009, 19:47
by Chris H.
I have discovered a problem with this keyword and the new spell Absorb Vis. The spLoseLifeGainLife keyword does not contain code to create the card description and uses the text from cards.txt.

As such, when you cast Absorb Vis you are not given a choice between the spell and cycling. In fact, the cycling ability is completed ignored. This is my fault. I can only plead ignorance as I am still learning how to code at this time. :oops:

I am now trying to fix the spLoseLifeGainLife keyword so that it will work correctly in this fashion. This in turn brings up a second issue.

Currently, the spells Kiss of Death; Stolen Grain and Vampiric Touch use the spLoseLifeGainLife keyword. I think that they should be removed from the spLoseLifeGainLife keyword code base.

There are two options that I am considering. One would be to make a few mods to the spLoseLifeGainLife keyword and create a spOppDamGainLife keyword. Or Rob's spDamageTgt keyword code code be changed to allow a spDamageTgtOpp variant.