It is currently 06 Jun 2024, 07:37
   
Text Size

Attempt at Rebound

Post MTG Forge Related Programming Questions Here

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

Attempt at Rebound

Postby Hellfish » 30 Oct 2010, 18:58

So I am currently poking at the Rebound keyword and,well, so far so good. The card exiles properly without going to the graveyard and gets cast again your next upkeep. There is a problem I've been banging my head on for a while,though, namely that the card keeps it's target (I've been testing with Staggershock) for the second casting. i.e. if I target an Ornithopter and send it to the graveyard, at my next upkeep it will cast for free and try to target the same Ornithopter(still in the graveyard) without setting a targeting input state. I've been trawling through the SpellAbility,Target and GameActionUtil classes to figure out why it skips the input state or how I can reset the targeting.I would greatly appreciate it if anyone with more insight into those classes has any ideas to share.

The code so far:
GameActionUtil.java:
Code: Select all
   public static CardList Rebounded_Human = new CardList();
   public static CardList Rebounded_AI = new CardList();
   
   public static void executeUpkeepEffects() {

      if(AllZone.GameAction.isPlayerTurn(AllZone.HumanPlayer))
      {
         for(Card c : Rebounded_Human)
         {
            AllZone.GameAction.playCardNoCost(c); //Same method that cascade uses
         }
         
         Rebounded_Human.clear();
      }
      else
      {
         for(Card c : Rebounded_AI)
         {
            if(c.getSpellAbility()[0].canPlayAI())
            {
               AllZone.GameAction.playCardNoCost(c);
            }
         }
         Rebounded_AI.clear();
      }
...Nothing changed afterwards...
in CardFactory.java:
Code: Select all
        if(hasKeyword(card,"Rebound") != -1) {
           final Command graveyardReplacer = new Command() {
            private static final long serialVersionUID = 1489845860231758299L;

            public void execute() {
                 AllZone.GameAction.exile(card);
                 if(card.getController() == AllZone.HumanPlayer)
                 {
                    GameActionUtil.Rebounded_Human.add(card);
                 }
                 else
                 {
                    GameActionUtil.Rebounded_AI.add(card);
                 }
                 card.clearReplaceMoveToGraveyardCommandList();
              }
           };
           
           card.addReplaceMoveToGraveyardCommand(graveyardReplacer);
           
        }
staggershock.txt
Code: Select all
Name:Staggershock
ManaCost:2 R
Types:Instant
Text:no text
A:SP$DealDamage|Cost$2 R|Tgt$TgtCP|NumDmg$2|SpellDescription$CARDNAME deals 2 damage to target creature or player.
K:Rebound
End
Note that this will still fail if you bring back the card from the graveyard after it has rebounded. It won't rebound a second time. I'm looking at ZCTriggers to fix that,though.Also, the AI playing for free is probably incorrect ATM. But the targeting is the big deal right now. =P
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times

Re: Attempt at Rebound

Postby Chris H. » 30 Oct 2010, 19:54

Dennis came accross a similar problem with Flashback. Flashback would work correctly only for spells that did not target. We have a Flashback keyword that currently only works for non-targeted spells.

For targeted Flashback spells, Denenis came up with a hack of sorts. Check out Strangling Soot and Firebolt. It is possible that you could try something similar. It might be worth it to look at these two spells.
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: Attempt at Rebound

Postby friarsol » 30 Oct 2010, 21:46

It's probably easier than that. We can just clear out the target state after the spell resolves right around the same time that it would goto the graveyard (or wherever). We could do this for ALL spells, and that way Flashback or Rebound (or anything) wouldn't just reuse the same old target if it still remembers it.

My Phase work moved where ResolveStack is occurring (it's now in the MagicStack object) so I could add in a block that can reset the Target there. If you need more immediate satisfaction, just look here
Code: Select all
if (sa.isFlashBackAbility())
   c.replaceMoveToGraveyard();
and do something like this right before it:
Code: Select all
sa.setTargetPlayer(null);
sa.setTargetCard(null);
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Attempt at Rebound

Postby DennisBergkamp » 30 Oct 2010, 23:27

Hmm, for Flashback, I don't think it was using the same target, but it was just that the targeting didn't happen at all.
I don't remember exactly though, it was a long time ago.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Attempt at Rebound

Postby friarsol » 30 Oct 2010, 23:56

Wait a second. This problem is actually somewhere else.

It looks like playCardNoCost() calls playSpellAbilityForFree() which doesn't have a block of code for handling Spells that use the Target object. That probably means that Cascade is currently broken for any Spells that use the Target object. The solution then would be to add a block in the beginning of playSellAbilityForFree() that looks something like this:

Code: Select all
sa.setActivatingPlayer(AllZone.HumanPlayer);
if (sa.getPayCosts() != null){
   Target_Selection ts = new Target_Selection(sa.getTarget(), sa);

       Ability_Cost abCost = sa.getPayCosts();
        abCost.changeCost(sa);
        abCost.setMana("0");
   Cost_Payment payment = new Cost_Payment(abCost, sa);
   
   SpellAbility_Requirements req = new SpellAbility_Requirements(sa, ts, payment);
   req.fillRequirements();
}
else
// the rest of the funcion here
Also, I'm pretty sure these functions above are for Humans only. The AI should use something in ComputerUtil. Although it seems like those functions aren't as up-to-date as they should be.

I also just realized. Will this create an infinite rebound spell?
Technically, a spell will only rebound if you cast it from your hand (not from exile or the grave or the library).
friarsol
Global Moderator
 
Posts: 7593
Joined: 15 May 2010, 04:20
Has thanked: 243 times
Been thanked: 965 times

Re: Attempt at Rebound

Postby Hellfish » 31 Oct 2010, 10:23

True, I converted Lightning Bolt to use AbilityFactories and failed to cascade into it as predicted. However, with the fixed codeblock at the beginning of playSpellAbilityForFree, there is a NullPointerException in SpellAbility_Requirements when it tries to get the zone of the card that was paid for free.(It is removed from the library before playcardNoCost is called) I fixed this by actually making the code more true to the actual mechanic, in that it now exiles cards until a suitable one is found, instead of only removing them from the library without adding them anywhere else. It still however, does this when the Rebound code tries to playCardNoCost, so somewhere the card is being removed from exile without being added anywhere else. I've looked but there's not many places between playCardNoCost and fillRequirements where it can happen.

I have another appointment atm, so this post is as much for meyself get back as anything else. :mrgreen:

EDIT: fillRequirements() gets called twice when the card is cast from exile, for some reason...
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
User avatar
Hellfish
Programmer
 
Posts: 1297
Joined: 07 Jun 2009, 10:41
Location: South of the Pumphouse
Has thanked: 110 times
Been thanked: 169 times


Return to Developer's Corner

Who is online

Users browsing this forum: No registered users and 51 guests


Who is online

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

Login Form