@c -*-texinfo-*-
@node PropClass Quest Manager, PropClass Mesh, Property Classes, Property Classes
@subsection Quest Manager
@cindex quest manager
@cindex @code{iQuestManager}
@cindex @code{iPcQuest}
@cindex trigger
@cindex reward
@cindex sequence

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

@subsubheading Property Class Details

@itemize @bullet
@item @emph{Name}:
@samp{pcquest}
@item @emph{Factory ID}:
@samp{cel.pcfactory.quest}
@item @emph{Interface}:
@code{iPcQuest}
@item @emph{Header}:
@file{include/propclass/quest.h}
@end itemize

@subsubheading General Information

The quest manager is one of the most important modules in Crystal Entity
Layer. A quest is basically a @dfn{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 @sc{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 (@code{iQuestFactory}) and quests (@code{iQuest}). A factory acts
like a template from wich to create quests. In every quest there are basically
five different concepts: @dfn{states}, @dfn{triggers}, @dfn{rewards},
@dfn{responses}, and @dfn{sequences}.

@subsubheading 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:

@itemize @bullet
@item @samp{cel.questtrigger.entersector}:
This triggers when a camera enters a sector. See
@code{iEnterSectorQuestTriggerFactory}.
@item @samp{cel.questtrigger.meshentersector}:
This triggers when a mesh enters a sector. See
@code{iEnterSectorQuestTriggerFactory}.
@item @samp{cel.questtrigger.timeout}:
This triggers after a specified time. See
@code{iTimeoutQuestTriggerFactory}.
@item @samp{cel.questtrigger.propertychange}:
This triggers when a property changes. See
@code{iPropertyChangeQuestTriggerFactory}.
@item @samp{cel.questtrigger.sequencefinish}:
This triggers when a sequence finishes. See
@code{iSequenceFinishQuestTriggerFactory}.
@item @samp{cel.questtrigger.trigger}:
This triggers when a pctrigger fires. See
@code{iTriggerQuestTriggerFactory}.
@item @samp{cel.questtrigger.inventory}:
This triggers when an object enters inventory. See
@code{iInventoryQuestTriggerFactory}.
@item @samp{cel.questtrigger.meshselect}:
This triggers when a mesh is selected. See
@code{iMeshSelectQuestTriggerFactory}.
@end itemize

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

@subsubheading 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:

@itemize @bullet
@item @samp{cel.questreward.debugprint}:
This will print a debug message on stdout. See
@code{iDebugPrintQuestRewardFactory}.
@item @samp{cel.questreward.newstate}:
This will switch to quest a new state. See
@code{iNewStateQuestRewardFactory}.
@item @samp{cel.questreward.changeproperty}:
This will change a property. See
@code{iChangePropertyQuestRewardFactory}.
@item @samp{cel.questreward.inventory}:
This manipulates the inventory. See
@code{iInventoryQuestRewardFactory}.
@item @samp{cel.questreward.sequence}:
This fires a sequence. See @code{iSequenceQuestRewardFactory}.
@item @samp{cel.questreward.sequencefinish}:
Finishes a sequence. See @code{iSequenceFinishQuestRewardFactory}.
@end itemize

It is also possible to define your own rewards.

@subsubheading 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.

@subsubheading States

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

@subsubheading 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:

@itemize @bullet
@item @samp{cel.questseqop.debugprint}:
Prints a debug message on stdout. See
@code{iDebugPrintQuestSeqOpFactory}.
@item @samp{cel.questseqop.transform}:
Transforms a mesh. See @code{iTransformQuestSeqOpFactory}.
@item @samp{cel.questseqop.movepath}:
Moves a mesh along a path. See @code{iMovePathQuestSeqOpFactory}.
@item @samp{cel.questseqop.light}:
Animates a light color. See @code{iLightQuestSeqOpFactory}.
@end itemize

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

@subsubheading Defining a quest in XML

Here we show how you could define a quest in XML. We use the
@samp{cel.addons.questdef} addon (@pxref{Addons QuestDef}) so that we can
embed the quest definition in a regular world file:

@example
<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>
@end example

This quest has three states: @samp{locked}, @samp{closed}, and @samp{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 @samp{locked}
to @samp{closed} you need an object. The name of that object is given to
the @samp{key_ent} quest parameter (which is given on quest instantiation).
In the @samp{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 @samp{closed} state then we simply wait until the player
approaches and then we fire the @samp{opendoor} sequence to open the door
and go to the @samp{opened} state. Similarly for the @samp{opened} state
where we wait until the player moves away from the trigger.

To define an entity that uses this quest we use the @samp{cel.addons.celentity}
addon (@pxref{Addons CelEntity}) like this:

@example
<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>
@end example

