Hello All,
Is it possible to have an NPC ask the user for a specific password prior to the start of conversation?
Would it be a conversation node? Or an NPC Object?
Any help would be beneficial.
Hello All,
Is it possible to have an NPC ask the user for a specific password prior to the start of conversation?
Would it be a conversation node? Or an NPC Object?
Any help would be beneficial.
Welcome to the TADS forum!
Depending upon the specifics of your situation, it seems like there could be many ways to achieve what you want. My game hasnât been heavily conversation-based, so there are others that might be able to whip up sample code more quickly than I can.
If you want the NPC to start the conversation without the player having tried to talk first, you can use an AgendaItem, or the initiateConversation
method triggered from some other code, perhaps a beforeAction
.
Most likely in any case you will be entering a ConvNode, whether through NPCâs initiative or in response to some player-entered verb like TALK TO, ASK ABOUT, etc.
I am very thankful for your reply!
I have tried to use a beforeAction, but I donât seem to have it correct. Here is a copy of the code I have written:
Hooded_Figure : Person 'hooded figure' 'figure'
@Hidden_Alley
"the hooded figure is carrying a torch, but his dark cloak prevents you from seeing his face.
He is speaking in low tones, but you aren't close enough to make out what he is saying. "
properName = 'Sadesh'
globalParamName = 'figure'
isHim = true
password = 'THESE HANDS OF MINE'
passwordEntered = nil
beforeAction(){
if (self.isFirstTime());{
self.doAsk();
}
}
dobjFor(Ask){
verify(){
if(passwordEntered);{
"Yes, you already know the password."
;}
}
action(){
local pwd = ask('WHAT IS THE SOUND OF DEATH? ');
if (pwd == password) {
"Excellent.";
passwordEntered = true;
}
else {finishGameMsg(ftDeath, [finishOptionUndo]);
}
}
}
;
Unless there is a lot more pertinent code that you havenât shown, there are several inconsistencies there.
-doAsk
isnât defined anywhere, or isFirstTime
-ask()
isnât defined
-(you donât need to use self.
in front of TADS object properties and methodsâŚ)
-There is no dobjFor(Ask)
, the verbs are AskAbout
and AskFor
Furthermore, you probably donât want to override dobjFor(AskAbout)
on the Actor⌠you should use TopicEntry objects instead. Your verify
and action
donât call inherited
, so they are very likely to give empty responses or strange behavior except under the particular circumstances you are imagining.
If you really want the figure to ask you for the password as soon as you encounter the figure, beforeAction
is probably also not what you want. Youâd probably use a ConvAgendaItem.
Itâs hard to straighten things out exactly without knowing exactly what youâre trying to achieve.
John - In case nobody has told you today:
You are an absolute champion.
My intent is to have a specific NPC (who belongs to a nefarious group of neâer-do-wells) ask the User for a password the very first time the User interacts with him.
I am obviously out of my depth, despite how simple this sounded in my head.
The idea is to have the User choose to talk to the NPC, and then have the NPC immediately ask for the password. If the User doesnât type the exact password, then I will call up an finishGameMsg.
If it is easier to code, my backup plan is to have the NPC ask for the password when the User asks about a specific topic.
I suppose it is clear by this point just how new I am to TADS.
Thank you for your help.
Itâs pretty hard to get too far in TADS without having a good handle on what the docs have to say! Thereâs a lot to learn, but itâs really powerful once you come to grips with it.
These are two different scenarios, and really want to be handled differently.
If you really want the NPC to interrupt the player to demand the password, then you could do that in a beforeAction()
, and if you want the password prompt to be modal/forced (that is, the player canât just ignore it and walk out of the room) then you can probably get what you want by just printing the prompt and then reading the player response via inputManager.getInputLine()
or something like that.
f you donât want to handle it that way, and want the password prompt to be presented the first time does something conversational with the NPC (asks/tells them about something, greets them, talks to them, and so on) the âhookâ youâre looking for is handleConversation()
, on either the actor object (if youâre not using states) or on the appropriate state (if you are).
Hereâs a little demo that illustrates how to approach this, although all it does is print âWhat is the password?â, where you probably want to do a replaceAction
, trigger a convnode
, or something like that:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
modify Person
passwordFlag = nil
;
startRoom: Room 'Void' "This is a featureless void. ";
+me: Person;
+pebble: Thing 'small round pebble' 'pebble' "A small, round pebble. ";
+alice: Person 'Alice' 'Alice'
"She looks like the first person you'd turn to in a problem. "
isProperName = true
isHer = true
passwordCheck() {
if(gActor.passwordFlag == true)
return(nil);
"<q>What is the password?</q> Alice demands. ";
return(true);
}
;
++InConversationState
specialDesc = "Alice is here, talking with you. "
stateDesc = "Alice is talking with you. "
;
+++AskTellTopic @pebble
"<q>It's a pebble,</q> she says. "
;
+++ConversationReadyState
isInitState = true
specialDesc = "Alice is here, not talking with you. "
stateDesc = "Alice is not talking with you. "
handleConversation(actor, topic, convType) {
if(alice.passwordCheck() == true)
return;
inherited(actor, topic, convType);
}
;
++++HelloTopic "<q>Hello,</q> she says. ";
++++ByeTopic
"<q>Bye,</q> she says. "
;
versionInfo: GameID;
gameMain: GameMainDef initialPlayerChar = me;
Nailed it!
Using handleConversation()
and nesting it into the ConversationReadyState
triggers the NPC asking for the password as soon as the player speaks to him for the first time.
Now comes the other half of my problem: Is it possible to have the password be a specific string of characters? I have tried fiddling around with inputManager.getInputLine()
but it seems like that isnât what I want.
Reading through the âGetting Started in TADS 3â only gets me so far. Is there another resource that you can point me to? Iâd rather learn than have to bother you kind folk every time I get stuck.
EDIT: If this second question should be a different post, let me know and Iâll mark the above response as the answer because, honestly, you crushed it.
@Scoyy You will also find that the most common way of dealing with TADS conversation is through objects. Here are two other ways to accomplish the above, that may be patterns for other things you might try to do:
Actor ;
+ InConversationState ;
++ DefaultAnyTopic
matchScore = 500
isActive = !talkCount
topicResponse {
//ask for the password
}
;
The above topic will supersede all other defined topics because of the matchScore, but it will cease being active after the first time you use it. (Of course, if you have a recurring password situation this isnât exactly what youâd want.)
And since the figure doesnât seem to be very conversational, itâs helpful to know that itâs not mandatory to use an InConversationState
⌠those particularly model polite conversation. An Actor can converse normally without the special state, there are simply no automatic greetings, farewells, or extra descriptions that âthey are in conversation with youâ.
Like soâŚ
Actor ;
+ DefaultAnyTopic ...
Here is another possibility, where HermitActorState already takes care of fielding all conversational attempts to one method. The thing about this is that youâll want to set the figure to another state afterwards, or else the figure will ask for the password on every single conversation attempt.
Actor ;
+ HermitActorState
noResponse {
//ask for password and handle responses
figure.setCurState(someOtherState);
}
;
As for the password:
Are you using adv3 or adv3Lite?
Because for adv3 you need inputManager.getInputLine(nil,nil)
.
Also you should probably define your password as a lowercase string, and then do
local resp = inputManager.getInputLine(nil,nil).toLower();
to make sure they match.
Lol, I look away for two days and miss ANOTHER chance to be helpful!
I just implemented an analagous sequence in the last month, but JZ beat me to the punch. Again! For me, the magic cocktail was using initiateConversation
. Note most of this pretty straight out of the Learning TADS 3 document.
npc : Person 'rude no boundaries person' 'rude person'
"Just a person. A rude, no boundaries person. "
location = intimidatingChair
posture = sitting
;
+ npcTalking : InConversationState
attentionSpan = nil
;
++ npcWaitingToPounce : ConversationReadyState
isInitState = true
afterTravel(traveler, connector) { //hits PC as soon as they arrive
inherited(traveler, connector);
if (traveler == gPlayerChar)
npc.initiateConversation(nil, 'gimmeDatPwd');
}
;
++ ConvNode 'gimmeDatPwd'
npcGreetingMsg =
"Before you can say anything, the rude person belts out, \"Gimme dat password.\" "
npcContinueList : ShuffledEventList {
[
'\"I said \'Gimme dat password.\'\" ',
'\"What part of \'password\' don\'t you understand?\" ',
'\"This is you. \'Buh buh buh not my password.\' Yes. Give it.\" ',
'\"Don\'t make me shake you.\" ',
'\"I can wait all day for that password.\" '
]
}
isSticky = true // won't leave convo
canEndConversation(actor, reason) { //Let PC leave, but not end convo with 'bye'
switch(reason) {
case endConvBye:
"Rude person ignores your attempted goodbye. ";
return blockEndConv;
default:
return true;
}
}
;
++ DefaultAnyTopic, ShuffledEventList // nothing but password will do
[
'Rude NPC ignores your attempt to change the subject. ',
'Rude NPC wants to hear only one thing from you. ',
'\"The next two things you say better be \'pass\' and \word\'.\" ',
'\"Bup-bup-bup. Password.\" ',
'\"I can\'t hear you if you\'re not saying \'password\'.\" '
]
;
I donât have an exact analog to wait for password, but the document goes into some depth on this in section 14.7 Conversation Nodes. It suggests something along the lines of:
++ SpecialTopic 'tell the password'
['tell', 'rude', 'npc', 'the', 'password', 'give', 'say' ]
topicResponse() = {
"\"Fine,\" you say. \"The password is ...\"';
//Handle password entry here
}
;
To the password entry part, I do a lot of character entry bits, and code like this gives me what I want:
do {
strSel = inputManager.getKey(nil, nil).toUpper();
intSel = toInteger(strSel);
"<<((strSel == 'Q') || ((intSel > 0) && (intSel <= maxVal))) ? strSel : 'X\nThat\'s not it, reenter: '>>";
} while ((strSel != 'Q') && ((intSel == 0) || (intSel > maxVal)));
Spins until player inputs a number in range 0âŚmaxVal or âQâ Seems like a similar approach would work by matching the inputManager.getInputLine(nil,nil).toLower();
?
Sorry JJ Hadnât been hearing from you in awhile⌠your example is clearly more detailed!
Lol, you had no way of knowing the moons aligned and I actually had something to offer this time! :]