Can't get custom command to work on remote objects! Bug?

tebling
02 Dec 2004, 01:22
Ok here's the scenario: the player has a cellphone that they can (or should be able to) use to call other characters in the game, no matter where they are.

So I have the following code:

	command <call #@obj#> {
msg <#obj#_call>
set numeric <curr_want; $objectproperty(#obj#_call; want)$>
}


The msg command here is just for testing.

In any case, the script above does not work when #obj# is not in the same room as the player. In fact, none of the custom command script is executed - it just prints "I can't see that anywhere".

Interestingly, if I change #@obj# to #obj#, then the script executes even though the object is not in the room. So that's great, BUT then I have the problem that the player can refer to a character by its alias, which breaks the script! UGH.

It seems like the difference in behavior between using '@' and not using it is a genuine bug. Anyone care to comment? Alex?

Thanks!

007bond
02 Dec 2004, 02:03
you need to check if the object is in the current room that the player is in

tebling
02 Dec 2004, 02:07
1) I should be able to call any character even if they're NOT in the room. That's the whole problem.

2) If I could move the object TO the current room, then move it back, I would. But that custom command script doesn't even execute, preventing me from doing that.

007bond
02 Dec 2004, 02:15
this is where the built-in commands come in. If we had more built-in commands for these things, it would help a lot more in the time it takes to make games, and it would make more time for people like Alan to write other libraries for more advanced things. Another dissappointment is that you can't check if an object is in a certain room, just the current room, which sucks.

tebling
02 Dec 2004, 02:17
Actually, upon further reflection, I think I know why this is happening.

The whole point of using #@obj# is to disambiguate an object in the current room from another object (presumably elsewhere) with the same alias. Therefore, if none of the objects with that alias are in the room, then Quest doesn't really know what to do - and so it says "I can't see that here".

It seems like the proper behavior would be to see if objects with duplicate aliases even exist. If they don't, and there's only one object with that alias (as in my case), then the choice of #obj# is obvious and it shouldn't give up so easily. It's only in the case where there *are* duplicate aliases where you'd have no way to disambiguate the two - and in that case I can see why you may want to just "error" out.

tebling
02 Dec 2004, 02:19
007bond - you can check to see where an object is. Use the $locationof$ function. Works like a charm!

007bond
02 Dec 2004, 02:20
oh. i didn't know that. tks

I think Im Dead
02 Dec 2004, 04:35
What you want to do is have a cell phone that can basically check to see if an object exists anywhere in the game, then if it does, show the call message for that object, right?

If so I'd suggest doing something like this...



command <call #someone#> {
if exists <#someone#> and property <#someone#; call> then {
msg <whatever scripts you want to execute if it is someone you can call that exists in the game, go in here.>
}
else msg <Call who?|n>
}



The "if exists" checks if an object is defined in the game, not wether it is in the same room or available to mess with, just that it exists. Alternately you could use "if real" to test if an object is defined in the game and is free to be manipulated(available). Hope that helps you get an idea of how you can make what you want to happen.

Anonymous
02 Dec 2004, 05:41
Thanks ITID, but what you've suggested doesn't really address the problem.

The problem is that I can't use #someone#, I have to use #@someone#, since I've aliased the people's full names with first names. And if I do that, then no matter whether the object exists or not, it will *always* say "I can't see that here" if the object is not in the same room as the player.

Make sense?

007bond
02 Dec 2004, 06:32
i get what your saying, and this is why i would like an if statement condition that checked if 1) the object is in a specific room, not just the current room, and 2) to check if an object exists.

Anonymous
02 Dec 2004, 12:28
All you need to do this is already available in Quest, you just have to use the tools provided :shock:

Because the #@(objname)# construct is designed to disambiguate things locally, you cannot use it easily when you want a command to refer to an object not present in the current (or otherwise specified) room(s).

I hit this same problem when writing typelib - I needed players to be able to act on things that were not actually in the current room as they were in 'containers' - so I wrote a simple function to get around the issue. I've quickly 'bodged' together this altered function which will I think put you on the right road.

It looks like this.

define function <realname>
set string <tempname;$parameter(1)$>
set string <realname; >
if exists <#tempname#> then set <realname;#tempname#>
if (#realname#=) then set string <realname;$getobjectname(#tempname#; game)$>
return <#realname#>
end define


and you'd call it like so:

set string <obj; $realname(#obj#)$>


What it does is return the object's proper name when passed either the alias (or the correct name!) as the parameter of the function, but only if the object exists somewhere in the game world. It returns an empty string if the object doesn't exist.

Rather that explain how it works, here is a working demo. I've coded four people in a different room to the player, Boris aliased as 'bartender') who has a called action, Henry (no alias) who also has a called action, Claudia (aliased as 'dancer') no called action and Jenny (no alias and no called action).

Obviously only those with 'called' actions will respond to being called, (the guys) the others (girls) will ignore you - a bit like life really :-) These four cover the full range of possibilties between them.

Try this little demo to see how it works.

' "TEST"
' Created with QDK 3.52

define game <TEST>
asl-version <350>
gametype singleplayer
start <hall>
game author <MaDbRiT>
game info <Created with QDK 3.52>
command <call #obj#> {
set string <obj; $realname(#obj#)$>
if action <#obj#;called> then {
doaction <#obj#;called>
}
else {
msg <A nice lady tells you the phone you tried to call is unavailable.>
}
}
end define

define synonyms
end define

