Crystal Entity Layer: 4.3.1 Quest Manager

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 4.3.1 Quest Manager

The quest property classes uses the quest manager in the background so this section will also explain the quest manager.

#### Property Class Details

- Name: ``pcquest'`
- Factory ID: ``cel.pcfactory.quest'`
- Interface: `iPcQuest`
- Header: ``include/propclass/quest.h'`

#### General Information

The quest manager is one of the most important modules in Crystal Entity Layer. A quest is basically a story in a game. With story defined in the very broad sense of the word. A quest can be as simple as a quest to turn on a light in a room if the player clicks on a button to complex quests that keep track of NPC conversation and complex interaction with items. A quest is a state machine. At every given time it is at some specific state and can change state in response to some event. There are quest factories (`iQuestFactory`) and quests (`iQuest`). A factory acts like a template from wich to create quests. In every quest there are basically five different concepts: states, triggers, rewards, responses, and sequences.

#### Triggers

Triggers cause progression in a quest. Whenever a trigger fires the quest will act and execute some rewards (see below). Currently the following triggers are defined in Crystal Entity Layer:

- ``cel.questtrigger.entersector'`: This triggers when a camera enters a sector. See `iEnterSectorQuestTriggerFactory`.
- ``cel.questtrigger.meshentersector'`: This triggers when a mesh enters a sector. See `iEnterSectorQuestTriggerFactory`.
- ``cel.questtrigger.timeout'`: This triggers after a specified time. See `iTimeoutQuestTriggerFactory`.
- ``cel.questtrigger.propertychange'`: This triggers when a property changes. See `iPropertyChangeQuestTriggerFactory`.
- ``cel.questtrigger.sequencefinish'`: This triggers when a sequence finishes. See `iSequenceFinishQuestTriggerFactory`.
- ``cel.questtrigger.trigger'`: This triggers when a pctrigger fires. See `iTriggerQuestTriggerFactory`.
- ``cel.questtrigger.inventory'`: This triggers when an object enters inventory. See `iInventoryQuestTriggerFactory`.
- ``cel.questtrigger.meshselect'`: This triggers when a mesh is selected. See `iMeshSelectQuestTriggerFactory`.

It is of course possible to define your own triggers and register them to the quest manager.

#### Rewards

Whenever a trigger fires one or more rewards are executed. A reward is basically some specific operation that needs to be done in response to a trigger. Currently the following rewards are defined in Crystal Entity Layer:

- ``cel.questreward.debugprint'`: This will print a debug message on stdout. See `iDebugPrintQuestRewardFactory`.
- ``cel.questreward.newstate'`: This will switch to quest a new state. See `iNewStateQuestRewardFactory`.
- ``cel.questreward.changeproperty'`: This will change a property. See `iChangePropertyQuestRewardFactory`.
- ``cel.questreward.inventory'`: This manipulates the inventory. See `iInventoryQuestRewardFactory`.
- ``cel.questreward.sequence'`: This fires a sequence. See `iSequenceQuestRewardFactory`.
- ``cel.questreward.sequencefinish'`: Finishes a sequence. See `iSequenceFinishQuestRewardFactory`.

It is also possible to define your own rewards.

#### Responses

A response is simply one trigger and one or more rewards together. In one state you can define multiple responses. Every response will define a different set of rewards.

#### States

A quest is made out of different states. Every state has zero or more responses.

#### Sequences

A reward is always a one-shot operation. It occurs and besides the effect that it has it immediatelly stops. Sequences, on the other hand, have a duration and represent operations that typically take a few frames to execute. For example, to open a door in response to a trigger one would use a sequence to transform the door for a few frames. Sequences can be fired by a reward. The following operations are currently defined in a sequence:

