(Redirected from Technical:Associations)
Jump to: navigation, search


Associations provide ways of linking various nodes. Associations have a source node, target node, and an association type (also known as an association definition). The term "Association" will depend on context, as to whether it is referring to the association type, or the actual linkage between nodes.


Association types describe the possible relations between various nodes. For example, an association type might be "likes". When an association of that type is present, it implies the target node "likes" the source node. As another example, an altar node might have other nodes upon it, so if the altar node were the source id, the other nodes would be target ids with an association type of "on". There are many different association types such as on, married, inventory, base_hard_association, and so forth. New association types can also be created.

Association types must be defined in the DOM before they can be used. An association type can also belong to a group, and then queries can be run to find the associations of any of the association types in a particular group. Some groups can be designated as exclusive. If an association is a part of any of the association types in an exclusive group, then only one association from that group can link two particular nodes at a time (see "Association Groups" below for more information).

When creating an association, there are three elements required:

The default value of an association variable is (0,"",0), which effectively means three wildcards.

Note that the Association data type is a special one, in that though data types are usually used for fields on a class, associations cannot be assigned to a field. Associations are only for use with variables in scripts, and even then, are used in a limited fashion.


q as list of association
type as string = ""
q = QueryAssociation(parentnode, type, childnode)    // With a null type, all associations between the parent
                                                     //  and childnodes are returned
foreach assoc in q
  when assoc.type
    is "on"
    is "under"
    is "behind"
      scripterror("Unknown association type: " + assoc.type)

Hard and Soft Associations

Association types are defined as either hard or soft, which affects whether or not target nodes are loaded into the game at the same time as their source node. For example, IN would usually be a hard association. If a backpack is loaded into the game, it would make sense for all of the objects in the backpack to be loaded into the game at the same time. MARRIED, however, would be a soft association. Just because one married character was in the game, would not require that the other character be in the game at the same time.

It is recommended that whenever a persistent node is created, that it be associated to the area or at least one other node with a hard association, such as base_hard_association. The reason for this is so that the node can be accessed in the future. Persistent nodes will indeed be saved to the database, but in order for them to ever be loaded into the area again from the database, they still need to have at least one hard association to something else in the game:

  AddAssociation(backpackref, "base_hard_association", swordref)

Associating a Node with an Area

Each area has a root node. Getting the ID of this node is accomplished with the following exposed function, which returns the Area Root Node or World Root Node, depending on which type of server it is called in:

function GetRootNode() as noderef

To associate a node with a particular area, the new node is associated with the appropriate root node.


function MakeANode()
  NewNode as noderef
  RootNode as noderef
  NewNode = CreateNodeFromClass("thingie")
  RootNode = GetRootNode()
  AddAssociation(RootNode, "base_hard_association", NewNode)
function ListAllNodesAttachedToRoot(NodetoDelete references noderef)
  RootNode as noderef = GetRootNode()
  AllTheAssocs as list of association
  AllTheAssocs = QueryAssociation(RootNode, "base_hard_association", None)
  foreach a in AllTheAssocs
    MsgArea("Node found: " +
    if ( = NodetoDelete)
  foreach a in AllTheAssocs
    if not IsAssociationValid(a)
      MsgArea("Invalid association found.")

Note that the above function would not find all the associated nodes in the Area -- it would only find nodes directly associated with the root node. There might be other "children" nodes of those. A recursive loop would still be required to find all the nodes in the area.

Association Groups

Caution: This page may contain information which is Hero's Journey-specific!

An Association Group is an arbitrary grouping of association types. It is possible to make a query based on an Association Group, to see if any associations within a set of different association types are found.

Some Groups are "exclusive" Groups. This means that two nodes can only be associated by one of the association types within that group. For example, in the group "base_hard_association_group" exist the following association types:

If two nodes, Anode and Bnode, are associated with "base_hard_association", and then later they are associated with "inventory", then the original "base_hard_association" will be automatically removed.

Any given association type can only belong to one Association Group at a time.

q as list of association
q = QueryAssociation(parentNode, "base_hard_association_group", childNode)

Association CLI Commands

The following commands can be used to create and manipulate associations via the CLI. Please click on the appropriate command to learn more about it.

Commands can be prefaced with one of the following characters, to made the association in the appropriate GOM.

For more information on Preface commands, please see the section on the CLI.

Create Association

Delete Association

Modify Association

Show Association

Query Association

Association HeroScript Functions

There are various built-in functions that allow for the manipulation of associations.

Add Association

Main page: Add Association

AddAssociation( sourceNode as noderef, associationName as string, targetNode as noderef )

Remove Association

Main page: Remove Association

RemoveAssociation( sourceNode as noderef, associationName as string, targetNode as noderef )

Query Association

Main page: Query Association

This built-in function gets a list of the associations involved with a particular node and association type (what things are "in" a backpack). For more information, please see Query Association.

// Returns a list of all associations between the SOURCE and TARGET nodes that have the specified NAME.
// Any two of the three parameters may act as wildcards if "uninitialized" (e.g., None for the NodeRefs or "" for NAME).
// see documentation:
external function QueryAssociation( source as NodeRef, name as String, target as NodeRef ) as List of Association

There are also specialized external functions for common queries which are both faster at runtime and more compact to code:

// To find a node that has a hard association to the given node.
// Use instead of QueryAssociation( 0, "base_hard_association_group", target)
// Returns NONE if no hard association is found
external function QueryAssocOwner( target as NodeRef ) as NodeRef
// Use these QueryAssociationOne* functions when it is expected there is a single association that matches.
// Additionally, the versions that accept a filterClass allow the query to be more selective.
// Produces a script error if there are more than one match.
// Returns NONE if no match is found.
external function QueryAssociationOneTarget( source as NodeRef, assocType as String) as NodeRef
external function QueryAssociationOneSource( assocType as String, target as NodeRef) as NodeRef
external function QueryAssociationOneTargetByClass( source as NodeRef, associationType as String, filterClass as String ) as NodeRef
external function QueryAssociationOneSourceByClass( filterClass as String, associationType as String, target as NodeRef ) as NodeRef
// Use these functions to get the list of NodeRefs (source or target) instead of a list of associations.
// This is more efficient and convenient when there is no need to check other fields of the association.
// Also, use of the filterClass avoids getting list elements only to be skipped by a later test.
external function QueryAssocTargetsByClass( source as NodeRef, filterClass as String ) as List of NodeRef
external function QueryAssocSourcesByClass( filterClass as String, target as NodeRef ) as List of NodeRef
external function QueryAssociationTargetsByClass( source as NodeRef, assocType as String, filterClass as String ) as List of NodeRef
external function QueryAssociationSourcesByClass( filterClass as String, assocType as String, target as NodeRef ) as List of NodeRef

Is Association Valid

function IsAssociationValid(thing as association) as boolean

This built-in function takes an example of the complex datatype association, and checks if it's valid. For example, if you have deleted a series of nodes, and you're not sure if any of them had related associations. If either the source or target nodes have been deleted or unloaded from the game, this function returns FALSE.


List all associations

myList as list of association
                                     // Note: this would be bad since it could return a very long list
myList = queryAssociation( None, "", None)     // None matches any node, and "" matches any association type
  // This line does the same thing as queryAssociation above
result as list of association = QueryAssociation(None,"",None)
Personal tools