Page 1 of 1

[Fix]Legion's Initiative crashes,once fixed no exile & haste

PostPosted: 18 Sep 2020, 10:08
by FastEddie
Describe the Bug:
Legion's Initiative has two issues:
    Activate the ability and the game will crash. The required fix is attached.
    Once this is fixed it doesn't give haste (to check play the Savannah Lions beforehand). Instead it plays the first card in my hand (Lightning Bolt).

Which card behaved improperly?
Legion's Initiative

Which update are you using? (date, name)Which type? (duel, gauntlet, sealed deck)
Version 8-2020 a62926f
Duel

What exactly should be the correct behavior/interaction?
Creatures should be exiled and return with haste.

Are any other cards possibly affected by this bug?
No.

The reason for the crash is that the loop counts in the wrong direction. The relevant fixed code piece is:

Code: Select all
         int i;
         for(i=150; i>-1; i--){ // <-- was i++ before
            if( marked[i] ){

Re: Legion's Initiative: crashes, once fixed doesn't give ha

PostPosted: 18 Sep 2020, 17:24
by Aswan jaguar
Of course to begin with it doesn't exile the creatures so it can return them back at least once crash is fixed ( I didn't test crash at all applied fix at once and tested then. edited

Re: [con]Legion's Initiative crashes,once fixed no exile & h

PostPosted: 20 Sep 2020, 06:36
by drool66
I don't have a dev environment so I can't test anything, but I see several problems with this card.

Code: Select all
               leg->targets[removed_count].player = get_owner(player, marked[i]);
               leg->targets[removed_count].card = get_original_internal_card_id(player, marked[i]);
               removed_count++;
               kill_card(player, marked[i], KILL_EXILE);
should probably be:
Code: Select all
               leg->targets[removed_count].player = get_owner(player, i);
               leg->targets[removed_count].card = get_original_internal_card_id(player, i);
               removed_count++;
               kill_card(player, i, KILL_EXILE);
This would explain the creatures not being exiled.

Secondly, the legacy shouldn't check current_turn==player, since the card says the creatures return at the beginning of the next combat, without specifying whose.

I have no idea why targets[0] is checked, and the value assignment really seems misplaced.

Instead of using give_haste() the legacy should probably use pump_ability_until_eot(). give_haste() itself says "Avoid!" and I believe just removes summoning sickness without actually giving haste.

The card probably also suffers from the "beginning of combat" problem, where it will not trigger if there are no creatures that can attack. It would be really nice if we could find a solution to this.

I would implement & test the changes myself but I don't have my dev computer; I hope this is somewhat accurate & helpful.

Re: [con]Legion's Initiative crashes,once fixed no exile & h

PostPosted: 20 Sep 2020, 08:44
by Aswan jaguar
The code you attached works, I followed your suggestions. I was aware of the current_turn issue but not of haste one. I used beginning_combat() and everything works fine haste in time to attack. It works fine also with stolen creatures which was implemented correctly.

Current code if anyone else wants to check something:
Code: Select all
static int legions_initiative_legacy(int player, int card, event_t event){
   if (beginning_of_combat(player, card, event, ANYBODY, -1) && get_card_instance(player, card)->targets[0].card != 66 )
   {
         card_instance_t *instance = get_card_instance(player, card);
         instance->targets[0].card = 66;
         int i;
         for(i=1; i<19; i++){
            int owner = instance->targets[i].player;
            int iid = instance->targets[i].card;
            if( owner > -1 ){
               if( check_rfg(owner, cards_data[iid].id) ){
                  int card_added = add_card_to_hand(owner, iid);
                  remove_card_from_rfg(owner, cards_data[iid].id);
                  put_into_play(owner, card_added);
                   pump_ability_until_eot(player, card, owner, card_added, 0, 0, 0, SP_KEYWORD_HASTE);
               }
            }
         }
         kill_card(player, card, KILL_EXILE);   
   }

   return 0;
}

int card_legions_initiative(int player, int card, event_t event){
/*
Legion's Initiative |W|R
Enchantment
Red creatures you control get +1/+0.
White creatures you control get +0/+1.
{R}{W}, Exile Legion's Initiative: Exile all creatures you control. At the beginning of the next combat,
      return those cards to the battlefield under their owner's control and those creatures gain haste until end of turn.
*/
   boost_creature_by_color(player, card, event, get_sleighted_color_test(player, card, COLOR_TEST_RED), 1, 0, 0,
                     BCT_CONTROLLER_ONLY | BCT_INCLUDE_SELF);

   boost_creature_by_color(player, card, event, get_sleighted_color_test(player, card, COLOR_TEST_WHITE), 0, 1, 0,
                     BCT_CONTROLLER_ONLY | BCT_INCLUDE_SELF);

   if( IS_GAA_EVENT(event) ){
      if( event == EVENT_RESOLVE_ACTIVATION ){
         int marked[151] = {0};
         CYCLE_ALL_CARDS(p, c,    {
                              if( p == player && in_play(p, c) && is_what(p, c, TYPE_CREATURE) && ! is_token(p, c) ){
                                 marked[c] = 1;
                              }
                           };
         );
         int legacy = -1;
         int removed_count = 1;
         int i;
         for(i=150; i>-1; i--){
            if( marked[i] ){
               if( legacy == -1 ){
                  legacy = create_legacy_effect(player, card, &legions_initiative_legacy);
               }
               if( removed_count > 18 ){
                  legacy = create_legacy_effect(player, card, &legions_initiative_legacy);
                  removed_count = 1;
               }
               card_instance_t *leg = get_card_instance(player, legacy);
               leg->targets[removed_count].player = get_owner(player, i);
               leg->targets[removed_count].card = get_original_internal_card_id(player, i);
               removed_count++;
               kill_card(player, i, KILL_EXILE);
            }
         }
      }
      return generic_activated_ability(player, card, event, GAA_RFG_ME, MANACOST_RW(1, 1), 0, NULL, NULL);
   }

   return global_enchantment(player, card, event);
}
Edit: Fixed in commit: 7d28e0. Cooperation of 3 devs this one. :D

Re: [Fix]Legion's Initiative crashes,once fixed no exile & h

PostPosted: 20 Sep 2020, 15:35
by drool66
Awesome!

I'm glad you posted the code because I just noticed one more thing: it looks like it doesn't exile creature tokens at all. If it doesn't, it would just be:
Code: Select all
int card_legions_initiative(int player, int card, event_t event){
/*
Legion's Initiative |W|R
Enchantment
Red creatures you control get +1/+0.
White creatures you control get +0/+1.
{R}{W}, Exile Legion's Initiative: Exile all creatures you control. At the beginning of the next combat,
      return those cards to the battlefield under their owner's control and those creatures gain haste until end of turn.
*/
   boost_creature_by_color(player, card, event, get_sleighted_color_test(player, card, COLOR_TEST_RED), 1, 0, 0,
                     BCT_CONTROLLER_ONLY | BCT_INCLUDE_SELF);

   boost_creature_by_color(player, card, event, get_sleighted_color_test(player, card, COLOR_TEST_WHITE), 0, 1, 0,
                     BCT_CONTROLLER_ONLY | BCT_INCLUDE_SELF);

   if( IS_GAA_EVENT(event) ){
      if( event == EVENT_RESOLVE_ACTIVATION ){
         int marked[151] = {0};
         CYCLE_ALL_CARDS(p, c,    {
                              if( p == player && in_play(p, c) && is_what(p, c, TYPE_CREATURE) ){
                                 marked[c] = 1;
                              }
                           };
         );
         int legacy = -1;
         int removed_count = 1;
         int i;
         for(i=150; i>-1; i--){
            if( marked[i] ){
               if(! is_token(player, i){
               if( legacy == -1 ){
                 legacy = create_legacy_effect(player, card, &legions_initiative_legacy);
               }
               if( removed_count > 18 ){
                 legacy = create_legacy_effect(player, card, &legions_initiative_legacy);
                 removed_count = 1;
               }
               card_instance_t *leg = get_card_instance(player, legacy);
               leg->targets[removed_count].player = get_owner(player, i);
               leg->targets[removed_count].card = get_original_internal_card_id(player, i);
               removed_count++;
            }
               kill_card(player, i, KILL_EXILE);
            }
         }
      }
      return generic_activated_ability(player, card, event, GAA_RFG_ME, MANACOST_RW(1, 1), 0, NULL, NULL);
   }

   return global_enchantment(player, card, event);
}
Indentation is off because I copied from the forum code but you see what I'm saying, and it's not like you wouldn't know how to do this anyway.

Re: [Fix]Legion's Initiative crashes,once fixed no exile & h

PostPosted: 20 Sep 2020, 15:56
by FastEddie
A creature token is a creature as far as I understood rule 111 (Tokens).

Re: [Fix]Legion's Initiative crashes,once fixed no exile & h

PostPosted: 20 Sep 2020, 16:39
by drool66
Right, but if Legion's Initiative 's ability resolves, its controller's creature tokens should be exiled but not returned later because of 111.7:
A token that’s in a zone other than the battlefield ceases to exist. This is a state-based action; see rule 704. (Note that if a token changes zones, applicable triggered abilities will trigger before the token ceases to exist.)
Therefore they need to go into marked[] but not leg->targets[]

Re: [Fix]Legion's Initiative crashes,once fixed no exile & h

PostPosted: 20 Sep 2020, 20:03
by FastEddie
drool66 wrote:Right, but if Legion's Initiative 's ability resolves, its controller's creature tokens should be exiled but not returned later
This is what I tried to imply ;). Exile a token aaaaaaaaaand... it's gone!

Re: [Fix]Legion's Initiative crashes,once fixed no exile & h

PostPosted: 21 Sep 2020, 12:16
by Aswan jaguar
Fixed the tokens issue in commit 2a9240e ("Legion's Initiative fix doesn't exile creature tokens.", 2020-09-21).