Attempt at Rebound
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins
Attempt at Rebound
by 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:
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...
- 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);
}
- 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
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
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
-
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
by 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.
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.
-
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
by 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
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();
- 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
by 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.
I don't remember exactly though, it was a long time ago.
-
DennisBergkamp - AI Programmer
- Posts: 2602
- Joined: 09 Sep 2008, 15:46
- Has thanked: 0 time
- Been thanked: 0 time
Re: Attempt at Rebound
by 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:
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).
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
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
by 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.
EDIT: fillRequirements() gets called twice when the card is cast from exile, for some reason...
I have another appointment atm, so this post is as much for meyself get back as anything else.
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
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
-
Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
6 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 51 guests