Verb:empty
Instance of: AdventureJS.Dictionary.Verb
Defined in: Adventure/Dictionary/verbs/empty.js, line 5
Tutorials: Subscriptions HowAVerbIsBuilt HowAVerbWorks ModifyVerbs
Description
Empty tries to empty the given direct object of its contents. Because Aspects can contain both Entities and Substances, emptying means that both the Entities and the Substances will fall out of the source Asset. If an Entity target is given, depending on its capacity, it may not be able to hold all of the contents of the source Asset. In this case, excess Entities and Substances will overflow onto the floor.
empty verb logic
Verb logic falls into a few recognizable patterns. Direction verbs tend to be simple and redirect to tryTravel(). Manipulation verbs test whether one asset is allowed to interact with another asset. Locomotion verbs test the player's current ability to move in a specified way. Many verbs are similar, but no two verbs are identical. Each verb has its quirks. If you would like to learn more about general verb logic, we recommend you see the Verb Anatomy and Verb Process pages. Verb phases and verb actions / reactions offer various hooks to customize verb behavior. If you find that you want still more flexibility, you may want to investigate the modifyVerb method, which lets you replace entire blocks of verb code. You can also write verbs from scratch if you're so inclined. See Modify Verbs for a complete list of verb modification methods.
The following sections provide information that is specific to the verb empty, though they include many features which are common to most verbs.
- Verb Subscriptions enable
emptyto act on specific assets, and provide a collection of properties for customizing those interactions. - Sentence Structures help filter player input by defining what sentence structures
emptycan handle. - Verb Phrases describe the direct and indirect objects that
emptycan handle. - Verb Phase Hooks offer a broad method for authors to hook into default logic and override it with custom code.
- Verb Action Hooks offer a surgical method for authors to hook into
empty's default logic and inject custom code. - Verb Reaction Hooks are like verb actions, but occur as secondary effects of successfully applying
empty. - Verb Params contain properties that are distinct to
empty. Not all verbs have params. - Verb Methods lists the methods that
emptyinherits from the Verb class. - Verb Properties lists the properties that
emptyinherits from the Verb class.
empty subscriptions
An asset must be subscribed to a verb for that verb to act upon that asset (with some exceptions). Though verbs are universal, each asset's verb subscriptions are distinct objects that can be used to customize how a given verb interacts with a given asset. To say it another way, a verb subscription is a collection of properties that defines how a verb should be applied to an asset; which allow authors to override a verb's default behaviors on a per-asset basis.
It's important to note that verb subscriptions need to be declared as direct or indirect, depending on whether the asset will be used as a direct object or indirect object. In the case of "unlock lock with key", the lock is the direct object and the key is the indirect object, and each asset needs to be subscribed to unlock in the appropriate way. (It's allowed, and a common pattern, to subscribe assets directly and indirectly to the same verb.)
Expand for example
MyGame.createAsset({
class: "Lock",
name: "lock",
dov: { unlock: true },
});
MyGame.createAsset({
class: "Key",
name: "key",
iov: { unlock: true },
});
As shown in the above example, dov: { unlock: true } is the minimum that is required to subscribe an asset to a verb. However, verb subscriptions have many properties that can be used to customize how this verb is applied to this asset. (Setting any property eliminates the need to set verb: true. ) Below is a list of verb subscription properties that authors may find useful.
-
automatically
{Boolean}
Allows for some verbs to be performed automatically if context calls for
it; for example, when unlocking a door in order to pass through it. An asset's verb subscription setting takes precedence over game settings.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { automatically: true } }, }); -
automatically_after_use
{Boolean}
This sets it so that a verb can only be applied automatically after a
player has already used it manually. This is to prevent automatic use of
tools from breaking puzzles. For example, imagine one door with many keys
but only one that works; if choosing the right key is part of the puzzle,
this option prevents players from simply saying "unlock door" and having
the right key automatically selected for them. When setting
automatically_after_useto true you don't also have to setautomatically.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { automatically_after_use: true } }, }); -
enabled
{Boolean}
Verb subscriptions are enabled by default, but can be disabled manually.
Temporarily disabling a verb subscription can be a useful method for
controlling an asset. For example, you might disable
openfor a door that needs another action to be completed before it can be opened.Individual verb subscriptions can be enabled / disabled viaExpand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { enabled: true } }, });asset.setDOV(verbname)andasset.unsetDOV(verbname). -
on_success
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default success message. Though a string is expected, this property
is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { on_success: "You empty the universal widget. " } }, }); -
on_first_success
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default success message the first time it is applied to this asset.
Though a string is expected, this property is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { on_first_success: "You empty the universal widget for the first time. " } }, }); -
on_failure
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default failure message. Though a string is expected, this property
is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { on_failure: "You failed to empty the universal widget. " } }, }); -
on_first_failure
{String|Array|Function}
If this property returns a string, the string will be appended to the
verb's default failure message the first time it is applied to this asset.
Though a string is expected, this property is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { on_first_failure: "You failed to empty the universal widget this first time. " } }, }); -
once
{Boolean}
if true, the verb can only be applied once to the asset. The verb
subscription will be disabled after use. No special message will be printed, but subsequent attempts to use the verb on this asset will explain why it can't be used again.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { once: true } }, }); -
then_destroy
{Boolean}
If this property is true, the asset will be destroyed after the verb is
applied.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { then_destroy: true } }, }); -
on_destroy
{String|Array|Function}
If this property returns a string, the asset will be destroyed after the
verb is applied, and the string will be appended to the verb's success
message. Though a string is expected, this property is handled by
getStringArrayFunction().
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { then_destroy: true, on_destroy: "The widget is destroyed!" } }, }); -
with_anything
{Boolean}
Pertains only to indirect objects. If true, this asset can be used as an indirect object of this verb with any direct object.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", iov: { empty: { with_anything: true } }, }); -
with_assets
{Boolean}
Use to specify particular assets that can interact with this one using the given verb. For example "unlock door with key" where the specified key is the only asset that can unlock door. This works distinctly for direct and indirect verb subscriptions. So, for instance, in "unlock door with key", the door might have a direct object subscription, while the key has an indirect object description.
Expand for example
MyGame.createAsset({ class: "Door", name: "gold door", dov: { unlock: { with_assets: [ "gold key" ] } }, }); MyGame.createAsset({ class: "Key", name: "gold key", iov: { unlock: { with_assets: [ "gold door" ] } }, }); -
with_classes
{Array}
Use to specify particular classes that can interact with this asset using the given verb. For example "unlock door with skeleton key" where any instance of the class SkeletonKey can unlock door. This works distinctly for direct and indirect verb subscriptions. So, for instance, in "unlock door with skeleton key", the door might have a direct object subscription, while the key has an indirect object description.
Expand for example
MyGame.createAsset({ class: "Door", name: "red door", dov: { unlock: { with_classes: [ "SkeletonKey" ] } }, }); MyGame.createAsset({ class: "SkeletonKey", name: "skeleton key", iov: { unlock: { with_classes: [ "Door", "Chest" ] } }, }); -
with_nothing
{Array}
Pertains only to direct objects. If true, the specified verb can be applied to the direct object without the use of any indirect object.
Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { with_nothing: true } }, }); -
with_params
{Object}
Used to contain a set of parameters that are specific to this particular verb. For example, plugIn includes
with_params.max_connectionsfor setting limits on how many other assets this asset can be plugged into. See the with_params section on this page to learn more aboutempty's parameters.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { with_params: { empty_property: value } } }, }); -
with_prepositions
{Array}
Use to limit the prepositions that can be used with this asset. For
instance: "knock over umbrella stand" might fail with a message of "you
can't knock over the umbrella stand"; setting
umbrella_stand.dov.knock.with_prepositions = ["over"]will allow the action to succeed.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { with_prepositions: [ "through", "over" ] } }, }); -
doBeforeTry
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
empty's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { doBeforeTry: function () { console.log("empty.doBeforeTry"); }, } }, }); -
doAfterTry
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
empty's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { doAfterTry: function () { console.log("empty.doAfterTry"); }, } }, }); -
doBeforeSuccess
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
empty's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { doBeforeSuccess: function () { console.log("empty.doBeforeSuccess"); }, } }, }); -
doAfterSuccess
{Function}
Verb phases provide methods to override default verb behaviors. See the verb phases section on this page to learn more about
empty's verb phases.Expand for example
MyGame.createAsset({ class: "Entity", name: "universal widget", dov: { empty: { doAfterSuccess: function () { console.log("empty.doAfterSuccess"); }, } }, });
Notes
- To learn more about working with verb subscriptions, see Verb Subscriptions.
- These are most, but not all, of the properties of a verb subscription. For full reference, see the VerbSubscription class.
empty sentence structures
accepts_structures: [
"verb noun",
"verb noun preposition noun"
]
The parser uses multiple filtering methods to try to channel player input into useable tokens. Sentence structures are defined for each verb in order to narrow down the input that the verb can handle. For example, the verb "hit" might accept "verb noun" as in "hit troll", or "verb noun preposition noun" as in "hit troll with sword", whereas an intransitive verb like "jump" might accept "verb" as a complete sentence. Input that isn't accepted will return a warning to the player.
A note about adverbs: though the parser does handle some adverbs, such as "carefully examine tiara" and "turn left", it excludes them from consideration in sentence structures. Due to the slipperyness of the English language, an adverb can appear in multiple positions in a sentence while still describing the same verb, which presents enough possible word combinations to make sentence structures less useful as a filtering tool. Instead, the parser puts adverbs aside and handles them separately.
Notes
- It is possible for authors to modify a verb's structures through the use of modifyVerb.
- To learn more about modifying verbs, see Modify Verbs.
empty phrases
phrase1:
{
accepts_noun:true,
requires_noun: true,
noun_must_be:
{
known: true,
tangible: true,
present_if_tangible: true,
reachable_if_tangible: true,
},
},phrase2:
{
accepts_noun:true,
noun_must_be:
{
known: true,
tangible: true,
present_if_tangible: true,
reachable_if_tangible: true,
},
accepts_preposition:true,
requires_preposition: true,
},
The AdventureJS parser uses multiple filtering methods to try to interpret player input. A verb's phrases may consist of a noun and/or a preposition. Whether any noun is defined as a direct or indirect object is up to that verb's unique logic. Each verb defines a unique set of phrases depending on what its logic can handle. Verbs may handle zero, one, two, or three nouns. The nested noun_must_be object sets conditional qualifiers to help narrow down assets that the verb might act upon. Input that isn't accepted will return a warning to the player.
Notes
- It is possible for authors to modify a verb's phrases through the use of modifyVerb.
- To see a list of properties that can be set for phrases, see the Phrase class.
- To see a list of properties that can be set for phrase.noun_must_be, see the NounMustBe class.
- To learn more about modifying verbs, see Modify Verbs.
empty phase hooks
Verb phase hooks let authors override verb subscriptions for specific assets when empty is applied to them. This is a broad method for customizing verb/noun interactions on a per-asset basis. For example, an author might supply completely different logic for "throw feather" vs "throw baseball" vs "throw anvil".
When empty.do() is called, it attempts to run a sequence of methods, or phases, as listed below. The four hooks have no default logic of their own but provide methods to inject custom code at any point in the life cycle of the verb action. See below for examples of how to use verb phases for empty.
do
doBeforeTry hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
empty: {
doBeforeTry: function( params )
{
let msg = `You're about to try to empty ${this.article_name}. `;
this.game.print(msg);
return;
},
},
},
});
doTry handles logic to determine if empty can be applied
doAfterTry hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
empty: {
doAfterTry: function( params )
{
let msg = `You just tried to empty ${this.article_name}! `;
this.game.print(msg);
return;
},
},
},
});
doBeforeSuccess hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
empty: {
doBeforeSuccess: function( params )
{
let msg = `You're about to succeed in performing empty on ${this.article_name}. `;
this.game.print(msg);
return;
},
},
},
});
doSuccess handles state changes and printing messages
doAfterSuccess hook
MyGame.createAsset({
class: "Entity",
name: "This Asset",
dov: {
empty: {
doAfterSuccess: function( params )
{
let msg = `You succeeded in performing empty on ${this.article_name}. `;
this.game.print(msg);
return;
},
},
},
});
Expand for example
Assets must have separate direct and indirect verb subscriptions. Consider this singing sword, which is directly subscribed to the verb "take". We want our game to print a custom message when the player tries to take the sword, and a different message when the player succeeds in taking it.
MyGame.createAsset({
class: "Sword",
name: "singing sword",
dov: {
take:
{
doAfterTry: function()
{
let msg = "The sword begins to vibrate as your hand curls around its haft. ";
MyGame.print( msg );
},
doAfterSuccess: function()
{
let msg = "The sword bursts into song in your hand. ";
MyGame.print( msg );
},
},
},
});
Now consider this stone, which is indirectly subscribed to "remove". We want to print messages when the sword is removed from it, so we'll hook into the stone's indirect object subscription. We could put this code on either object. A case like this comes down to author's choice.
MyGame.createAsset({
class: "Entity",
name: "stone",
iov: {
remove:
{
doBeforeTry: function()
{
let msg = "Will the stone judge you worthy enough to remove the sword? "
MyGame.print( msg );
},
doAfterSuccess: function()
{
let msg = "With the sword removed, the stone bursts into rubble! ";
MyGame.print( msg );
MyGame.destroyAsset(this);
},
},
},
});
Notes
- To learn more, see verb phase hooks.
- Verb phase hooks are similar to, but distinct from, verb action hooks and verb reaction hooks, which offer more surgical hooks.
empty action hooks
Every asset referred to in the turn's input is checked for verb action hooks. These hooks allow authors to inject custom code or print custom text during verb operations. There are two distinct approaches to defining verb actions, designed to accommodate different levels of scripting experience. Authors may use whichever approach they find most comfortable. For more details, see Action Hooks.
-
Simple approach: Define string properties such as
asset.do_empty. If AdventureJS finds a string, it prints it instead of the default output for that turn. This option is best for authors who want to customize output without writing code. -
Advanced approach: Define method properties such as
asset.doEmpty(). If a method is found, it is called with a parameter object containing any relevant assets from the input (e.g.,asset.doEmpty({asset1,asset2})). The author may use or ignore these parameters. This approach offers complete control over the turn’s outcome: authors can add conditional logic, force success or failure, or revise the default output.
Expand any item to see code examples. Methods are called with a parameter object in the form of action({asset1, asset2, params}) which authors may use or ignore.
tryEmptyThis
Called on This asset in a phrase such as "empty this". Since no indirect object is given, we treat the player character as an indirect object.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which player character uses the verb.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryEmptyThis: function () { let msg = "Found custom method at thing_one.tryEmptyThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryEmptyThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", tryEmptyThis: { "Player Two": function () { let msg = "Found custom method at thing_one.tryEmptyThis['Player Two']()"; MyGame.print(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this particular verb action, asset1 is the player character, because we've treated it as the indirect object in absence of a player specified object.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryEmptyThis: function ({asset1}) { switch (asset1.name) { case "Player Two": let msg = "Found custom method at thing_one.tryEmptyThis('Player Two')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doEmptyThis
Called on This asset in a phrase such as "empty this".
Since no indirect object is given, we treat the player character as an indirect object.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which player character uses the verb.
MyGame.createAsset({ class: "Entity", name: "Thing One", doEmptyThis: function () { let msg = "Found custom method at thing_one.doEmptyThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doEmptyThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", doEmptyThis: { "Player Two": function () { let msg = "Found custom method at thing_one.doEmptyThis['Player Two']()"; MyGame.print(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this particular verb action, asset1 is the player character, because we've treated it as the indirect object in absence of a player specified object.
MyGame.createAsset({ class: "Entity", name: "Thing One", doEmptyThis: function ({asset1}) { switch (asset1.name) { case "Player Two": let msg = "Found custom method at thing_one.doEmptyThis('Player Two')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryEmptyThisPrepositionThat
Called on This asset in a phrase such as "empty this with that", where This is the direct object and That is the indirect object.
tryEmptyThisPrepositionThat mirrors tryEmptyThatPrepositionThis. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", tryEmptyThisWithThat: function () { let msg = "Found custom method at thing_one.tryEmptyThisWithThat()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryEmptyThisPrepositionThatfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", tryEmptyThisWithThat: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.tryEmptyThisWithThat['Second Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing One", tryEmptyThisWithThat: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.tryEmptyThisWithThat('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doEmptyThisPrepositionThat
Called on This asset in a phrase such as "empty this with that", where This is the direct object and That is the indirect object.
doEmptyThisPrepositionThat mirrors doEmptyThatPrepositionThis. One is called on a direct object; the other on an indirect object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing One", doEmptyThisWithThat: function () { let msg = "Found custom method at thing_one.doEmptyThisWithThat()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doEmptyThisPrepositionThatfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing One", doEmptyThisWithThat: { "Thing Two": function (params) { let msg = "Found custom method at thing_one.doEmptyThisWithThat['Second Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing One", doEmptyThisWithThat: function ({asset1}) { switch (asset1.name) { case "Thing Two": let msg = "Found custom method at thing_one.doEmptyThisWithThat('Second Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
tryEmptyThatPrepositionThis
Called on That asset in a phrase such as "empty this with that", where That is the indirect object and This is the direct object.
tryEmptyThatPrepositionThis mirrors tryEmptyThisPrepositionThat. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryEmptyThatWithThis: function () { let msg = "Found custom method at thing_two.tryEmptyThatWithThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
tryEmptyThatPrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing Two", tryEmptyThatWithThis: { "Thing One": function (params) { let msg = "Found custom method at thing_two.tryEmptyThatWithThis['First Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing Two", tryEmptyThatWithThis: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.tryEmptyThatWithThis('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
doEmptyThatPrepositionThis
Called on That asset in a phrase such as "empty this with that", where That is the indirect object and This is the direct object.
doEmptyThatPrepositionThis mirrors doEmptyThisPrepositionThat. One is called on an indirect object; the other on a direct object. These are equivalent, and you may place code on whichever asset makes sense to you.
This example uses "with" as the preposition, but any preposition can set a unique response.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thatasset is.MyGame.createAsset({ class: "Entity", name: "Thing Two", doEmptyThatWithThis: function () { let msg = "Found custom method at thing_two.doEmptyThatWithThis()"; MyGame.print(msg); }, }); -
To limit the method to act only on a certain asset, change the value of
doEmptyThatPrepositionThisfrom a method to an object, use the asset's name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Entity", name: "Thing Two", doEmptyThatWithThis: { "Thing One": function (params) { let msg = "Found custom method at thing_two.doEmptyThatWithThis['First Thing']()"; MyGame.print(msg); } }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter. In this verb action, asset1 is the second noun.
MyGame.createAsset({ class: "Entity", name: "Thing Two", doEmptyThatWithThis: function ({asset1}) { switch (asset1.name) { case "Thing One": let msg = "Found custom method at thing_two.doEmptyThatWithThis('First Thing')"; MyGame.print(msg); break; default: // do nothing and allow the default result break; } return; }, });
Notes
- Verb action hooks are specific to their particular verb.
- Which verb action hooks are called depends on the structure of the player's input. Hooks are checked for every asset in the input, including the player character. Which hooks are called depends on the sentence structure of the player's input:
-
Single-object input (e.g., "empty this"): The hook is called on
Thisasset. Since no indirect object is specified, the player character is treated as an indirect object. -
Multiple-object input (e.g., "empty this with that"): The hook is called depending on the object’s role in the phrase.
doThisPrepositionThatruns onThisdirect object, whiledoThatPrepositionThisruns onThatindirect object. These are equivalent, and you may place code on whichever asset makes sense to you. Any preposition can be used to define a unique response, for exampleempty withvsempty on. -
Sentence structures are commonly mutated during the doTry verb phase, so
tryanddomay act on different sentence structures. -
Verb actions are extremely granular and depend on specific combinations of assets and prepositions. Verb actions are called during a verb's doTry and doSuccess phases, which lets them override a verb's operations. Use them if you want to customize output for specific inputs, but beware of that granularity. Consider
doTake(): it's called when a player takes an asset, so you might want to hook into that; but many other verbs may also move the asset into the player. If you want to catch any method that moves an asset into the player, you may find thedoMoveThisToThatverb reaction more broadly applicable. - By default, string properties override a turn's output, but they can also be set to append or prepend the turn's default output. See verb action hooks for more information.
- Verb reaction hooks are functionally the same as action hooks. The only difference is that reaction hooks are not specific to any verb.
- Verb phase hooks are a different form of hook that allows authors to override entire verb phases.
empty reaction hooks
Every asset affected by the turn is checked for verb reaction hooks. These hooks allow authors to inject custom code or print custom text during verb operations. Verb reactions are subject to String Array Function, which means they can be set to any of those three types. Authors may use whichever they find most comfortable. See verb reaction hooks for details.
- String: If AdventureJS finds a string, it prints it instead of the default output for that turn. This option is best for authors who want to customize output without writing code.
- Array: If AdventureJS finds an array, it will print an item from the array, using randomization or not according to global settings.
-
Functions: Set a function like
asset.doMoveThisToThat(). If a function is found, it is called with a parameter object containing any relevant assets from the input (e.g.,asset.doMoveThisToThat({asset1})). The author may use or ignore these parameters. This approach offers complete control over the turn’s outcome: authors can add conditional logic, force success or failure, or revise the default output.
Expand any item to see code examples. All methods are called with a parameter object in the form of asset.reaction({asset1, asset2, params}) which authors may use or ignore.
doMoveThisFromThat
Called on This Entity asset when it is removed from That Entity asset.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thisis removed from.MyGame.createAsset({ class: "Dagger", name: "Jeweled Dagger", doMoveThisFromThat: function () { let msg = "The jeweled dagger slides free. "; MyGame.overrideOutput(msg); }, }); -
To limit the method to removing
Thisfrom a certainThat, you can change the value ofdoMoveThisFromThatfrom a method to an object, useThatasset name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Dagger", name: "Jeweled Dagger", doMoveThisFromThat: { "Leather Scabbard": function () { let msg = "The jeweled dagger slides free from the leather scabbard. "; MyGame.overrideOutput(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter.
MyGame.createAsset({ class: "Dagger", name: "Jeweled Dagger", doMoveThisFromThat: function ({asset1}) { switch (asset1.name) { case "Leather Scabbard": let msg = "The jeweled dagger slides smoothly from the leather scabbard. "; MyGame.overrideOutput(msg) break; default: // do nothing and allow the default result break; } return; }, });
doMoveThatFromThis
Called on This Entity asset when That Entity asset is removed from it.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which
Thatis removed fromThis.MyGame.createAsset({ class: "Chest", name: "Ornate Chest", doMoveThatFromThis: function () { let msg = "The chest snaps at you! "; MyGame.overrideOutput(msg); }, }); -
To limit the method to act only when removing a certain
ThatfromThis, you can change the value ofdoMoveThisFromThatfrom a method to an object, useThatasset name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Chest", name: "Ornate Chest", doMoveThatFromThis: { "Leather Scabbard": function () { let msg = "The ornate chest snaps at you when you remove the leather scabbard from it. "; MyGame.overrideOutput(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter.
MyGame.createAsset({ class: "Chest", name: "Ornate Chest", doMoveThatFromThis: function ({asset1}) { switch (asset1.name) { case "Leather Scabbard": let msg = "The ornate chest quivers at you when you remove the leather scabbard from it. "; MyGame.overrideOutput(msg) break; default: // do nothing and allow the default result break; } return; }, });
doMoveThisToThat
Called on This Entity asset when it is moved to That Entity asset.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of what
Thisis moved to.MyGame.createAsset({ class: "Torch", name: "burning brand", doMoveThisToThat: function () { let msg = "The burning brand scorches its surroundings. "; MyGame.appendOutput(msg); }, }); -
To limit the method to act only when moving
Thisto a certainThat, you can change the value ofdoMoveThisToThatfrom a method to an object, useThatasset name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Torch", name: "burning brand", doMoveThisToThat: { "funeral pyre": function () { let msg = "The pyre bursts into flame! "; // add logic to change state of pyre MyGame.appendOutput(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter.
MyGame.createAsset({ class: "Torch", name: "burning brand", doMoveThisToThat: function ({asset1}) { switch (asset1.name) { case "funeral pyre": let msg = "The pyre bursts into flame! "; // add logic to change state of pyre MyGame.appendOutput(msg); break; default: // do nothing and allow the default result break; } return; }, });
doMoveThatToThis
Called on an Entity asset when another asset is moved to it.
Called on This Entity asset when That Entity asset is moved to it.
-
In this example, we ignore the passed parameter. This variation results in the same response regardless of which
Thatis moved toThis.MyGame.createAsset({ class: "Chest", name: "Ornate Chest", doMoveThatToThis: function () { let msg = "The chest snaps at you but accepts your offering. "; MyGame.overrideOutput(msg); }, }); -
To limit the method to act only when moving a certain
ThattoThis, you can change the value ofdoMoveThatToThisfrom a method to an object, useThatasset name as a key on the object, and set that key's value to a method instead.MyGame.createAsset({ class: "Chest", name: "Ornate Chest", doMoveThatToThis: { "Golden Idol": function () { let msg = "The ornate chest accepts the golden idol and belches loudly. "; MyGame.overrideOutput(msg); }, }, }); -
Finally, in this example, we apply per-asset logic based on the value of asset1, which is available via our passed parameter.
MyGame.createAsset({ class: "Chest", name: "Ornate Chest", doMoveThatToThis: function ({asset1}) { switch (asset1.name) { case "Golden Idol": let msg = "The ornate chest accepts the golden idol and belches loudly. "; MyGame.overrideOutput(msg); break; default: // do nothing and allow the default result break; } return; }, });
Notes
- See verb reaction hooks for more details.
- Reaction hooks aren't specific to any particular verb.
-
Verb reactions fire at the end of a turn after the verb's doSuccess phase. Many verbs may call the same reactions. For instance, any verb that moves an asset into the player calls
doMoveThisToThat. This makes them more broadly applicable than verb actions and lets you customize the turn's output regardless of what verb is used. - Verb action hooks work the same way as reaction hooks, but are specific to their particular verb.
- Verb phase hooks are a different form of hook that allows authors to override entire verb phases.