Adding verbs to an object's display verb list

ELGAROU
01 Feb 2014, 19:18
Hey, I finished my first gamebook, and now im trying to make a text adventure but so far I'm stuck struggling with this problem:

I want that the first time that the player take a look to the the verblist of an object it shows only one verb (lets say talk), but when the player already have selected to talk to the object then verblist show another verb (ask for example).

I also wonder how is that some games have such customized games interfaces, like "dream pieces".

And finally, what programming languaje should I have learn to understand better the stuff like funtions and more advanced features of Quest.

Greetings

george
01 Feb 2014, 19:28
I'll try your questions backward:

3) learning Javascript (JS), CSS and HTML will help you the most at first with Quest I think.

2) Games like Dream Pieces probably customize their CSS and maybe JS to make them look different from regular Quest games

1) You can change the list of an object's display verbs by changing this stringlist attribute,

http://quest5.net/wiki/Displayverbs

http://quest5.net/wiki/Stringlist

So the basic idea is, when a player talks to the object, run a script that changes the displayverbs.

ELGAROU
01 Feb 2014, 19:35
Thanks a lot.

ELGAROU
01 Feb 2014, 21:50
I thought that the "add value to a list" script would do the trick, but it doesn't work even when I'm pretty sure that I'm introducing the parameters in the right way:

"list add (object.displayverbs, object.ask)"

I have my doubts how it is suppose to work when "displayverb" is a stringlist and I'm trying to add a script to the list, however when tried to enter plain text and testing the game I get this error:

"Error running script: Cannot modify the contents of this list as it is defined by an inherited type. Clone it before attempting to modify."

george
01 Feb 2014, 22:01
Yes, you don't want to add a script to a string list. But for the error see this,

http://quest5.net/wiki/Notes

HegemonKhan
01 Feb 2014, 22:17
I think you can override this, if you override the inherited "displayverbs" Attribute:

the inherited "(I presume, as I haven't looked it up, it's) editor_object" Object Type provides the "displayverbs" special built-in String List to that Object, so you need to override this, by adding the "displayverbs" yourself to that Object:

(and you also may need to change the settings in the GUI~Editor, as it has setting options that deals with the "displayverbs")

In-Code:

<object name="???">
-> <inherit name="editor_object" />
-> <attr name="displayverbs" type="simplestringlist">Look at; Drop; Take; etc</attr> // hopefully, this will override the "displayverbs" Attribute from the inherited trait, hopefully allowing your ' list add ' scripting to now work...
</object>

In GUI~Editor:

(I'm not sure if this will work, or if this is how it's done)

"???" Object -> Attributes (Tab) -> Attributes -> Add ->

Attribute Name: displayverbs
Attribute Type: stringlist
Attribute Value: Look at;Take;Drop;etc

-----

and now within a scripting:

hopefully the ' list add (this.displayverbs, "ask") ', will now work.

or, you could also try to just re-set the "displayverbs" Attribute too:

this.displayverbs = split ("Look at;Take;Drop;etc;Ask",";")

-----

otherwise, make the copy as George shown.

-----

P.S.

within the Object, you can add extra verbs into the displayverbs via:

<object name="???">
-> <inherit name="editor_object" />
-> <attr name="displayverbs" type="listextend">Ask</attr>
</object>

what the "listextend" does is to add the verb to the list (and thus not re-creating~resetting the list):

Look at;Take;Drop;etc (original~old~initial~starting "displayverbs" list) + Ask (from "listextend") = Look at;Take;Drop;etc;Ask

but, this doesn't help you in what you asked for in how to add a verb after an action~event happens (ie adding a verb via scripting), as your Object will start with this verb already, which is what you don't want.

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

Pixie in his~her Spell Library does this (except he~she creates a custom Object Type to do it), though with "inventoryverbs" instead of "displayverbs":

