Page 1 of 1

[fixed/closed]Pillar of Flame

PostPosted: 25 Sep 2013, 09:17
by stassy
Describe the Bug:
Pillar of Flame does not allow regeneration.

Which card did behave improperly ?
Pillar of Flame

Which update are you using?(date,name)Which type(Duel,Gauntlet,Sealed Deck)
OoAv1

What exactly should be the correct behavior/interaction ?
Pillar of Flame does allow regeneration.

Are any other cards possibly affected by this bug ?
Others cards with "If a creature dealt damage this way would die this turn, exile it instead"

Image

I suppose this is due to the new code for this effect, as there is not destroy effect (no death icon), no regeneration ability/spell can be activated/cast and the creature is directly exiled.

Re: Pillar of Flame

PostPosted: 25 Sep 2013, 12:37
by Gargaroz
Yes, it's due to how regeneration is coded in Manalink... I dunno if this is fixable, Korath, any advice ?

Re: Pillar of Flame

PostPosted: 25 Sep 2013, 13:24
by Korath
Should be able to come close by setting instance->kill_code to KILL_REMOVE (but not changing event_result) during EVENT_GRAVEYARD_FROM_PLAY.

Re: Pillar of Flame

PostPosted: 26 Sep 2013, 00:11
by Gargaroz
It's exactly how that effect is set, but it still prevent regeneration.
Remaining on this topic, how is set the "event_result" of EVENT_GRAVEYARD_FROM_PLAY ?

Re: Pillar of Flame

PostPosted: 26 Sep 2013, 09:45
by Korath
exile_if_would_be_put_into_graveyard_legacy() is setting kill_code to KILL_REMOVE whenever it's nonzero (just like the disintegrate legacy does). Only setting it in EVENT_GRAVEYARD_FROM_PLAY lets regeneration work. (It still increases creatures_dead_this_turn, which normally doesn't happen for KILL_REMOVE, lets other EVENT_GRAVEYARD_FROM_PLAY handlers that happen to run before it see the original KILL_BURY/KILL_DESTROY/KILL_SACRIFICE kill code, and might incorrectly run TRIGGER_GRAVEYARD_FROM_PLAY before it gets here, though.)

A positive event_result from EVENT_GRAVEYARD_FROM_PLAY keeps the card from being killed at all.

The function that does most of kill_card()'s work | Open
Code: Select all
//----- (00477B30) --------------------------------------------------------
void kill_card_guts(int player, int card)
{
  card_instance_t* instance = get_card_instance(player, card);
  int iid = instance->internal_card_id;
  kill_t kill_code = instance->kill_code;

  if (!instance->kill_code)
    return;

  if (!(instance->token_status & STATUS_CANNOT_LEAVE_PLAY))
    {
      if (!(instance->token_status & STATUS_OBLITERATED))
        {
          card_data_t* cd = card_data_pointers[iid];

          if (kill_code != KILL_REMOVE
              && (cd->type & TYPE_CREATURE)
              && !(instance->state & STATE_INVISIBLE))
            ++creatures_dead_this_turn;

          if (cd->type & (TYPE_EFFECT|TYPE_PERMANENT))
            {
              push_affected_card_stack();
              event_result = 0;
              affected_card_controller = player;
              affected_card = card;
              attacking_card_controller = 1 - player;
              attacking_card = -1;

              dispatch_event_raw(EVENT_GRAVEYARD_FROM_PLAY);
              if (event_result > 0)
                {
                  LOBYTE(instance->token_status) &= ~STATUS_DYING;
                  pop_affected_card_stack();
                  return 0;
                }
              kill_code = instance->kill_code;

              pop_affected_card_stack();
            }

          if (!(cd->type & TYPE_EFFECT))
            {
              if (kill_code == KILL_REMOVE)
                put_card_in_exile(instance->state & STATE_OWNED_BY_OPPONENT ? 1 : 0, card, player);
              else
                {
                  if (kill_code != KILL_SACRIFICE && ai_is_speculating != 1)
                    {
                      card_data_t* cd = card_data_pointers[instance->original_internal_card_id];

                      if (cd->type & TYPE_CREATURE)
                        play_sound_effect(WAV_KILL);
                      else if (!(cd->type & TYPE_SPELL))
                        play_sound_effect(WAV_BURIED);
                    }

                  if (!(instance->token_status & STATUS_TOKEN))
                    put_card_in_graveyard(player, card);

                  if (kill_code == KILL_SACRIFICE)
                    dispatch_trigger_twice_once_with_each_player_as_reason(current_turn, TRIGGER_GRAVEYARD_FROM_PLAY, "Card(s) to graveyard", 0);
                  // TRIGGER_GRAVEYARD_FROM_PLAY is also dispatched in TENTATIVE_damage_prevention_step2() for KILL_DESTROY and KILL_BURY
                }
            }
        }

      push_affected_card_stack();
      int old_trigger_cause_controller = trigger_cause_controller;
      int old_trigger_cause = trigger_cause;
      trigger_cause_controller = player;
      trigger_cause = card;

      if (card_data_pointers[iid]->type & TYPE_PERMANENT)
        dispatch_trigger_twice_once_with_each_player_as_reason(current_turn, TRIGGER_LEAVE_PLAY, "Card leaving play", 0);

      trigger_cause_controller = old_trigger_cause_controller;
      trigger_cause = old_trigger_cause;
      pop_affected_card_stack();
    }

  type_t typ = card_data_pointers[iid]->type;
  if (typ & TYPE_CREATURE)
    --TENTATIVE_creature_count[player];
  if (typ & TYPE_ARTIFACT)
    --TENTATIVE_artifact_count[player];
  if (typ & TYPE_ENCHANTMENT)
    --TENTATIVE_enchantment_count[player];

  redraw_libraries();

  instance->internal_card_id = -1;
  instance->kill_code = 0;
  instance->unknown0x14 = 0;

  if (ai_is_speculating != 1)
    sub_471D60();       // redraw everything?

  destroy_attached_auras(player, card);

  if (card_data_pointers[iid]->type & TYPE_PERMANENT)
    recalculate_all_cards_in_play();
}

Re: Pillar of Flame

PostPosted: 27 Sep 2013, 12:42
by Gargaroz
I see, fix inserted. Checking the code you attached, setting "token_status" to "STATUS_CANNOT_LEAVE_PLAY" will be a good approximation of "indestructible" ?

Re: Pillar of Flame

PostPosted: 27 Sep 2013, 13:11
by stassy

Re: Pillar of Flame

PostPosted: 27 Sep 2013, 13:20
by Korath
STATUS_CANNOT_LEAVE_PLAY would prevent KILL_REMOVE and KILL_SACRIFICE too.

stassy wrote:Also please if you can spread the fix to similar cards :
Yamabushi's Flame
Yamabushi's Storm
Demonfire
Red Sun's Zenith
Pillar of Flame
Annihilating Fire
Some of these should already work right - rfg_when_die(), used by Yamabushi's Flame, Yamabushi's Storm, already looks correct. The others either call card_pillar_of_flame() directly, or use the same backend function (exile_if_would_be_put_into_graveyard()) as it does.