Page 1 of 1

[fixed/closed]Thragtusk

PostPosted: 27 Nov 2013, 02:48
by RanDomino
Describe the Bug:
Thragtusks which die in combat create two copies in the gy.

This appears to be a resurgence of an old bug.

Which card did behave improperly ?
Thragtusk

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

What exactly should be the correct behavior/interaction ?
Only one dead Thragtusk

Are any other cards possibly affected by this bug ?
Possibly other creatures with similar abilities.

Re: [confirmed]Thragtusk

PostPosted: 27 Nov 2013, 16:01
by Gargaroz
Well, it'll required the good 'ol legacy card, but it won't functions if it's stolen.

Re: [confirmed]Thragtusk

PostPosted: 01 Dec 2013, 16:35
by Korath
Wait, is the only reason all these go-to-graveyard triggers need a separate effect card to keep from making a duplicate?

Re: [new info]Thragtusk

PostPosted: 02 Dec 2013, 14:27
by Gargaroz
No, every "graveyard from player" trigger that invokes targeting, drawing a card or putting a token into play goes apeshit if it's happening during combat, I really don't know why but it's the reason there are many cards that uses an external legacy to implement these kind of triggers. However, it's not big deal, but we need a way to update the "targets" of such legacies when an exchange of control happens.

Re: [new info]Thragtusk

PostPosted: 02 Dec 2013, 16:07
by Korath
Anytime during combat, or when handling a trigger?

Anyway, set legacy_instance->number_of_targets to be one more than the highest target you need updated, and gain_control_exe() (the u4b6860() called in switch_control() in functions.c) will take care of it for you. Just arrange the ordering of your targets so that all the ones up to there are all referring to actual player/card pairs, not arbitrary data, or else you risk them being updated incorrectly if they happen to match up to a real card that gets controlled. The relevant part of the function is:
Code: Select all
for (p = 0; p < 2; ++p)
  for (c = 0; c < active_cards_count[p]; ++c)
    {
      inst = get_card_instance(p, c);
      if (inst->damage_target_player == player_being_controlled && inst->damage_target_card == card_being_controlled)
        {
          inst->damage_target_player = new_player;
          inst->damage_target_card = new_card;
        }
      if (inst->damage_source_player == player_being_controlled && inst->damage_source_card == card_being_controlled)
        {
          inst->damage_source_player = new_player;
          inst->damage_source_card = new_card;
        }
      if (inst->number_of_targets != 0)
        for (t = 0; t < inst->number_of_targets; ++t)
          if (inst->targets[t].player == player_being_controlled && inst->targets[t].card == card_being_controlled)
            {
              inst->targets[t].player = new_player;
              inst->targets[t].card = new_card;
            }

Re: [new info]Thragtusk

PostPosted: 04 Dec 2013, 18:40
by Korath
I still can't get them to go crazy like you describe. Have a reliable test case so I can fix it and we can do away with these eyesores?

Re: [new info]Thragtusk

PostPosted: 06 Dec 2013, 02:29
by Gargaroz
Just take Abyssal Gatekeeper, cut the code from its legacy and paste it inside the card, let it die on combat and see what's happening. However, I'm currently rendering these legacies invisble, so they're no more an eyesore, at least.

Re: [new info]Thragtusk

PostPosted: 06 Dec 2013, 04:38
by Korath
Making them invisible also makes them unclickable when they trigger - especially confusing when you run out of visible triggering cards to click on, if there were any in the first place - and pops up confusing "Opponent is processing: some effect card you can't see except in this dialog" dialogs.

Still can't get Abyssal Gatekeeper to go crazy. His trigger doesn't actually fire, though, since TRIGGER_GRAVEYARD_FROM_PLAY is only sent after the card's fully left play.

If you delay creating the effects until they're actually going to trigger, though, you can eliminate all the boilerplate on the code side and get a good playing interface - the effect cards will only be visible if there's more than one triggering at a time and so the player actually needs to see them (to choose the resolution order).

Shared support code:
Code: Select all
static int effect_this_dies(int player, int card, event_t event){
    card_instance_t* instance = get_card_instance(player, card);
    if (trigger_condition == TRIGGER_GRAVEYARD_FROM_PLAY && player == reason_for_trigger_controller
        && affect_me(player, card) && instance->targets[11].card != -1){
        if (event == EVENT_TRIGGER){
            event_result |= instance->targets[11].player;
        } else if (event == EVENT_RESOLVE_TRIGGER){
            typedef int (*CardFunction)(int, int, event_t);
            CardFunction fn = (CardFunction)instance->targets[11].card;
            instance->targets[11].card = -1;  // prevent reentrance
            fn(player, card, EVENT_RESOLVE_THIS_DIES_TRIGGER);    // new event
            kill_card(player, card, KILL_REMOVE);
        }
    }
    return 0;
}

int this_dies_trigger(int player, int card, event_t event, resolve_trigger_t trigger_mode){
    card_instance_t* instance = get_card_instance(player, card);

    if (event == EVENT_GRAVEYARD_FROM_PLAY && affect_me(player, card) && instance->kill_code != KILL_REMOVE){
        int legacy = create_legacy_effect(player, card, effect_this_dies);
        card_instance_t* leg = get_card_instance(player, legacy);
        leg->targets[11].player = trigger_mode;
        leg->targets[11].card = cards_data[instance->internal_card_id].code_pointer;
    }

    return event == EVENT_RESOLVE_THIS_DIES_TRIGGER;
}
and Abyssal Gatekeeper itself reduces to:
Code: Select all
int card_abyssal_gatekeeper(int player, int card, event_t event){
    if (this_dies_trigger(player, card, event, RESOLVE_TRIGGER_MANDATORY)){
        impose_sacrifice(player, card, player, 1, TYPE_CREATURE, 0, 0, 0, 0, 0, 0, 0, -1, 0);
        impose_sacrifice(player, card, 1-player, 1, TYPE_CREATURE, 0, 0, 0, 0, 0, 0, 0, -1, 0);
    }
    return 0;
}

Re: [still bugged]Thragtusk

PostPosted: 14 Jan 2014, 06:59
by BAgate
Still creates 2 copies in the gy when it dies in combat.

Re: [still bugged]Thragtusk

PostPosted: 14 Jan 2014, 12:45
by Korath
First attempt at this was... unsuccessful.
better-than-dredge.jpg
just-2-would-be-nice.jpg

Re: [still bugged]Thragtusk

PostPosted: 14 Jan 2014, 20:00
by HarlequinCasts
lol

Re: [still bugged]Thragtusk

PostPosted: 14 Jan 2014, 22:39
by Korath
Fixed in a29d4cd.