Page 1 of 1

External Activation and Triggers

PostPosted: 27 Apr 2014, 20:38
by friarsol
Ok, so I was looking at this last night and here's the deal:

Here's the (relatively new) block of code that is called form PhaseHandler to wait for activating an ability to be activated and returned or not.

Code: Select all
    @Override
    public SpellAbility chooseSpellAbilityToPlay() {
        PhaseType phase = game.getPhaseHandler().getPhase();
       
        boolean maySkipPriority = mayAutoPass(phase) || isUiSetToSkipPhase(game.getPhaseHandler().getPlayerTurn(), phase);
        if (game.getStack().isEmpty() && maySkipPriority) {
            return null;
        }
        else {
            autoPassCancel(); // probably cancel, since something has happened
        }
       
        InputPassPriority defaultInput = new InputPassPriority(player);
        defaultInput.showAndWait();
        return defaultInput.getChosenSa();
    }
This block waits for the locally stored InputPassPriority to return. I believe this Input used to be more globally accessible which allowed different functions to reference its state. The problem is it doesn't take into account cards that aren't activated by a "onCardSelected" (below) which I believe is basically anything that's not in the battlefield or in your hand.


Code: Select all
  @Override
    protected void onCardSelected(final Card card, final MouseEvent triggerEvent) {
       List<SpellAbility> abilities = card.getAllPossibleAbilities(player, false);
       if (abilities.isEmpty()) {
            flashIncorrectAction();
            return;
       }

       selectAbility(player.getController().getAbilityToPlay(abilities, triggerEvent));
    }
And it seems like cards that are activated from the External Activation Area aren't going through there, which is why lands aren't triggering. Instead the EAA in CField just does.

Code: Select all
        ZoneAction flashBackAction = new ZoneAction(player.getZone(ZoneType.Graveyard), MatchConstants.HUMANFLASHBACK) {
            @Override
            protected List<Card> getCardsAsIterable() {
                return player.getCardsActivableInExternalZones();
            }

            @Override
            protected void doAction(final Card c) {
                // activate cards only via your own flashback button
                if (player.getLobbyPlayer() != CField.this.viewer) {
                    return;
                }
                final Game game = player.getGame();
                // TODO: "can play" check needed!

                // should I check for who owns these cards? Are there any abilities to be played from opponent's graveyard?
                final SpellAbility ab = player.getController().getAbilityToPlay(c.getAllPossibleAbilities(player, true));
                if ( null != ab) {
                    game.getAction().invoke(new Runnable(){
                       @Override public void run() {
                          HumanPlay.playSpellAbility(player, ab);
                          game.getStack().addAllTirggeredAbilitiesToStack(); // This line Sloth just added
                    }});
                }
            }
        };
I'll see if there's any way for this doAction to be routed through the "onCardSelected" up above.

Re: External Activation and Triggers

PostPosted: 28 Apr 2014, 00:54
by friarsol
Ok, I just checked in r25657 to attempt to fix this. I'll revert if it doesn't seem like it works, but it appeared to be triggering when I used a 40 Island deck with an Oracle of Mul Daya and Fastbond. I'll continue playing with the change tonight, but please let me know if the Flashback button is acting weird due to this, or anything else seems to not appreciate the flip