<.convstay> not staying on topic (adv3lite)

I have defined a conversation between Harry and Aaron that utilizes a StopEventList. I want to require that all items in the list be heard before the conversation can be ended. So, I have a ConvNode that has an AskTopic, StopEventList with three items in the list. All but the last one contains a <.convstay> tag.

There are also default responses, and a NodeContinuationCheck block, all of which contain the <.convstay> tag.

But when Harry deviates from the script after the first item in the event list by saying “yes” (and triggering the default Any topic that does include a <.convstay> tag), the chain is broken. Harry cannot continue to ask about the pool party.

Harry says yes, instead of continuing to ask about the pool party. The Harry, listen to me… text is from the DefaultAnyTopic, which includes a <.convstayt> tag, but the node is broken. The conversation is over, prematurely…

Here’s the source…

[code]#charset “us-ascii”

#include <tads.h>
#include “advlite.h”

versionInfo: GameID
IFID = ‘243748b1-5310-4916-8436-890e9ccc16fd’
name = ‘test’
byline = ‘by Jerry Ford’
htmlByline = ‘by
Jerry Ford

version = ‘1’
authorEmail = ‘Jerry Ford jerry.o.ford@gmail.com
desc = ‘Testing adv3lite character conversations.’
htmlDesc = ‘Testing adv3lite character conversations.’
;

gameMain: GameMainDef
/* the initial player character is ‘harry’ */
initialPlayerChar = harry
paraBrksBtwnSubcontents = nil
usePastTense = true
;

// harry, main character
harry: Actor ‘Harry;;man self’ @harrysBed
“”
globalParamName = ‘harry’
isHim = true
isInitState = true
person = 3
proper = true
;

  • cellPhone: Thing ‘cell phone;;telephone phone cell mobile’
    "The cell phone was an older model, no data plan, just basic telephone
    service, and, of course, a camera. "

    cellPhoneNotSeenText = "The cell phone was somewhere nearby, {the subj
    harry} was sure of it. He just needed to look around for it some more. "

    isRinging = nil

    ringing()
    {
    isRinging = true;
    “Harry heard his cell phone ring.
    <.p>”;
    }
    dobjFor(Answer)
    {
    verify(){}
    action()
    {
    “Harry looked at the phone’s screen. \b”;
    if(isRinging)
    {
    "It was Aaron, his ex-wife’s current husband, stepfather to
    Harry’s son Max, rich and powerful lawyer, and all-around-general
    pain in the ass. \b
    Just what I need, Harry moaned inwardly, as he prepared
    to talk to Aaron. ";

              commLink.connectTo(aaron);
              
              if(phoneCallFromAaron.conversationWithAaron != nil)
              {
                  phoneCallFromAaron.conversationWithAaron.removeEvent();
                  phoneCallFromAaron.conversationWithAaron = nil;
              }
          }
    
          isRinging = nil;
      }
    

    }
    ;

harrysBedroom: Room
‘Bedroom’ ‘bedroom; room’
“The bedroom was small, the furniture adequate but utilitarian.”

;

  • harrysBed: Container ‘bed;;bed’
    “Harry’s bed.”
    canLieOnMe = true
    isEnterable = true
    bulk = 5001
    ;

// aaron character
aaron: Actor ‘Aaron’
“”
isHim = true
globalParamName = ‘aaron’
person = 3
bulkCapacity = 5000
;

  • aaronOnPhoneAboutParty: ActorState
    ;
    ++ AskTopic @tCallOnPhone
    “Aaron, why did you call me? What do you want? Harry said. \b
    I called to talk to you about picking up Max, Aaron replied coldly.
    I’m having a pool party and I need you to exercise some discretion when
    you get here. I don’t want you interfering with my guests.
    <.convnodet beDiscrete>”

    name = ‘the call’
    ;

  • ConvNode ‘beDiscrete’
    ;
    ++ AskTopic, StopEventList @tBeDiscrete
    eventList =
    [
    ‘Pool party? Hey, I’m up for that, Harry said. Should I
    bring my suit? \b
    Very funny, Harry Aaron replied without humor. Discretion, Harry. Can you
    spell discretion? <.convstayt>’ ,

      '<q>Yeah, got it, Aaron.</q> 
      <q>Some of my guests are...shy. Camera shy. Detective shy. Stay away
      from the party, Harry. When you get here, someone
      from the catering staff will fetch Max for you and you two can be on
      your way. You don\'t need to go any further than the front door. Are
      we clear, Harry?</q> Aaron\'s demeanor clearly indicated he thought the
      conversation was finished.
      <.convstayt>',
      
      '<q>We clear, Aaron. We so very clear.</q> And he disconnected the
      call. <.reveal poolPartyPlans>'
    

    ]

    name = ‘the pool party’
    ;
    ++ DefaultTellTopic
    “Hary, I don’t want to banter with you. I have better things to do
    with my time, Aaron said. <.convstayt>”
    ;
    ++ DefaultAnyTopic
    “Harry, listen to me! Aaron said harshly. <.convstayt>”
    ;
    ++ NodeContinuationTopic
    “Pay attention, Harry. <.convstayt>”
    ;
    ++ NodeEndCheck
    canEndConversation(reason)
    {
    switch(reason)
    {
    case endConvBye:
    ““Listen to me, Harry, I’m loosing my pateience with you and
    your damn kid, you hear me?” Aaron said in a surly tone.

    <.convstayt>”;
    return blockEndConv;
    case endConvLeave:
    “Harry…\b
    Okay, Aaron, okay, finish what you have to say and then
    let’s not continue beyond that, okay? Harry said.
    <.p> <.convstayt>”;
    return blockEndConv;
    default:
    return nil;
    }
    }
    ;

phoneCallFromAaron: Scene
startsWhen = (!harry.isIn(harrysBed))
endsWhen = (gRevealed(‘poolPartyPlans’))

conversationWithAaron = nil

whenStarting()
{
    conversationWithAaron = new Daemon(cellPhone, &ringing, 3);
    aaron.setState(aaronOnPhoneAboutParty);
}
whenEnding()
{
    commLink.disconnectFrom(aaron);
    if(conversationWithAaron != nil)
    {
        conversationWithAaron.removeEvent();
        conversationWithAaron = nil;
    }
    aaron.setState(nil);
}

;

tBeDiscrete: Topic ‘the pool party’;
tCallOnPhone: Topic ‘the call’;

VerbRule(Answer)
‘answer’ singleDobj
: VerbProduction
action = Answer
verbPhrase = ‘answer/answering’
missingQ = ‘answer what’
;
DefineTAction(Answer)
;
[/code]

The conversation is in fact staying within the Conversation Node (at least it does when I try it). What’s happening here is that once you’ve asked Aaron about the party once, the game is taking Harry’s curiosity about it to be satisfied, so it doesn’t suggest the topic again (even though the conversation remains in the same node).

You can fix that by defining timesToSuggest = 3 on the AskTopic:

++ AskTopic, StopEventList @tBeDiscrete
    eventList =
    [
        '<q>Pool party? Hey, I\'m up for that,</q> Harry said. <q>Should I
        bring my suit?</q> \b
        <q>Very funny, Harry</q> Aaron replied without humor. <q>Discretion, Harry. Can you
        spell <i>discretion</i>?</q> <.convstayt>' ,
       
        '<q>Yeah, got it, Aaron.</q>
        <q>Some of my guests are...shy. Camera shy. Detective shy. Stay away
        from the party, Harry. When you get here, someone
        from the catering staff will fetch Max for you and you two can be on
        your way. You don\'t need to go any further than the front door. Are
        we clear, Harry?</q> Aaron\'s demeanor clearly indicated he thought the
        conversation was finished.
        <.convstayt>',
       
        '<q>We clear, Aaron. We so very clear.</q> And he disconnected the
        call. <.reveal poolPartyPlans>'
    ]

    name = 'the pool party'

    timesToSuggest = 3
;

This should keep the suggestion in play until the player has seen all three items in the AskTopic’s eventList.

That said, the library was meant to be doing this for you automatically. Looking at the library code I see I’ve gone and misused the static keyword again, so I’ll fix this for the next release. If you want to change your copy of the library code, it’s the definition of ActorTopicEntry at around line 2778 in actor.t. Where it reads:

timesToSuggest =  static (ofKind(Script) ? eventList.length : 1)

Change it to:

timesToSuggest()
    {
        local t = (ofKind(Script) ? eventList.length : 1);
        
        timesToSuggest = t;
        
        return t;        
    }

This isn’t critical, though; it just saves you from having to override timesToSuggest by hand each time.