After reading
this thread, I realised that a transparent container is quite good way to have items out of reach, but visible.
ETA:
If you are working on-line, this technique will not work, as you have to override an existing function and a dynamic template.Here then is a complete Quest game (two rooms, four items) that shows that implemented for when the player has to stand on something to reach an item.
<!--Saved by Quest 5.4.4873.16527-->
<asl version="540">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<dynamictemplate name="ObjectNotOpen">DoObjectNotOpen (object)</dynamictemplate>
<game name="shelf">
<gameid>6975d6af-3d28-4f58-aef6-ef3ada36a002</gameid>
<version>1.0</version>
<firstpublished>2013</firstpublished>
</game>
<object name="room">
<inherit name="editor_room" />
<alias>First Room</alias>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
<object name="chair">
<inherit name="editor_object" />
<inherit name="standonable" />
</object>
<object name="shelf">
<inherit name="editor_object" />
<inherit name="container_closed" />
<transparent />
<listchildren />
<open type="boolean">false</open>
<close type="boolean">false</close>
<contentsprefix>holding</contentsprefix>
<cannotreachmsg>The shelf is too high to reach.</cannotreachmsg>
<object name="teapot">
<inherit name="editor_object" />
<take />
</object>
</object>
<object name="cup">
<inherit name="editor_object" />
<take />
</object>
<exit alias="west" to="room2">
<inherit name="westdirection" />
</exit>
<exit alias="up" to="room2">
<inherit name="updirection" />
</exit>
</object>
<command name="standon">
<pattern>stand on #object#;stand #object#;get on #object#;up on #object#</pattern>
<script>
if (object.canstandon) {
if (not object.isstoodon) {
if (not game.pov.isstoodon = null) {
msg ("First you get down from " + GetDisplayName (game.pov.isstoodon) + ".")
game.pov.isstoodon.isstoodon = false
}
if (not object.parent = game.pov.parent) {
msg ("You put down " + GetDisplayName (object) + " on the ground.")
object.parent = game.pov.parent
}
msg ("You stand on " + GetDisplayName (object) + ".")
OpenUnreachables (game.pov.parent)
object.oldroomname = game.pov.parent.alias
object.isstoodon = true
game.pov.isstoodon = object
game.pov.parent.alias = game.pov.parent.alias + " (stood on " + GetDisplayName (object) + ")"
request (UpdateLocation, CapFirst(GetDisplayName(game.pov.parent)))
}
else {
msg ("You are already on it!")
}
}
else {
msg ("You cannot stand on " + GetDisplayName (object) + "!")
}
</script>
</command>
<command name="getoff">
<pattern>get off #object#;off #object#;down from #object#;get down from #object#</pattern>
<script>
if (object.canstandon) {
if (object.isstoodon) {
msg ("You get off " + GetDisplayName (object) + ".")
CloseUnreachables (game.pov.parent)
game.pov.isstoodon = null
game.pov.parent.alias = object.oldroomname
request (UpdateLocation, CapFirst(GetDisplayName(game.pov.parent)))
object.isstoodon = false
}
else {
msg ("You are not on it!")
}
}
else {
msg ("You are not on it - and nor should you be!")
}
</script>
</command>
<object name="room2">
<inherit name="editor_room" />
<alias>Second Room</alias>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<exit alias="east" to="room">
<inherit name="eastdirection" />
</exit>
<exit alias="down" to="room">
<inherit name="downdirection" />
</exit>
<object name="stool">
<inherit name="editor_object" />
<inherit name="standonable" />
</object>
</object>
<type name="standonable">
<canstandon />
<take />
<isstoodon type="boolean">false</isstoodon>
<displayverbs type="stringlist">
<value>Look at</value>
<value>Take</value>
<value>Stand on</value>
<value>Get off</value>
</displayverbs>
</type>
<function name="OnEnterRoom" parameters="oldRoom"><![CDATA[
game.displayroomdescriptiononstart = false
if (IsDefined("oldRoom")) {
if (oldRoom <> null) {
// *** This line added ***
LeavingSoGetOff (oldRoom)
if (HasScript(oldRoom, "onexit")) {
do (oldRoom, "onexit")
}
}
}
on ready {
if ((not GetBoolean(game.pov.parent, "visited")) and HasScript(game.pov.parent, "beforefirstenter")) {
do (game.pov.parent, "beforefirstenter")
}
on ready {
if (HasScript(game.pov.parent, "beforeenter")) {
do (game.pov.parent, "beforeenter")
}
on ready {
if (game.gridmap) {
Grid_CalculateMapCoordinates (game.pov.parent)
Grid_DrawPlayerInRoom (game.pov.parent)
}
if (IsDefined("oldRoom")) {
if (oldRoom <> null) {
msg ("")
}
}
request (UpdateLocation, CapFirst(GetDisplayName(game.pov.parent)))
roomFrameExists = false
if (HasString(game.pov.parent, "picture")) {
if (LengthOf(game.pov.parent.picture) > 0) {
roomFrameExists = true
SetFramePicture (game.pov.parent.picture)
}
}
if (game.clearframe and not roomFrameExists) {
ClearFramePicture
}
if (game.showdescriptiononenter) {
ShowRoomDescription
}
if ((not GetBoolean(game.pov.parent, "visited")) and HasScript(game.pov.parent, "firstenter")) {
do (game.pov.parent, "firstenter")
}
on ready {
if (HasScript(game.pov.parent, "enter")) {
do (game.pov.parent, "enter")
}
}
set (game.pov.parent, "visited", true)
}
}
}
]]></function>
<function name="LeavingSoGetOff" parameters="oldroom">
foreach (o, ScopeVisibleForRoom (oldroom)) {
if (GetBoolean (o, "canstandon") and GetBoolean (o, "isstoodon")) {
msg ("You get off the " + GetDisplayName (o) + ".")
CloseUnreachables (oldroom)
oldroom.alias = o.oldroomname
game.pov.isstoodon = null
}
}
</function>
<function name="OpenUnreachables" parameters="rm">
foreach (o, ScopeVisibleForRoom (rm)) {
if (HasString (o, "cannotreachmsg")) {
o.isopen = true
}
}
</function>
<function name="CloseUnreachables" parameters="rm">
foreach (o, ScopeVisibleForRoom (rm)) {
if (HasString (o, "cannotreachmsg")) {
o.isopen = false
}
}
</function>
<function name="DoObjectNotOpen" parameters="object" type="string">
if (HasString (object, "cannotreachmsg")) {
return (object.cannotreachmsg)
}
else {
return (CapFirst(GetDisplayAlias(object)) + " " + Conjugate(object, "be") + " not open.")
}
</function>
</asl>
The system requires:
1. The object to stand on (chair or stool in the example) must be on type "standonable".
2. The container (the shelf) is set to type "closed container", with transparent ticked; it needs a string attribute "cannotreachmsg".
3. The room has an alias.
The cunning part of the system is to redefine a dynamic template so we can have a custom message when trying to reach an object and the container is closed, so the player is informed the item is out of reach, not that the shelf is closed. This is done via the DoObjectNotOpen function.
It also overrides the stand OnRoomEnter function. There is one line added, and this is flagged. There is a fair chance OnRoomEnter will be updated in later releases of Quest (this is the 5.4 version), and you will have to copy in the new version and insert that extra line yourself.