define function <realname>
set string <tempname;$parameter(1)$>
set string <realname; >
if exists <#tempname#> then set <realname;#tempname#>
if (#realname#=) then set string <realname;$getobjectname(#tempname#; game)$>
return <#realname#>
end define


define room <hall>
look <The hall.>
west <bar>
end define

define room <bar>
look <The bar.>
east <hall>

define object <Boris>
alias <bartender>
prefix <the>
action <called> {
msg <From the earpiece come Boris's cultured tones - "Naff off I'm busy!">
}
end define

define object <Claudia>
alias <dancer>
prefix <the>
end define

define object <Henry>
action <called> {
msg <From the earpiece comes Henry's high pitced voice - "Oooh, hello sailor!">
}
end define

define object <Jenny>

end define

end define

define text <intro>

end define

define text <win>

end define

define text <lose>

end define


In a real game you might want to differentiate between those who exist and have no phone and those who simply don't exist - that's a simple 'if' based on the content of #realname# and I'll leave it to you.

Al (MaDbRiT)

paul_one
02 Dec 2004, 15:15
Al, Let's suppose the alias <> real name...

In your script it would go through to the second if (if (#realname#=)) ... The problem is it will execute either of these if's....

if exists <#alias#> will execute if alias = realname
if (#realname#=) will execute if the first doesn't run.

I don't understand why you don't just use $getobjectname()$ straight away, instead of using the first if... surely even if the object wasn't alias'ed (or the alias is the objects real name) it would return the objects name anyway...

Anonymous
02 Dec 2004, 16:13
CW wrote:

I don't understand why you don't just use $getobjectname()$ straight away, instead of using the first if... surely even if the object wasn't alias'ed (or the alias is the objects real name) it would return the objects name anyway



surely? ahem - I'm afraid not, $getobjectname(#whatever#)$ actually returns an error if you supply it with something that is not a valid alias. That is why I do the check in two stages.

My code does it this way;

I first check if an object with the passed name exists (note that this test will only return true if the actual object name is passed, an alias will return false)

if it does return true, the job is done and my function returns the real name of the object :-)

If the first check returns 'false' it may be that the name passed was for an object that doesn't exist at all, or that the name passed was in fact an alias for a real object in the game.

So the second test (only be performed if the first has failed) therefore uses $getobjectname(#obj#; game)$ to return either the real name of the #obj# if an alias for an existing object was passed, or an error ("!") if it wasn't an alias that was passed (e.g. an unrecognized word).

The function thus returns the "real name" of the #obj# passed, whether you pass it the real name or an alias - so long as the #obj# actually exists somewhere in the game. If the #obj# passed isn't resolvable to a real object in the game then the function returns an error.

I'm sure it could be written other ways, but I hope this explains why I didn't go straight to the '$getobjectname(#obj#; location)$' test :-)

Al (MaDbRiT)

paul_one
02 Dec 2004, 16:54
Ah, ok. Thanks Al for the swift reply...

So it checks the name, if it doesn't exist, then it get's either the alias or an ! (error).
Returning the error if it is an error.... OK, I get it now.
Cheers.

steve the gaming guy
02 Dec 2004, 18:46
As educational as this post thread was (and it really was), tebling, how many people are actually needed to be called in this game?

Just curious... :shock:

tebling
02 Dec 2004, 19:40
Al,

Your workaround is quite elegant, thanks VERY much for posting it! I'll drop it in when I get a chance.

Steve, I've got 8 characters in so far, but there will be more. I'm working on a relationship building sim (a subset of which is the so-called "dating sim"), so that's why the "call" command needs to be as abstract as possible.

Thanks again guys!

steve the gaming guy
10 Dec 2004, 19:34
I'm posting under this thread because it seems somewhat related.

First, here is a clip from the help section in QDK:

Actions: Actions are script commands that you associate with an object, room or object type. In our "edible" example above we would add an action called "eat" to our object type. We might then add a Custom Command which would accept "eat #@object#", and then its script would run #object#'s "eat" action. This would then allow any edible object to be eaten - and if we needed a particular object to do something special when eaten, we could simply override our default "eat" action from our "edible" type by adding a different "eat" action to our particular object.



This makes me believe that you set it up in the game properties. I was wondering when you create an object, can you, under the interations tab of that object, set up a custom command to interact with that one object? I have a few examples but here is just one: Let's say the player finds a genii's lamp. The obvious command would probably be 'rub lamp' and then run a script based on that command. Does 'rub lamp' have to be in the game properties or can't the word 'rub' be in the actions tab under the lamp object itself?
I tried that but it doesn't seem to work.

The reason why I had used the word 'rub' in that way was because Al MaDbRiT gave me an idea when he used the word 'take' under the action tab. (which works)

Anonymous
10 Dec 2004, 20:20
Hi Steve

I'm afraid the answer is no (AFAIK) - you can set up a user command globally (in the game properties) which will be available anywhere in the game, or locally (in a room definition block) in which case the command works only in the one room it is defined in. You cannot set up a user command within an object definition to only work with that object.

The reason that adding a 'take' action works is because typelib adds a global user command 'take' that calls the inbuilt 'take' action of whatever object it is used on, so you are just replacing the action bit called by the user command in typelib with your own variation.

What you probably ought to do is code a global 'rub' command, but then use a conditional to restrict it to only being useful on the lamp object. I say global not local because this has the added bonus of not giving the impression that 'rub' is not understood as a word if it is tried on another object.

Al (MaDbRiT)

steve the gaming guy
10 Dec 2004, 20:26
Ah, ok. I was going to set it up globally but wanted to check on that question first.

One thing I noticed in Alex's example in help on QDK is the eating action. You can 'eat' an object if it has the edible type which basically means you can use one action on many things (based on type). So of course, my question is the opposite where I was asking if multiple custom commands can be entered for one object.
Soooo, seeing that the answer is no, that frees my mind a bit so while I'm working on the global commands I won't be thinking constantly, "Gee, is there a quicker way to do this?"
hahaha...Thanks again, Mr. bRiT :lol: :lol: :lol: :lol: