TADS Block Conversation

what’s an easy way to block conversation with an NPC? i.e. an animal?

i know that i can use beforeAction() or dobjFor(), but i have to do that for each conversation-related action which seems inefficient.

i can use a HermitActorState but then the NPC also won’t respond to ‘give’ or ‘show’.

i’ve tried overriding handleConversation() which works great but, again, also blocks ‘give’ and ‘show’ and i don’t know how to let those still get through.

1 Like

There are undoubtedly many ways to go about it. I created an Animal subclass of Actor, and overrode all of the conversational dobjFors with a message like “You surely aren’t expecting a response, are you?”. This leaves GiveTo and ShowTo to act as they normally would for other Actors.
However, you could probably continue to use handleConversation by starting out with

handleConversation(actor, topic, convType) {

    if (convType is in(giveConvType, showConvType))
        return inherited(actor, topic, convType);

    // your other handling here
}

Don’t forget to handle hi, bye, and issuing commands to the animal as well…

2 Likes

yes, that’s what I needed. it works perfectly with a tweak:

handleConversation(actor, topic, convType) 
    {
        if (convType is in(giveConvType, showConvType))
        {
            inherited(actor, topic, convType);
            return;
        }
        // your other handling here
    }

I had forgotten, though, commands and all the other stuff. so maybe it is easier just to block everything individually and wrap it in a class.

1 Like

If you make the Animal subclass, you can easily handle hi, bye, and commands with

class Animal : Actor
    // dobjFors
    defaultGreetingResponse(actor) { "yourmsg"; }
    defaultGoodbyeResponse(actor) { "yourmsg"; }
    defaultCommandResponse(fromActor, topic) { "yourmsg"; }
;

You could still contemplate handling all of the other dobjFors with handleConversation in addition to these three methods.

1 Like

It’s been awhile since I’ve done this, so I’m realizing that you could catch all three of those with one property, defaultConvResponse(actor, topic, convType). I spread mine out more because I implemented quite a few Animals and wanted to allow for more customization if desired.
It turns out you may be able to catch all of the behavior within defaultConvResponse. The upside to definining dobjFors in an Animal class is that besides nixing actual conversation, you can also set the logicalRank and such lower, so that Animals aren’t picked by the parser as targets of conversation if the player perhaps doesn’t specify whom they’re trying to talk to.

it seems actions can be blocked or altered equally well either with a beforeAction() method or with a dobjFor() method. is there an advantage or best-practices to one over the other? to me it seems like dealing with beforeActions() is easier. but i suppose access to logicalRank would be a check in the favor of dobjFor().

1 Like

beforeAction can come to the rescue in a pinch, but there are a lot of ways it can get overused and lead to poorly organized or brittle code. You should use dobjFor whenever it is clearly applicable, as it is in this case. beforeAction is much more so intended for catching corner cases and conditions being just such and such a way. If it’s illogical to churn the cheese, put that in cheese.verifyDobjChurn, don’t write a beforeAction that says if (gActionIs(Churn) && gDobj == cheese) failCheck(...)!

1 Like

Something that comes to mind as a valid use for beforeAction would be a situation where there’s a certain region or time period where you don’t want the PC to part with a certain inventory item, whereas at other points in the game it’s okay if they put the thing down. You might have:

sometimesImportantItem : Thing
    beforeAction {
        if (   certainConditionsApply && 
               gActionIn(Drop, PutIn, PutOn, PutUnder, 
                  PutBehind, GiveTo, ThrowAt, ThrowTo) &&
               gDobj == self)
            failCheck('You can\'t part with this right now! ');
    }
;

Note how that isn’t clearly handled by any one dobjFor… you could copy that logic in the check method of each of those verb dobjFors, but this is a case where it just makes sense to handle one situation (that might be accessed by several verbs) in one block.

1 Like

note that failCheck (which is Adv3 specific) isn’t limited to, well, failures, but also for success, if you want to alllow some “minor, purple action” (e.g. kissing an arrow; the stock “you can’t…” can be out-of-character, if the latter is not only an archer, but also a bit quirky and a bit superstitious, kissing an arrow isn’t needed for successfully sniping an out-of-reach rope or lever, but allow players a bit of role-playing isn’t bad…)

Best regards from Italy,
dott. Piergiorgio.

1 Like