NPC Behavior Help Wishlist

dwn
07 Feb 2013, 04:15
Hello, All - I was hoping someone could post any tips or point me in any direction which would help me to figure out the easiest ways to implement a number of NPC Behavior scripts which I think would help bring a game characters to life.

Here's a few of my wish-list ideas for tutorials, help or suggestions:

1. How to script randomized turn-based NPC messages, so if there's an NPC in the room with you, every few turns the player gets a message of some kind of behavior they're engaged in...i.e. "Joe is busy talking on the phone", "Joe is banging his head against the desk in frustration", "Joe's slumped back in his chair dozing off", ect.

2. A FOLLOW NPC or FOLLOW ME command, so you can give path-finding directions to the NPC, or could also be used for stalking/hunting someone or something.

3. A PATROLLING NPC who can be made to walk through a series of rooms on a schedule, like a City Guard, for example.

If anyone has an ideas or knows of a tutorial or post where this has been covered before please let me know. Thanks!

sgreig
07 Feb 2013, 04:27
1. This can be accomplished the same way as I explained in the random description thread, but instead of putting the line:


msg(StringListItem(npc.behaviorDesc, GetRandomInt(1,3) - 1))


in the object's description, you'd create a turn script that would execute that command every X number of turns. In this instance, I would add the string list to the different npc's in the game. I hope that makes sense.

2. I don't have the energy to fully work this out off the top of my head, but as long as you think it through methodically it shouldn't be too tough. Basically what you want to do is have some sort of flag that gets triggered when you use the follow command and then any time you move to a different room, change the npc's parent room to the player's parent room. You would likely need to use a turn script for this as well.

3. This is once again a turn script scenario. You could have the npc move to a different room on every turn, or every x number of turns, or whatever.

dwn
07 Feb 2013, 22:46
sgreig wrote:1. This can be accomplished the same way as I explained in the random description thread, but instead of putting the line:


msg(StringListItem(npc.behaviorDesc, GetRandomInt(1,3) - 1))


in the object's description, you'd create a turn script that would execute that command every X number of turns. In this instance, I would add the string list to the different npc's in the game. I hope that makes sense.

2. I don't have the energy to fully work this out off the top of my head, but as long as you think it through methodically it shouldn't be too tough. Basically what you want to do is have some sort of flag that gets triggered when you use the follow command and then any time you move to a different room, change the npc's parent room to the player's parent room. You would likely need to use a turn script for this as well.

3. This is once again a turn script scenario. You could have the npc move to a different room on every turn, or every x number of turns, or whatever.


After looking through some examples I think I can figure this out mostly. The next NPC question I am thinking about would seem simpler in concept than 'patrollers', but I can't even begin to work it out in scipt form--

I have an NPC that has locked themself in a room.

I created a verb "knock on" to knock on the door, and it works fine so long as that's all you do.

But what if you want the NPC in the locked room to answer you, like "Give me a moment, I'll be right out."--if they're in the room?

How can you make a script check to see if the NPC is in the room when you knock on the door, and if so, print a response? And if not, say "Nobody answers"?

I can't see any of setting up an If Then script to check and see if an NPC is in the room in order to respond to knocking on the door.

dwn
08 Feb 2013, 00:24
sgreig wrote:1. This can be accomplished the same way as I explained in the random description thread, but instead of putting the line:


msg(StringListItem(npc.behaviorDesc, GetRandomInt(1,3) - 1))


in the object's description, you'd create a turn script that would execute that command every X number of turns. In this instance, I would add the string list to the different npc's in the game. I hope that makes sense.

2. I don't have the energy to fully work this out off the top of my head, but as long as you think it through methodically it shouldn't be too tough. Basically what you want to do is have some sort of flag that gets triggered when you use the follow command and then any time you move to a different room, change the npc's parent room to the player's parent room. You would likely need to use a turn script for this as well.

3. This is once again a turn script scenario. You could have the npc move to a different room on every turn, or every x number of turns, or whatever.


With no programming knowledge, this is the best I could guess in putting together the code with the example you suggested, but nothing happens when I run the game...not sure what I did wrong...


<!--Saved by Quest 5.3.4762.29157-->
<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="NPC Crowd">
<gameid>70d76bbb-2e9b-455e-a69e-b79f47955343</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="NPC_Crowd">
<inherit name="editor_object" />
<alias>crowd</alias>
NPC_Crowd.behaviorDesc = newStringList()
list add (NPC_Crowd.behaviorDesc, "A dusty old tome.")
list add (NPC_Crowd.behaviorDesc, "It's a weathered volume.")
list add (NPC_Crowd.behaviorDesc, "A very old book with that familiar musty book smell.")
</object>
<turnscript>
<script>
SetTurnTimeout (2) {
msg(StringListItem(NPC_Crowd.behaviorDesc, GetRandomInt(1,3) - 1))
}
</script>
</turnscript>
</object>
</asl>

HegemonKhan
08 Feb 2013, 04:35
dwn wrote:I have an NPC that has locked themself in a room.

I created a verb "knock on" to knock on the door, and it works fine so long as that's all you do.

But what if you want the NPC in the locked room to answer you, like "Give me a moment, I'll be right out."--if they're in the room?

How can you make a script check to see if the NPC is in the room when you knock on the door, and if so, print a response? And if not, say "Nobody answers"?

I can't see any of setting up an If Then script to check and see if an NPC is in the room in order to respond to knocking on the door.


----------

this (the below line) is a code line for adding in comments or notes, extremely useful, don't be lazy like me (lol), add in lots of notes or comments into all of your game codes! :

// your_comments_or_notes

-----------

or, you can also do this:

(but, this seems to disappear within your game file when its a game file (when you save and load it back up), it only remains if you make your file as a library file instead)

<!-- your_comments_or_notes, your_comments_or_notes, your_comments_or_notes, etc -->

or, it can have this format too:

<!--
etc
your_comments_or_notes
your_comments_or_notes
your_comments_or_notes
etc
-->

-------------------

both of these below codes can be copied and pasted (delete and paste into your) into your new game's code file (either via the Code View mode toggle button or by opening up the game file with note, note++, or word pad), but do *NOT*change anything, and watch in awe, hehe (look at it in your Code View mode, hehe. the comments/notes coding is really awesome and useful!)

your code should look something like this:

// the below line is the start of the script block for your door object
<object name="door">
// the below line is the start of the script block for your verb ' knock on '
<knock on type="script">
// the below line is the script, a simple message, that your verb ' knock on ' runs
msg ("knock on door")
</knock on>
// the above line is the end of the script block for your verb ' knock on '
</object>
// the above line is the end of the script block for your door object


now this is how you want to change your code, so that it will look like this:

// the below line is the start of the script block for your door object
<object name="door">
// the below line is the start of the script block for your verb ' knock on '
<knock on type="script">
// the below lines is the script, a simple message, that your verb ' knock on ' runs
msg ("knock on door")
// the below two coding lines says this: if your npc's parent is the locked room (the ' parent ' meaning that, if the npc is a, ' child ' or INSIDE, of the locked room), then output the message, "Give me a moment, I'll be right out."
// the line below is the start of the if script block
if (your_npc_name.parent = the_room_name_of_that_he_she_is_locked_inside_of) {
msg ("Give me a moment, I'll be right out.")
}
// the above line, the single ' } ', is the end of the if script block
// the below two coding lines is the script block for if the npc's parent is *NOT* the locked room (meaning that, since there npc isn't in the locked room, then output the message, "Nobody answers"
else {
msg ("Nobody answers")
}
// the above line, the single ' } ' is the end of the else script block
</knock on>
// the above line is the end of the script block for your verb ' knock on '
</object>
// the above line is the end of the script block for your door object


----------------

P.S.

for posting code here, use this (as it keeps your code from taking up lots of space, and it maintains the proper format, keeps the proper indentation):

[code.]pppppppp
ppppppppp
[/code.]

but remove the "." (dots) from inside the [ code ] 's , so it'll properly work:

pppppppp
ppppppppp


-------------

P.S.S.

good attempt at trying to do the coding on your own! I would have done worse, if I had tried right out of the blue like you just did (I started off simple and slowly, err kinda... I jumped right into doing harder stuff lol, worked my way up to understanding the basics of coding, so I had more of a progressive approach at learning the coding then you, trying to do it right now, hehe)