- ``cel.questseqop.debugprint'`: Prints a debug message on stdout. See `iDebugPrintQuestSeqOpFactory`.
- ``cel.questseqop.transform'`: Transforms a mesh. See `iTransformQuestSeqOpFactory`.
- ``cel.questseqop.movepath'`: Moves a mesh along a path. See `iMovePathQuestSeqOpFactory`.
- ``cel.questseqop.light'`: Animates a light color. See `iLightQuestSeqOpFactory`.

You can define your own sequence operations for the quest manager.

#### Defining a quest in XML

Here we show how you could define a quest in XML. We use the ``cel.addons.questdef'` addon (see section Quest Definition Addon) so that we can embed the quest definition in a regular world file:

    <addon plugin="cel.addons.questdef">
      <quest name="SlideDoor">
        <state name="locked">
          <trigger type="trigger">
            <fireon entity="$this" />
            <reward type="debugprint" message="Door is closed!" />
          </trigger>
          <trigger type="inventory">
            <fireon entity="camera" child_entity="$key_ent" />
            <reward type="debugprint" message="The door is unlocked!" />
            <reward type="changeproperty" entity="$key_ent" pc="pcbillboard"
              property="cel.property.visible" bool="true" />
            <reward type="newstate" state="closed" />
          </trigger>
        </state>
        <state name="closed">
          <trigger type="trigger">
            <fireon entity="$this" />
            <reward type="debugprint" message="Door Opens!" />
            <reward type="sequencefinish" entity="$this" sequence="closedoor" />
            <reward type="sequence" entity="$this" sequence="opendoor" />
            <reward type="newstate" state="opened" />
          </trigger>
        </state>
        <state name="opened">
          <trigger type="trigger">
            <fireon entity="$this" leave="true" />
            <reward type="debugprint" message="Door Closes!" />
            <reward type="sequencefinish" entity="$this" sequence="opendoor" />
            <reward type="sequence" entity="$this" sequence="closedoor" />
            <reward type="newstate" state="closed" />
          </trigger>
        </state>
        <sequence name="opendoor">
          <op type="transform" duration="500" entity="$this">
            <v x="$openx" y="$openy" z="$openz" />
          </op>
        </sequence>
        <sequence name="closedoor">
          <op type="transform" duration="500" entity="$this">
            <v x="$closex" y="$closey" z="$closez" />
        </op>
        </sequence>
      </quest>
    </addon>

This quest has three states: ``locked'`, ``closed'`, and ``opened'`. When using this quest you can start it in any of those three states depending on how you want the door to be when the game starts. To go from ``locked'` to ``closed'` you need an object. The name of that object is given to the ``key_ent'` quest parameter (which is given on quest instantiation). In the ``closed'` state we also look at the trigger to see if we're approaching the door. In that case we print out a message to the user to indicate that the door is still closed.

If the door is in ``closed'` state then we simply wait until the player approaches and then we fire the ``opendoor'` sequence to open the door and go to the ``opened'` state. Similarly for the ``opened'` state where we wait until the player moves away from the trigger.

To define an entity that uses this quest we use the ``cel.addons.celentity'` addon (see section CelEntity Addon) like this:

    <addon plugin="cel.addons.celentity" entityname="SlidingDoor">
      <propclass name="pcmesh">
        <action name="SetMesh">
          <par name="name" string="SlidingDoor" />
        </action>
      </propclass>
      <propclass name="pctrigger">
        <property name="monitor" string="camera" />
        <action name="SetupTriggerSphere">
          <par name="sector" string="Corridors" />
          <par name="position" vector="-118,-8,78.7" />
          <par name="radius" float="4" />
        </action>
      </propclass>
      <propclass name="pcquest">
        <action name="NewQuest">
          <par name="name" string="SlideDoor" />
          <par name="openx" string="-3.5" />
          <par name="openy" string="0" />
          <par name="openz" string="0" />
          <par name="closex" string="3.5" />
          <par name="closey" string="0" />
          <par name="closez" string="0" />
        </action>
        <property name="state" string="closed" />
      </propclass>
    </addon>

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ]

This document was generated using texi2html 1.76.