( also, this is an older version of quest, so you'll have to replace the, type="list", to, type="simplestringlist" )

  <!-- Object types -->

<type name="spell">
<inventoryverbs type="list">Learn</inventoryverbs>
<displayverbs type="list">Learn</displayverbs>
<drop type="boolean">false</drop>
<take type="boolean">false</take>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<learn type="script"><![CDATA[
if (not this.parent = player) {
this.parent = player
this.inventoryverbs = Split ("Cast", " ")
msg (DynamicTemplate("SpellLearnt", this))
}
else {
msg ("[SpellAlreadyKnown]")
}
]]></learn>
</type>


<?xml version="1.0"?>
<library>


<!--
This library adds a basic magic system to quest. It allows for three types of spells:

nonattackspell: Instant effect
lastingspell: An on-going spell. These last until another spell is cast
attackspell: Instant effect, attacking anything of the "monster" type that is not dead

Attack spells must be of an element, and eight are already set up. Monsters
can be assigned to elements too; they will be immune to that element, but take
four-fold damage from the opposed element.

A "Magic" tab is added to the editor to make setting up spells and monsters as easy as possible.
-->

<!--
Adding new elements involves a bit of effort. This system requires that elements are added in pairs or opposites,
such as fire and frost.
1. Create a new type for both elements, named [elemem]_type
2. In the data section, the object element_struct needs both elements added to both "elements" and
"opposedelements", and for the latter you need to put them in both ways around (look at existing entries)
3. You need to add both elements to the tab, both for "monster" and for "attackspell". Again, see existing
entries.
-->


<!-- =================================================== -->
<!-- Templates -->

<!--
Using templates makes it easier to convert to other languages, but also for other users to word it how they want it.
When templates are in the library that uses them (as here) the way to change the language is to
modify the template in the library, so really the only benefit is that all the text is together here.
Also modify the default responses in the verbs!
-->

<template name="Learn">learn</template>
<template name="Cast">cast</template>

<template name="LookDead">Oh, and it is dead.</template>
<template name="SpellAlreadyKnown">Er, you already know that one!</template>
<template name="SpellNotKnown">Er, you don't know that one!</template>
<template name="NoMonstersPresent">No monsters present</template>

<dynamictemplate name="SpellEnds"><![CDATA["The <i>" + GetDisplayAlias(object) + "</i> spell ends."]]></dynamictemplate>
<dynamictemplate name="SpellCast"><![CDATA["You cast <i>" + GetDisplayAlias(object) + "</i>."]]></dynamictemplate>
<dynamictemplate name="SpellLearnt"><![CDATA["In a process that seems at once unfathomable, and yet familiar, the spell fades away, and you realise you are now able to cast the <i>" + GetDisplayAlias(object) + "</i> spell."]]></dynamictemplate>



<!-- =================================================== -->
<!-- Verbs -->

<verb>
<property>learn</property>
<pattern>[Learn]</pattern>
<defaultexpression>"You can't learn " + object.article + "."</defaultexpression>
</verb>
<verb>
<property>cast</property>
<pattern>[Cast]</pattern>
<defaultexpression>"You can't cast " + object.article + "."</defaultexpression>
</verb>


<!-- =================================================== -->
<!-- Functions -->

<!--
Handles an attack on the given monster, using the given spell.
Monster loses hit points according to the spell's powerrating.
If they share an element, then no damage, if elements are opposed, damage is multplied by 4
Handles monsters with no elements too, but spell must have an element set.
-->
<function name="SpellAttackMonster" parameters="monster, spell"><![CDATA[
element = GetElement (monster)
handled = False
if (not element = Null) {
if (DoesInherit (spell, element + "_type")) {
msg ("... " + monster.ignoreselement)
handled = True
}
if (DoesInherit (spell, StringDictionaryItem (element_struct.opposedelements, element) + "_type")) {
monster.hitpoints = monster.hitpoints - 4 * spell.powerrating
handled = True
if (monster.hitpoints > 0) {
msg ("... " + monster.hurtbyelement)
}
else {
msg ("... " + monster.deathbyelement)
Death (monster)
}
}
}

if (not handled) {
monster.hitpoints = monster.hitpoints - spell.powerrating
if (monster.hitpoints > 0) {
msg ("... " + monster.hurt)
}
else {
msg ("... " + monster.death)
Death (monster)
}
}
]]></function>


<!--
Call this when a spell is cast, to ensure any on-going spells
are terminated.
-->
<function name="CancelSpell"><![CDATA[
if (HasObject (player, "currentspell")) {
spell = player.currentspell
msg (DynamicTemplate("SpellEnds", spell))
player.currentspell = null
if (HasScript (spell, "terminate")) {
do (spell, "terminate")
}
}
]]></function>


<!--
Call this when a monster dies for some housekeeping.
-->
<function name="Death" parameters="monster"><![CDATA[
monster.alias = monster.alias + " (dead)"
if (HasString (monster, "lookwhendead")) {
monster.look = monster.lookwhendead
}
else {
monster.look = monster.look + " [LookDead]"
}
monster.dead = True
]]></function>


<!--
Returns as a string the name of this object's element (or null).
-->
<function name="GetElement" parameters="obj" type="string"><![CDATA[
result = Null
foreach (element, element_struct.elements) {
type = element + "_type"
if (DoesInherit (obj, type)) {
result = element
}
}
return (result)
]]></function>


<!--
Describes casting
-->
<function name="DescribeCast" parameters="spell"><![CDATA[
if (HasString (spell, "description")) {
msg (DynamicTemplate("SpellCast", spell) + " " + spell.description)
}
else {
msg (DynamicTemplate("SpellCast", spell))
}
]]></function>


<!-- =================================================== -->
<!-- Object types -->

<type name="spell">
<inventoryverbs type="list">Learn</inventoryverbs>
<displayverbs type="list">Learn</displayverbs>
<drop type="boolean">false</drop>
<take type="boolean">false</take>
<usedefaultprefix type="boolean">false</usedefaultprefix>
<learn type="script"><![CDATA[
if (not this.parent = player) {
this.parent = player
this.inventoryverbs = Split ("Cast", " ")
msg (DynamicTemplate("SpellLearnt", this))
}
else {
msg ("[SpellAlreadyKnown]")
}
]]></learn>
</type>



<type name="attackspell">
<inherit name="spell"/>
<cast type="script"><![CDATA[
// Check the player has the spell
// If so iterate through all objects in the room
// Apply attack to those with the monster type that are not dead
if (this.parent = player) {
DescribeCast (this)
flag = False
foreach (obj, ScopeVisibleNotHeld ()) {
if (DoesInherit (obj, "monster") and not GetBoolean (obj, "dead")) {
SpellAttackMonster (obj, this)
flag = True
}
}
if (not flag) {
msg ("... [NoMonstersPresent]")
}
CancelSpell ()
}
else {
msg ("[SpellNotKnown]")
}
]]></cast>
</type>


<type name="nonattackspell">
<inherit name="spell"/>
<cast type="script"><![CDATA[
if (this.parent = player) {
DescribeCast (this)
do (this, "spelleffect")
CancelSpell ()
}
else {
msg ("[SpellNotKnown]")
}
]]></cast>
</type>


<type name="lastingspell">
<inherit name="spell"/>
<cast type="script"><![CDATA[
if (this.parent = player) {
DescribeCast (this)
do (this, "spelleffect")
CancelSpell ()
player.currentspell = this
player.status = this.status
}
else {
msg ("[SpellNotKnown]")
}
]]></cast>
</type>


<type name="fire_type">
</type>

<type name="frost_type">
</type>

<type name="storm_type">
</type>

<type name="earthmight_type">
</type>

<type name="shadow_type">
</type>

<type name="rainbow_type">
</type>

<type name="divine_type">
</type>

<type name="necrotic_type">
</type>

<type name="monster">
</type>


<!-- =================================================== -->
<!-- Data -->

<!--
This is a data store for elements (I call it a "struct" after the keyword in the C programming language)
If you add more elements to the name, you need to add them to both lists as well as creating a new type.
Note that your new type must end "_type", but that must not be included on these lists.
-->
<object name="element_struct">
<elements type="list">fire; frost; storm; earthmight; shadow; rainbow; divine; necrotic</elements>
<opposedelements type="stringdictionary">fire = frost;frost = fire;storm = earthmight;earthmight = storm;shadow = rainbow;rainbow = shadow;necrotic = divine;divine=necrotic</opposedelements>
</object>


<!-- =================================================== -->
<!-- Tabs -->

<tab>
<parent>_ObjectEditor</parent>
<caption>Magic</caption>
<mustnotinherit>editor_room; defaultplayer</mustnotinherit>

<control>
<controltype>dropdowntypes</controltype>
<caption>Spell type</caption>
<types>*=None; nonattackspell=Non-attack spell; lastingspell=Lasting spell; attackspell=Attack spell; monster=Monster</types>
<width>150</width>
</control>



<control>
<controltype>title</controltype>
<caption>Non-Attack Spell</caption>
<mustinherit>nonattackspell</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description (optional)</caption>
<attribute>description</attribute>
<mustinherit>nonattackspell</mustinherit>
</control>

<control>
<controltype>script</controltype>
<caption>Spell effect</caption>
<attribute>spelleffect</attribute>
<mustinherit>nonattackspell</mustinherit>
</control>



<control>
<controltype>title</controltype>
<caption>Lasting Spell</caption>
<mustinherit>lastingspell</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description (optional)</caption>
<attribute>description</attribute>
<mustinherit>lastingspell</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Status when active</caption>
<attribute>status</attribute>
<mustinherit>lastingspell</mustinherit>
</control>

<control>
<controltype>script</controltype>
<caption>Spell effect</caption>
<attribute>spelleffect</attribute>
<mustinherit>lastingspell</mustinherit>
</control>

<control>
<controltype>script</controltype>
<caption>Cacel spell effect</caption>
<attribute>terminate</attribute>
<mustinherit>lastingspell</mustinherit>
</control>



<control>
<controltype>title</controltype>
<caption>Attack Spell</caption>
<mustinherit>attackspell</mustinherit>
</control>

<control>
<controltype>number</controltype>
<caption>Power of attack (1-10)</caption>
<attribute>powerrating</attribute>
<width>100</width>
<mustinherit>attackspell</mustinherit>
<minimum>0</minimum>
<maximum>10</maximum>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description (optional)</caption>
<attribute>description</attribute>
<mustinherit>attackspell</mustinherit>
</control>

<control>
<controltype>dropdowntypes</controltype>
<caption>Element</caption>
<types>*=None; fire_type=Fire; frost_type=Frost; storm_type=Storm; earthmight_type=Earthmight; shadow_type=Shadow; rainbow_type=Rainbow; necrotic_type=Necrotic; divine_type=Divine</types>
<width>150</width>
<mustinherit>attackspell</mustinherit>
</control>



<control>
<controltype>title</controltype>
<caption>Monster</caption>
<mustinherit>monster</mustinherit>
</control>

<control>
<controltype>dropdowntypes</controltype>
<caption>Element</caption>
<types>*=None; fire_type=Fire; frost_type=Frost; storm_type=Storm; earthmight_type=Earthmight; shadow_type=Shadow; rainbow_type=Rainbow; necrotic_type=Necrotic; divine_type=Divine</types>
<width>150</width>
<mustinherit>monster</mustinherit>
</control>

<control>
<controltype>number</controltype>
<caption>Hit points</caption>
<attribute>hitpoints</attribute>
<width>100</width>
<mustinherit>monster</mustinherit>
<minimum>0</minimum>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description on injury</caption>
<attribute>hurt</attribute>
<mustinherit>monster</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description on death</caption>
<attribute>death</attribute>
<mustinherit>monster</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description on injury by opposed element</caption>
<attribute>hurtbyelement</attribute>
<mustinherit>monster</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description on death by opposed element</caption>
<attribute>deathbyelement</attribute>
<mustinherit>monster</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Description on ignore</caption>
<attribute>ignoreselement</attribute>
<mustinherit>monster</mustinherit>
</control>

<control>
<controltype>textbox</controltype>
<caption>Look (when dead)</caption>
<attribute>lookwhendead</attribute>
<mustinherit>monster</mustinherit>
</control>

</tab>
</library>

ELGAROU
01 Feb 2014, 22:44
So finally it works, I cloned object.displayverb then just used the "add value to a list" script and using the same name of the verb in plain text, but it called the script anyway.


Object.displayverbs = Object.displayverbs
firsttime {
list add (Object.displayverbs, "ask")
}

Thanks for the help.