I'll let sgreig help you with getting his coding stuff right, as I'm still learning this stuff myself too, and figuring out how to get that other stuff (my game demo) working for you, was a royal pain (it wasn't that easy, lol), so I need a bit of a break, lol.

sgreig
08 Feb 2013, 06:23
dwn wrote:

With no programming knowledge, this is the best I could guess in putting together the code with the example you suggested, but nothing happens when I run the game...not sure what I did wrong...

<!--Saved by Quest 5.3.4762.29157-->
<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="NPC Crowd">
<gameid>70d76bbb-2e9b-455e-a69e-b79f47955343</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="NPC_Crowd">
<inherit name="editor_object" />
<alias>crowd</alias>
NPC_Crowd.behaviorDesc = newStringList()
list add (NPC_Crowd.behaviorDesc, "A dusty old tome.")
list add (NPC_Crowd.behaviorDesc, "It's a weathered volume.")
list add (NPC_Crowd.behaviorDesc, "A very old book with that familiar musty book smell.")
</object>
<turnscript>
<script>
SetTurnTimeout (2) {
msg(StringListItem(NPC_Crowd.behaviorDesc, GetRandomInt(1,3) - 1))
}
</script>
</turnscript>
</object>
</asl>


The 'N' in NewStringList should be capitalized. Also, the way you have it written the string list hasn't actually been created on the object. If you want to write it that way, it has to be in a script somewhere, like in game start. Otherwise, you need to create the list as an attribute of the book. This code should work:


<!--Saved by Quest 5.3.4762.29157-->
<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="NPC Crowd">
<gameid>70d76bbb-2e9b-455e-a69e-b79f47955343</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="NPC_Crowd">
<inherit name="editor_object" />
<alias>crowd</alias>
<behaviorDesc type="list">A dusty old tome.; It's a weathered volume.; A very old book with that familiar musty book smell.</behaviorDesc>
</object>
<turnscript>
<script>
SetTurnTimeout (2) {
msg(StringListItem(NPC_Crowd.behaviorDesc, GetRandomInt(1,3) - 1))
}
</script>
</turnscript>
</object>
</asl>


As for the issue about knocking on the door and having the npc answer if he's in it, that's not too difficult. As you're probably learning, the hardest part of programming is figuring out the steps to accomplish something in a very logical, methodical manner as it's not really how humans think naturally.

So let's assume your npc is called "NPC" and he's in a room called "Locked_Room" to make things easier for the example. When you enter the knock on door command, a script like this should be used:


if (NPC.parent = "Locked_Room") {
msg("You hear a voice call out, \"Give me a moment! I'll be right out!\" from behind the door.")
}
else {
msg("Nobody answers.")
}


The backslashes in the first msg command might be confusing you. Since Quest (and most other programming languages) will assume a quotation mark is the end of a string, you need to "Escape" the character with a backslash so that Quest will ignore it and print it as part of the message. You could also use a single quote instead, but that won't work in all programming languages as some use those for strings as well.

But as you can see, it's a fairly simple check to make. When you want to check if an object is in a particular room, you just need to check the parent attribute of the object. You can also move objects around by changing the value of the parent attribute as well. Understanding how parent->child relationships work will help you immensely in Quest and other object-oriented programming languages.

dwn
08 Feb 2013, 15:36
sgreig wrote:

"dwn"





The 'N' in NewStringList should be capitalized. Also, the way you have it written the string list hasn't actually been created on the object. If you want to write it that way, it has to be in a script somewhere, like in game start. Otherwise, you need to create the list as an attribute of the book. This code should work:

So let's assume your npc is called "NPC" and he's in a room called "Locked_Room" to make things easier for the example. When you enter the knock on door command, a script like this should be used:


if (NPC.parent = "Locked_Room") {
msg("You hear a voice call out, \"Give me a moment! I'll be right out!\" from behind the door.")
}
else {
msg("Nobody answers.")
}




When I run the NPC Crowd code, this is what I get:

You are in a room.
You can see a crowd.

> look at crowd
Nothing out of the ordinary.

> z
Time passes.

> z
Time passes.

> z
Time passes.

> z
Time passes.

> z
Time passes.

After taking 2 turns, nothing happens. Not sure how to fix it.

HegemonKhan
08 Feb 2013, 16:20
take a look at my codes too (it's the same as sgreig's, except it's missing the random messages code part), as I've made some comments for you to read and understand the code (it looks really nice in Code View Mode!), but it's messy otherwise, so if you want to, you can delete all the ' // _____ ' (comment) lines.

here's the code with the comment lines (view this in Code View mode!):

// the below line is the start of the script block for your door object
<object name="door">
// the below line is the start of the script block for your verb ' knock on '
<knock on type="script">
// the below lines is the script, a simple message, that your verb ' knock on ' runs
msg ("knock on door")
// the below two coding lines says this: if your npc's parent is the locked room (the ' parent ' meaning that, if the npc is a, ' child ' or INSIDE, of the locked room), then output the message, "Give me a moment, I'll be right out."
// the line below is the start of the if script block
if (your_npc_name.parent = the_room_name_of_that_he_she_is_locked_inside_of) {
msg ("Give me a moment, I'll be right out.")
}
// the above line, the single ' } ', is the end of the if script block
// the below two coding lines is the script block for if the npc's parent is *NOT* the locked room (meaning that, since there npc isn't in the locked room, then output the message, "Nobody answers"
else {
msg ("Nobody answers")
}
// the above line, the single ' } ' is the end of the else script block
</knock on>
// the above line is the end of the script block for your verb ' knock on '
</object>
// the above line is the end of the script block for your door object


here's the code without the comment lines (It looks the exact same as sgreig's, except its missing all of his coding for the random selection and etc):

<object name="door">
<knock on type="script">
msg ("knock on door")
if (your_npc_name.parent = the_room_name_of_that_he_she_is_locked_inside_of) {
msg ("Give me a moment, I'll be right out.")
}
else {
msg ("Nobody answers")
}
</knock on>
</object>


-------

sgreig was saying to combine (though it takes some work and "know-how" to do this) the two codes of his:

<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="NPC Crowd">
<gameid>70d76bbb-2e9b-455e-a69e-b79f47955343</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="NPC_Crowd">
<inherit name="editor_object" />
<alias>crowd</alias>
<behaviorDesc type="list">A dusty old tome.; It's a weathered volume.; A very old book with that familiar musty book smell.</behaviorDesc>
</object>
<turnscript>
<script>
SetTurnTimeout (2) {
msg(StringListItem(NPC_Crowd.behaviorDesc, GetRandomInt(1,3) - 1))
}
</script>
</turnscript>
</object>
</asl>


and

if (NPC.parent = "Locked_Room") {
msg("You hear a voice call out, \"Give me a moment! I'll be right out!\" from behind the door.")
}
else {
msg("Nobody answers.")
}


so, it would look like this (using sgreig's codes):

<asl version="530">

<include ref="English.aslx" />
<include ref="Core.aslx" />

<game name="NPC Crowd">

<gameid>70d76bbb-2e9b-455e-a69e-b79f47955343</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>

</game>

<object name="room">

<inherit name="editor_room" />

<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>

<object name="locked_door">

<knock_on type="script">
if (NPC.parent = "Locked_Room") {
msg("You hear a voice call out, \"Give me a moment! I'll be right out!\" from behind the door.")
}
else {
msg("Nobody answers.")
}
</knock_on>

</object>

</object>

<object name="locked_room">

<inherit name="editor_room" />

<object name="NPC_Crowd">

<inherit name="editor_object" />
<alias>crowd</alias>
<behaviorDesc type="list">A dusty old tome.; It's a weathered volume.; A very old book with that familiar musty book smell.</behaviorDesc>

</object>

<turnscript>

<script>
SetTurnTimeout (2) {
msg(StringListItem(NPC_Crowd.behaviorDesc, GetRandomInt(1,3) - 1))
}
</script>

</turnscript>

</object>

</asl>


I think this code is still missing the code to move the npc_crowd object around, so here's the code with this implemented:

(I had to trouble shoot, so I've altered sgreig's code a bit to get it to work for me, he'll have to help if you want the code to more follow his own, as I had to adjust it to get this to work)

(I got one problem, I can't figure out why upon knocking, it moves the NPC_Crowd back and forth between room and locked_room, I'll check if I got some attribute code that is doing this... as it is the only thing I can think of that may be causing this... lol)

<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="NPC Crowd">
<gameid>70d76bbb-2e9b-455e-a69e-b79f47955343</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
<turns type="int">0</turns>
<statusattributes type="stringdictionary">turns = </statusattributes>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
<drop type="boolean">false</drop>
</object>
<object name="locked_door">
<inherit name="editor_object" />
<drop type="boolean">false</drop>
<knock type="script">
if (NPC_Crowd.parent = locked_room) {
msg ("You hear a voice call out, \"Give me a moment! I'll be right out!\" from behind the door.")
}
else if (NPC_Crowd.parent = room) {
msg ("Nobody answers.")
}
</knock>
</object>
<object name="NPC_Crowd">
<inherit name="editor_object" />
<alias>crowd</alias>
<behaviorDesc type="list">A dusty old tome.; It's a weathered volume.; A very old book with that familiar musty book smell.</behaviorDesc>
<drop type="boolean">false</drop>
<speak type="script">
msg (StringListItem(NPC_Crowd.behaviorDesc, GetRandomInt(1,3) - 1))
</speak>
</object>
</object>
<object name="locked_room">
<inherit name="editor_room" />
</object>
<turnscript>
<enabled />
<script>
SetTurnTimeout (5) {
if (NPC_Crowd.parent = room) {
MoveObject (NPC_Crowd, locked_room)
}
else if (NPC_Crowd.parent = locked_room) {
MoveObject (NPC_Crowd, room)
}
}
</script>
</turnscript>
</asl>

dwn
08 Feb 2013, 17:11
Another example...say after 2 turns, you want an NPC to enter a room, so you move the NPC from one place to another. This bit of code does that, however, the message: "The NCP arrives to check in on you." loops endlessly now, wherever you go and whatever you do, and it is not clear how to make the message only print once. I tried to add disable turnscript, but that didn't seem to work...

Edit: I modified code in attempt to make NPC enter the room after 2 turns, then exit room again after 2 turns. But still get errors and msg lopping....


<!--Saved by Quest 5.3.4762.29157-->
<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="NPC Behavior Automated Event - Turnscripts - Movement Between Rooms">
<gameid>91415345-16e8-48d4-a419-5aa3da6ae105</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
</game>
<object name="Inside House">
<inherit name="editor_room" />
<alias>Inside House</alias>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<turnscript name="NPC_checksin">
<enabled />
<script>
SetTurnTimeout (2) {
msg ("The NPC arrives to check in on you.")
MoveObject (NPC_Busybody, Inside House)
SetTurnTimeoutID (2, "NPC_leavesagain") {
}
MoveObject (NPC_Busybody, Backyard)
msg ("The NPC leaves the room again.")
}
</script>
</turnscript>
<exit alias="south" to="Backyard">
<inherit name="southdirection" />
</exit>
</object>
<object name="Backyard">
<inherit name="editor_room" />
<alias>Backyard</alias>
<object name="NPC_Busybody">
<inherit name="editor_object" />
</object>
<exit alias="north" to="Inside House">
<inherit name="northdirection" />
</exit>
</object>
</asl>

HegemonKhan
08 Feb 2013, 17:43
I was jsut doing some trouble shooting, and just edited this into my previous post (take a look at my previous post if you want to read my comments, otherwise...) here's the code that I just editted onto my previous post:

(I think this does what you wanted, if not, let me know)

<asl version="530">

<include ref="English.aslx" />
<include ref="Core.aslx" />

<game name="NPC Crowd">
<gameid>70d76bbb-2e9b-455e-a69e-b79f47955343</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
<turns type="int">0</turns>
<statusattributes type="stringdictionary">turns = </statusattributes>
</game>

<object name="room">
<inherit name="editor_room" />

<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
<drop type="boolean">false</drop>
</object>

<object name="locked_door">
<inherit name="editor_object" />
<drop type="boolean">false</drop>

<knock type="script">
if (NPC_Crowd.parent = locked_room) {
msg ("You hear a voice call out, \"Give me a moment! I'll be right out!\" from behind the door.")
}
else if (NPC_Crowd.parent = room) {
msg ("Nobody answers.")
}
</knock>

</object>

<object name="NPC_Crowd">

<inherit name="editor_object" />
<alias>crowd</alias>

<behaviorDesc type="list">A dusty old tome.; It's a weathered volume.; A very old book with that familiar musty book smell.</behaviorDesc>

<drop type="boolean">false</drop>

<speak type="script">
msg (StringListItem(NPC_Crowd.behaviorDesc, GetRandomInt(1,3) - 1))
</speak>

</object>

</object>

<object name="locked_room">
<inherit name="editor_room" />
</object>

<turnscript>
<enabled />
<script>
SetTurnTimeout (5) {
if (NPC_Crowd.parent = room) {
MoveObject (NPC_Crowd, locked_room)
}
else if (NPC_Crowd.parent = locked_room) {
MoveObject (NPC_Crowd, room)
}
}
</script>
</turnscript>

</asl>

HegemonKhan
08 Feb 2013, 18:09
also, I think you've got a problem with the space here (spaces are BAD! lol):

Inside House

so change them *ALL* to this (I love using the underscores, lol):

Inside_House

--------------------------

for your looping problem:

(I'm not certain if this is correct, so you may want to ask sgreig or whoever about it~this)

it is your turnscript:

    <turnscript name="NPC_checksin">
<enabled />
<script>
SetTurnTimeout (2) {
msg ("The NPC arrives to check in on you.")
MoveObject (NPC_Busybody, Inside House)
SetTurnTimeoutID (2, "NPC_leavesagain") {
}
MoveObject (NPC_Busybody, Backyard)
msg ("The NPC leaves the room again.")
}
</script>
</turnscript>


you need some if lines, because this is what it is doing right now:

on every 2 turns (turn 2, turn 4, turn 6, etc), move the ' NPC_Busybody ' to ' Inside_House ' and to ' Backyard ', so do you see the problem? it is stuck moving the NPC_Busybody back and forth (forever, continously, looping'ly) between ' Inside_House ' and ' Backyard '

so, to stop this, we need the if script lines:

    <turnscript name="NPC_checksin">
<enabled />
<script>
SetTurnTimeout (2) {

if (NPC_Busybody.parent = Backyard) {
msg ("The NPC arrives to check in on you.")
MoveObject (NPC_Busybody, Inside_House)
}

else if (NPC_Busybody.parent = Inside_House) {
MoveObject (NPC_Busybody, Backyard)
msg ("The NPC leaves the room again.")
}

</script>
</turnscript>


the code reads as this:

on every 2 turns [ SetTurnTimeout (2) { ]

turn 2:

if NPC_Busybody is in Backyard [ NPC_Busybody.parent = Backyard ], then move NPC_Busybody to in Inside_House [ MoveObject (NPC_Busybody, Inside_House) ] + show message [ msg ("The NPC arrives to check in on you.") ]

~OR~ (else)

if NPC_Busybody is in Inside_House [ NPC_Busybody.parent = Inside_House ], then move NPC_Busybody to in Backyard [ MoveObject (NPC_Busybody, Backyard) ] + show message [ msg ("The NPC leaves the room again.") ]

turn 4:

if NPC_Busybody is in Backyard [ NPC_Busybody.parent = Backyard ], then move NPC_Busybody to in Inside_House [ MoveObject (NPC_Busybody, Inside_House) ] + show message [ msg ("The NPC arrives to check in on you.") ]

~OR~ (else)

if NPC_Busybody is in Inside_House [ NPC_Busybody.parent = Inside_House ], then move NPC_Busybody to in Backyard [ MoveObject (NPC_Busybody, Backyard) ] + show message [ msg ("The NPC leaves the room again.") ]

turn 6:

if NPC_Busybody is in Backyard [ NPC_Busybody.parent = Backyard ], then move NPC_Busybody to in Inside_House [ MoveObject (NPC_Busybody, Inside_House) ] + show message [ msg ("The NPC arrives to check in on you.") ]

~OR~ (else)

if NPC_Busybody is in Inside_House [ NPC_Busybody.parent = Inside_House ], then move NPC_Busybody to in Backyard [ MoveObject (NPC_Busybody, Backyard) ] + show message [ msg ("The NPC leaves the room again.") ]

turn etc... :

etc...

sgreig
09 Feb 2013, 10:36
I just made up a sample game to demonstrate the features you wanted but it's not working for me either, and I can't figure out why. I'm assuming there must have been a change in Quest that's causing it because i'm 99% positive it would have worked in Quest 5.0 - 5.2. The turnscript isn't triggering the stuff when it's supposed to happen for some reason. Once I've got it figured out, I'll post it here and have it commented to explain what's going on.

EDIT: Got it sorted. Apparently Quest doesn't like turnscripts nested under objects. Not sure if that's a bug so I'll bring it up with Alex. Here is the code, with comments:


<!--Saved by Quest 5.3.4762.29157-->
<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="test">
<gameid>f26302df-aa5c-4ebd-b389-e9d18be20930</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
<turnCount type="int">0</turnCount> // This is a variable we will use to keep track of the number of turns for the npc behaviour.
</game>
<object name="room1">
<inherit name="editor_room" />
<alias>Library</alias>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="NPC">
<inherit name="editor_object" />
<inherit name="male" />
<alias>Happy McGoo</alias>
<usedefaultprefix />
<look>He stares at you blankly, a small rope of drool forming at the corner of his lopsided grin.</look>
// This creates the string list with the behaviour descriptions. Pretty straightforward.
<behaviorDesc type="list">Happy's index finger begins an exploratory mission to the inner depths of his nasal cavity.; Happy seems to have discovered that the walls make an interesting hollow thumping noise when he slams his forehead against them.; Happy appears to be chewing on something. You figure it's better not to ask questions.</behaviorDesc>
</object>
<exit alias="east" to="room2">
<inherit name="eastdirection" />
</exit>
</object>
<turnscript name="npc_stuff">
<enabled />
<script><![CDATA[
if (GetBoolean(NPC, "following")) { // This line checks to see if the "following" attribute of the npc object is set to true or not.
if (NPC.parent <> player.parent) { // If it IS set to true, this line checks to see if the npc is not in the same room as the player.
NPC.parent = player.parent // This line moves the npc to the room the player is in. If they're already in the same room, this won't happen.
}
}
game.turnCount = game.turnCount + 1 // This line increased the variable game.turnCount by 1 every turn.
if (game.turnCount = 2) { // If game.turnCount = 2, then the next line happens.
if (NPC.parent = player.parent) { // This line checks to see if the npc and the player are in the same room or not. If not, you won't see the behaviour message.
msg (StringListItem(NPC.behaviorDesc, GetRandomInt(1,3) - 1)) // This displays a random behaviour message from the stringlist on the npc object.
}
game.turnCount = 0 // This line resets the game.turnCount variable to 0. This ensures the behaviour messages display every 2 turns.
}
]]></script>
</turnscript>
<object name="room2">
<inherit name="editor_room" />
<alias>Foyer</alias>
<exit alias="west" to="room1">
<inherit name="westdirection" />
</exit>
<exit alias="east" to="room3">
<inherit name="eastdirection" />
</exit>
</object>
<object name="room3">
<inherit name="editor_room" />
<alias>Dining Room</alias>
<object name="Patrol">
<inherit name="editor_object" />
<inherit name="maleplural" />
<alias>Patrol</alias>
<look>A patrol of guards.</look>
</object>
<exit alias="west" to="room2">
<inherit name="westdirection" />
</exit>
</object>
<command name="follow">
<pattern>follow me</pattern> // This line creates the "follow me" command.
<script>
msg ("Happy begins to follow you.") // This gives the player feedback that the command has worked.
SetObjectFlagOn (NPC, "following") // This line sets the NPC.following value to "true" for the turnscript.
</script>
</command>
<command name="unfollow">
<pattern>unfollow me</pattern> // This command allows you to stop the npc from following you.
<script>
SetObjectFlagOff (NPC, "following") // This sets the "following" value on the npc object to "false."
</script>
</command>
<turnscript name="Patrol_Duty"> // This turnscript controls the guards' patrol route.
<enabled />
<script>
SetTurnTimeout (2) { // Every 2 turns
if (Patrol.parent = room3) { // This line checks to see if the patrol is in room3. If so, the patrol is moved to room2 on the next line.
Patrol.parent = room2
Patrol.previousRoom = room3 // This variable is created to keep track of the last room the patrol was in because we want the patrol to go 3-2-1-2-3. Since room2 has 2 exits, we want to make sure the patrol doesn't go back the way they came.
}
else if (Patrol.parent = room2) { // Now, if the patrol is room 2...
if (Patrol.previousRoom = room3) { // We check the previous room variable to determine where to go next. If they were last in room3, we move them to...
Patrol.parent = room1 // room1
}
else if (Patrol.previousRoom = room1) { // Otherwise if they were just in room1 we move them to...
Patrol.parent = room3 // room3
}
}
else if (Patrol.parent = room1) { // If they're currently in room1
Patrol.parent = room2 // Move them to room2
Patrol.previousRoom = room1 // Set the previous room variable to room1.
}
}
</script>
</turnscript>
</asl>


I should mention that as it's written, you can type follow me from any room and Happy will appear. Try reading the comments to figure out how things were implemented and see if you can apply that to changing the follow me command to only work when you're in the same room as Happy. And if you need any more clarification, please ask. :)

HegemonKhan
09 Feb 2013, 16:56
thanks Sgreig!, as I was still working on (unsure of) how to do a "Follow" code myself, also the guard patrol will be useful too.

I also wasn't sure if I could use the ???.parent = ???.parent code or not, though I wasn't using it correctly in my attempt, as I see now.

Now, if I can also remember that the ' <> ' means not equal, lol. I keep using: if (not ???.parent = ???), the <> is much faster!

and I didn't know you can put the // ??? comment code on the same line as your game code lines, as it is more messy putting the // comment code lines below or above your game code lines.

sgreig
09 Feb 2013, 17:05
HegemonKhan wrote:thanks Sgreig!, as I was still working on (unsure of) how to do a "Follow" code myself, also the guard patrol will be useful too.

I also wasn't sure if I could use the ???.parent = ???.parent code or not, though I wasn't using it correctly in my attempt, as I see now.

Now, if I can also remember that the ' <> ' means not equal, lol. I keep using: if (not ???.parent = ???), the <> is much faster!


Hehe you're welcome. It took me quite a while to learn that '<>' means not equal in Quest, as in most other programming languages, "not equal" is '!='. And I'm not sure if it's on the wiki now, but it wasn't when I was first learning and I couldn't find it on the forum anywhere. I had to ask Alex eventually. :)

HegemonKhan
09 Feb 2013, 17:21
for me as a noob, the quest coding is really nice... these other coding languages with their terms or symbols, is confusing, as it's like massive memorization... for me, all those symbols for coding looks so alien... learning some JS... for quest, will be a long long long long ways off for me, lol. I've got enough of a task trying to learn quest's coding, hehe. I'm making progress, at least, though it's slow, I'm so anxious~excited to make an uber ambitious game, but then it's like... oh... I don't know how to do that yet... doh!... have to go learn this coding aspect first... laughs.

I'm really proud of making a functional beginning of a combat system (especially at being able to successfully trouble shoot it the most, this feels more accomplishing then making the code, as if I can trouble shoot, I got to be learning to code, hehe), and I've also made a functional storage system for learned spells, hehe. Now, I've got to do with same for equipment (and then figure out how to implement "items" into the game too, I mean rpg items: useable items, non-useable game progression items, and battle only items), and I also need to learn the list, dictionary, item iteration, "getting", and "checking", and etc like stuff, as this is a vital code for doing almost everything.

then it's back to working on my combat system, implementing in the equipment, magic, items, and a run~escape option too.

dwn
10 Feb 2013, 02:10
HegemonKhan wrote:for me as a noob, the quest coding is really nice... these other coding languages with their terms or symbols, is confusing, as it's like massive memorization... for me, all those symbols for coding looks so alien... learning some JS... for quest, will be a long long long long ways off for me, lol. I've got enough of a task trying to learn quest's coding, hehe. I'm making progress, at least, though it's slow, I'm so anxious~excited to make an uber ambitious game, but then it's like... oh... I don't know how to do that yet... doh!... have to go learn this coding aspect first... laughs.

I'm really proud of making a functional beginning of a combat system (especially at being able to successfully trouble shoot it the most, this feels more accomplishing then making the code, as if I can trouble shoot, I got to be learning to code, hehe), and I've also made a functional storage system for learned spells, hehe. Now, I've got to do with same for equipment (and then figure out how to implement "items" into the game too, I mean rpg items: useable items, non-useable game progression items, and battle only items), and I also need to learn the list, dictionary, item iteration, "getting", and "checking", and etc like stuff, as this is a vital code for doing almost everything.

then it's back to working on my combat system, implementing in the equipment, magic, items, and a run~escape option too.


Yeah, that does sound very ambitious, looking forward to seeing what you come up with! I'm sure a lot of people will be interested in adapting an elaborate combat system for their own games. Thanks for all your help, and see you around the forums!

dwn
10 Feb 2013, 02:13
sgreig wrote:I just made up a sample game to demonstrate the features you wanted but it's not working for me either, and I can't figure out why. I'm assuming there must have been a change in Quest that's causing it because i'm 99% positive it would have worked in Quest 5.0 - 5.2. The turnscript isn't triggering the stuff when it's supposed to happen for some reason. Once I've got it figured out, I'll post it here and have it commented to explain what's going on.

EDIT: Got it sorted. Apparently Quest doesn't like turnscripts nested under objects. Not sure if that's a bug so I'll bring it up with Alex. Here is the code, with comments:


<!--Saved by Quest 5.3.4762.29157-->
<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="test">
<gameid>f26302df-aa5c-4ebd-b389-e9d18be20930</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
<turnCount type="int">0</turnCount> // This is a variable we will use to keep track of the number of turns for the npc behaviour.
</game>
<object name="room1">
<inherit name="editor_room" />
<alias>Library</alias>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="NPC">
<inherit name="editor_object" />
<inherit name="male" />
<alias>Happy McGoo</alias>
<usedefaultprefix />
<look>He stares at you blankly, a small rope of drool forming at the corner of his lopsided grin.</look>
// This creates the string list with the behaviour descriptions. Pretty straightforward.
<behaviorDesc type="list">Happy's index finger begins an exploratory mission to the inner depths of his nasal cavity.; Happy seems to have discovered that the walls make an interesting hollow thumping noise when he slams his forehead against them.; Happy appears to be chewing on something. You figure it's better not to ask questions.</behaviorDesc>
</object>
<exit alias="east" to="room2">
<inherit name="eastdirection" />
</exit>
</object>
<turnscript name="npc_stuff">
<enabled />
<script><![CDATA[
if (GetBoolean(NPC, "following")) { // This line checks to see if the "following" attribute of the npc object is set to true or not.
if (NPC.parent <> player.parent) { // If it IS set to true, this line checks to see if the npc is not in the same room as the player.
NPC.parent = player.parent // This line moves the npc to the room the player is in. If they're already in the same room, this won't happen.
}
}
game.turnCount = game.turnCount + 1 // This line increased the variable game.turnCount by 1 every turn.
if (game.turnCount = 2) { // If game.turnCount = 2, then the next line happens.
if (NPC.parent = player.parent) { // This line checks to see if the npc and the player are in the same room or not. If not, you won't see the behaviour message.
msg (StringListItem(NPC.behaviorDesc, GetRandomInt(1,3) - 1)) // This displays a random behaviour message from the stringlist on the npc object.
}
game.turnCount = 0 // This line resets the game.turnCount variable to 0. This ensures the behaviour messages display every 2 turns.
}
]]></script>
</turnscript>
<object name="room2">
<inherit name="editor_room" />
<alias>Foyer</alias>
<exit alias="west" to="room1">
<inherit name="westdirection" />
</exit>
<exit alias="east" to="room3">
<inherit name="eastdirection" />
</exit>
</object>
<object name="room3">
<inherit name="editor_room" />
<alias>Dining Room</alias>
<object name="Patrol">
<inherit name="editor_object" />
<inherit name="maleplural" />
<alias>Patrol</alias>
<look>A patrol of guards.</look>
</object>
<exit alias="west" to="room2">
<inherit name="westdirection" />
</exit>
</object>
<command name="follow">
<pattern>follow me</pattern> // This line creates the "follow me" command.
<script>
msg ("Happy begins to follow you.") // This gives the player feedback that the command has worked.
SetObjectFlagOn (NPC, "following") // This line sets the NPC.following value to "true" for the turnscript.
</script>
</command>
<command name="unfollow">
<pattern>unfollow me</pattern> // This command allows you to stop the npc from following you.
<script>
SetObjectFlagOff (NPC, "following") // This sets the "following" value on the npc object to "false."
</script>
</command>
<turnscript name="Patrol_Duty"> // This turnscript controls the guards' patrol route.
<enabled />
<script>
SetTurnTimeout (2) { // Every 2 turns
if (Patrol.parent = room3) { // This line checks to see if the patrol is in room3. If so, the patrol is moved to room2 on the next line.
Patrol.parent = room2
Patrol.previousRoom = room3 // This variable is created to keep track of the last room the patrol was in because we want the patrol to go 3-2-1-2-3. Since room2 has 2 exits, we want to make sure the patrol doesn't go back the way they came.
}
else if (Patrol.parent = room2) { // Now, if the patrol is room 2...
if (Patrol.previousRoom = room3) { // We check the previous room variable to determine where to go next. If they were last in room3, we move them to...
Patrol.parent = room1 // room1
}
else if (Patrol.previousRoom = room1) { // Otherwise if they were just in room1 we move them to...
Patrol.parent = room3 // room3
}
}
else if (Patrol.parent = room1) { // If they're currently in room1
Patrol.parent = room2 // Move them to room2
Patrol.previousRoom = room1 // Set the previous room variable to room1.
}
}
</script>
</turnscript>
</asl>


I should mention that as it's written, you can type follow me from any room and Happy will appear. Try reading the comments to figure out how things were implemented and see if you can apply that to changing the follow me command to only work when you're in the same room as Happy. And if you need any more clarification, please ask. :)


Thank you very much, I'll try this later tonight, from looking it over it should keep me busy for awhile in figuring out how everything works!