Prop System

Jump to: navigation, search



Two prop instances whose state (open/closed) is set independently for each player

The Prop System, a part of the Foundation Framework, provides a set of tools which may be used to manage interactive and non-interactive objects. These objects may be introduced to players for the purposes of visualization and interaction, and this introduction may be restricted such that only players who meet certain criteria will be included (e.g. only players with the 'collect acorns' quest will be allowed to see and interact with acorn objects). From the perspective of the world-builder, these objects - once added to a scene - are seamlessly integrated with an area's geometry and may be manipulated with the standard HeroBlade translation tools. Unlike standard area geometry, however, these prop objects may have additional functionality attached to them to restrict visibility, provide interactivity, or to provide any other game-specific behavior required.

The Prop System utilizes the Spec System to store prop type definitions. These definitions are used during construction of prop objects to define their behavior, and each can be overridden, extended or decorated in order to provide game-specific functionality for props. Overriding default functionality and providing restrictions or augmentations to visibility, interactivity, etc, is accomplished either by extending a spec via inheritance or by glomming decorator classes onto the prop spec which offer the desired functionality. An example of a decorator that might extend the default prop functionality is the 'MouseInteractionDecorator' which responds to mouse input events. Additional game-specific decorators may be created, and the base prop spec may be overridden or extended as desired.

By default, the MMO Foundation Framework offers the following functionality for props:

What problem(s) does this solve?

What problem(s) does this not solve?


For World Builders

Prop entry in the Asset Library set to use PropSpec 1

From the perspective of the world-builder, the prop system is fairly seamlessly integrated into the tools they are already familiar with using. Prop type definitions are established in the prop spec editor, individual prop objects are instantiated by adding them to the asset library, and these objects are manipulated in the world using the standard HeroBlade translation tools and prop context menus.

The process of setting up a prop to be instantiated in the world and manipulating it involves the following steps:

Choosing a Prop Spec

image All prop objects are instantiated from prop specs, each of which may extend or override the base behavior. These specs can also be decorated with prop spec decorators to provide additional functionality on a per-spec basis. (example: A sign that can be clicked on in order to be read may be instantiated from one spec; while a an ancient relic that must be discovered, approached and then clicked on to collect may be instantiated from a different one)

In order to determine which spec you want to use for your prop (or to edit an existing spec), you'll first want to open the Prop Spec Selector from the Utilities Interface's "Tools" menu. There, you'll see a list of all prop specs currently defined. Many, such as the "Visible Prop" and "Interactive Prop" specs, are pre-defined and offered as part of the base MMOFF implementation. Others, which your team may implement, will also be listed here.

To use a pre-existing prop spec, simply note the ID of the spec and write it down for use in later steps. To add, edit, or decorate a spec, click either the 'Add', 'Edit' or 'Glom' buttons, respectively.

Adding the Library Command

image Once you know the spec from which you want to instantiate your prop, create a Library entry with an /heprops command similar to the one below:

/heprops library #spec='1'  #fqn='\engine\cleangame\resources\common\utility_box_white01.gr2' #position='$POSITION' #lod='10'

Instantiating and Manipulating Props

image Once the prop has been added to the library, props may be instantiated by selecting the prop in the library and clicking 'Add'. The prop - once instantiated in the world - may be treated like any other asset and repositioned, rotated, scaled or interacted with via the HeroBlade translation tool widgets.

For Developers

Props are - at base - dynamic server objects which respond to spatial awareness events by performing some action; usually, this is simply introduction or removal from a player's awareness (e.g. you've moved within range of a resource node or dynamic object which you should now be able to see). Props can also be used, though, to drive custom game logic which uses spatial awareness (e.g. king-of-the-hill or capture-the-flag logic for a dynamic object; or determining proximity to objects to determine whether interactions are valid). There are several moving parts that are required to work together in order to facilitate this behavior, and - as such - changing the logic for a type of prop (or defining your own) often requires touching multiple classes and multiple scripts.

The pieces involved in creating a new prop from scratch (all of which have both server and client components):

Understanding Prop Instantiation

Props may be instantiated on the server either in the Edit instance of an area or a Play instance. Props instantiated in the Edit instance persist with the area, whereas props instantiated in a play instance are destroyed the moment the area spins down.

The process for instantiating a prop in script is as follows:

specKey as ID = 1 //use any valid specKey for a spec within the _PropSpecOracle
propSpecOracle as NodeRef of Class _PropSpecOracle = $_PROPS._getPropSpecOracle() //get our prop spec oracle
propSpec as NodeRef of Class _PropSpec = propSpecOracle.GetSpecByKey(specKey) //get the spec we're interested in creating a prop from
prop as NodeRef of Class _Prop = propSpec.CreateFromSpec() //create our prop

