I noticed more anomalous behavior when trying
to do more work on this project. Specifically, I was using change, add, and
destroy events to try to track when cards entered and left play, so that I
could compare a list of IDs in play to the deck's discard pile to determine
whether there are actually any cards in the discard. However, I observed that
the giveCardToPlayer(), recallCards(), and shuffleDeck() calls do not seem to
trigger change:hand or change:deck events.
I'm pretty new to change events, so maybe this is expected behavior, but in
case not, here's a script that can be used for reproduction: on('ready',()=>{ const getCardName = (()=>{ let lookup = {}; return (cardid) => { if(!lookup.hasOwnProperty(cardid)){ let c = getObj('card',cardid); if(c){ lookup[cardid] = c.get('name'); } else { lookup[cardid] = '[UNKNOWN]'; } } return lookup[cardid]; }; })(); on("chat:message", (msg) => { const [cmd, args] = msg.content.split(/\s(.+)/); log({cmd}); log({args}); const deck = findObjs({_type: "deck", name: "Playing Cards"}, {caseInsensitive: true})[0]; switch (cmd.toLowerCase()) { case '!draw': { let num = parseInt(args)||1; let drawn = []; let drawfail = 0; for(let i = 0; i<num; ++i){ let cardId =drawCard(deck.id); if(cardId !== false){ //Card found, give to player giveCardToPlayer(cardId, msg.playerid); drawn.push(cardId); } else { ++drawfail; } } const cardRows = (ids) => ids.map(getCardName).join(', '); if(drawn.length > 0) { log(`${msg.who} drew ${cardRows(drawn)} and failed to draw ${drawfail} cards.`); } else { log(`${msg.who} failed to draw ${drawfail} cards.`); } break; } case '!shuffle': { recallCards(deck.id); shuffleDeck(deck.id); log(`${msg.who} recalled and shuffled the cards for ${deck.get("name")}.`); break; } } }); on("change:hand", (hand) => { let player = getObj("player", hand.get("_parentid")); log(`A change event occurred for ${player.get("_displayname")}'s hand.`); }); on("change:deck", (deck) => { log(`A change event occurred for the ${deck.get("name")} deck.`); }); on("change:card", (card) => { let cardId = card.get("_cardid"); log(`A change event occurred for the ${getCardName(cardId)} card.`); }); on("add:card", (card) => { let cardId = card.get("_cardid"); log(`${getCardName(cardId)} was added to the tabletop.`); }); on("destroy:card", (card) => { let cardId = card.get("_cardid"); log(`${getCardName(cardId)} was removed from the tabletop.`); }); }); I followed the below steps to test this. I'm having issues getting the console log to post as a screenshot, so I'm just listing the steps along with the line number from the console log that should appear in the reproduction: Create
a new game. Add
the script to the game. Open
the game. Go
to Collections and click "Show" for the Playing Cards deck. This
triggered a change:deck event
[line 4]. Click
the "Shuffle" button on the newly displayed deck. This triggered
a change:deck event
[line 5]. Drag
a card from the shown deck to the player icon to add it to the player's hand.
This triggered a change:deck event
[line 6] but no change:hand event,
presumably because the hand didn't exist at this point. Drag
another card from the shown deck to the player icon. This time a change:hand event
[line 7] and a change:deck event
[line 8] are triggered. Issue
the !draw 2 command. This draws two cards [lines 9-11] but
does not trigger any events. I
dragged a card from the deck to the tabletop. This triggered a change:deck event
[line 12], an add:card event
[line 13], and another change:deck event
[line 14]. I haven't looked into why two change:deck events are triggered by this
behavior, though I suspect it may have to do with interacting with the deck
after an API call was made against it. I
then moused over the shown deck, selected the "Recall" option,
checked the "Shuffle after recalling?" checkbox, and then clicked the
"Recall All" button. This triggered four change:hand events (one per card) [lines
15-18], a destroy:card event
[line 19], and a change:deck event
[line 20]. I
dragged a card from the deck to the tabletop. This triggered only two events
(unlike in Step 1 above): a change:deck event
[line 21] and add:card event
[line 22]. I
issued the !draw 4 command. This drew the cards but did not
trigger any events, as expected from the previous test case [lines 23-25]. I
issued the !shuffle command. While I expect to see the same
events as in Step 2, instead I see the logged command lines [lines 26-27, 29]
and a single destroy:card event
[line 28]. Given that Steps 6 and 7 triggered change:deck events while Step 8 did not, and given that Step 7 triggered a change:hand event while Step 8 did not, it seems that giveCardToPlayer() isn't triggering events correctly. Similarly, given that Step 10 triggered change:hand and change:deck events while Step 13 did not, it seems that recallCards() and shuffleDeck() are not triggering events correctly. This may be intended behavior to avoid infinite loops in the API, but I wasn't sure and figured I'd check with the community.