After the call to 'propSpec.CreateFromSpec()', the following will be true:

That's it! You can now access, modify and use the prop at will.

Understanding Prop Instance Destruction

The process for destroying a prop in script is as follows:

myProp as NodeRef of Class _Prop = 2938717654872

At this point, the prop will have been removed from the area and any spatial awareness tracking or replication will have ceased for it.

Querying For Props

To query for props (perhaps because they were created during a previous session or because you don't store references to them elsewhere), simply make a call to one of the following methods on the $_PROPS system node:

method _FindPropsBySpec(propSpec as NodeRef of Class _PropSpec) as List of NodeRef of Class _Prop
method _GetAllProps() as List of NodeRef of Class _Prop
method _GetAllProxyProps() as List of NodeRef of Class _Prop

Understanding Client/Server Props

The default prop spec is designed to provide an example of creating objects that will only become visible to the player when s/he approaches an object. This is accomplished through clever use of spatial awareness, replication and local client visualizations to give the illusion of permanence for temporary, dynamic objects.

The sequence of events for one of these dynamic replicated objects (all of which is handled within the prop spec and prop classes) is:

Once a dynamic prop is replicated to a player's client, the client may choose to respond by rendering the prop on-screen or triggering some other client-side action.

With this setup, any number of dynamic objects may be created that will respond to spatial awareness events by introducing themselves to players. Additional behavior could be added to these props to - for instance - make the props selective and only introduce themselves to certain players.

Understanding The Prop Spec

Spec editor for Prop Spec 1

The prop spec is comprised of - at minimum - the following methods (in addition to those found on a BaseSpec object):

CreateFromSpec is what handles the physical instantiation of the prop from the _Prop class. After instantiation, this method allows any decorators glommed onto the prop spec to perform any desired initialization, then makes a call to $_PROPS._AddProp to add the prop to the prop system.

At base, a simple implementation of CreateFromSpec in a prop spec looks something like this:

method CreateFromSpec() as NodeRef
  aInstantiatedNode as NodeRef
  if $AREA._IsEditInstance()
    aInstantiatedNode = CreatePersistedNodeFromClass("_Prop")
    aInstantiatedNode = CreateNodeFromClass("_Prop")
  me.OnCreateNotifySpecDecoratorClasses( aInstantiatedNode )
  where aInstantiatedNode is kindof _Prop
  return aInstantiatedNode

In order to support Library instantiation, a prop spec must implement the _LibraryCreateFromSpec method. This method will wrap both the creation of the prop from the spec as well as the interpretation of the library command associated with the Library asset. Additionally, it will give any spec decorators the opportunity to perform initialization on the instantiated prop.

The default implementation of this method (shown below) looks for a '#position' tag embedded in the Library command string and sets the position of the newly instantiated prop to the specified position. It also lets any spec decorators perform initialization by passing the Library command string down into any that are glommed onto the spec.

method _LibraryCreateFromSpec( libraryCmd as String ) as NodeRef
  aInstantiatedNode as NodeRef
  tokens as LookupList indexed by String of String = me._parseTokensFromLibraryCmd( librarycmd )
  pos as Vector3 = tokens["#position"]
  aInstantiatedNode = me.CreateFromSpec()
  where aInstantiatedNode is kindof _Prop
  me._OnLibraryCreateNotifySpecDecoratorClasses( aInstantiatedNode, libraryCmd )
  return aInstantiatedNode  

Creating a New Spec Decorator

The Prop Spec Decorator Editor

The great flexibility of the prop system comes from the fact that props and their specs may be decorated with virtually any behavior desired: different visualization methods, restrictions on introduction/interaction, connections to other game systems - the possibilities are vast.

New prop spec decorators must implement the following methods:

One of these two shared functions will be called depending upon whether the prop is instantiated from the Library or from script. The primary purpose of these methods is to perform operations on the newly instantiated prop to initialize it (such as glomming a decorator class onto the prop and initializing the fields belonging to the glommed class to the correct values).

An example implementation of OnInstantiationFromSpec might be:

shared function OnInstantiationFromSpec( specDerivedObject as NodeRef )
  if not ( specDerivedObject is kindof _VisibleProp )
    GlomClass( "_VisibleProp", specDerivedObject )
  where specDerivedObject is kindof _VisibleProp
    where specDerivedObject is kindof _Prop
      spec as NodeRef of Class _PropSpec = specDerivedObject.GetMySpec()
      where spec is kindof _PropVisualizationDecorator
        specDerivedObject._PropLoD = spec._PropLoD

In the above example, a new class - _VisibleProp - is glommed onto the instantiated prop. This class implements all the functionality required to visualize the prop on the client and will have the opportunity to respond to all events that the prop would normally respond to.


Personal tools