A more emersive way to experience story in Darkflame Universe.
## What is Darkflame Cinema?
Darkflame Cinema is a way to create interactive — acted — experiences in Darkflame Universe. It aims to provide a complement to the ordinary mission structure with static NPCs and mission texts to convey story. Insperation is drawn from games likes of World of Warcraft, where NPCs frequently act out scenes, alone and in combination with both the player and other NPCs.
## Top-level design
Cinema works with a few concepts:
* **Actors** are the non player characters that act and perform actions.
* **Props** are objects in the world which complement the actors.
* **Scenes** are a collection of actors and props that perform an interactive play.
* **Plays** are scenes which are performed to a player.
## Play isolation
When a play is performed to a player, it is always isolated from the rest of the players in the world. This is to ensure that the player can experience the play without being disturbed by others, and others can't be disturbed by the play. This is achieved by ghosting all NPCs and props in the play to all players except the one experiencing the play.
See <ahref="./media/acting.mp4">media/acting.mp4</a> for an example of how to act out a scene.
To start acting type: `/record-start (clear/copy)` in the chat. This will start recording your actions in the world. The actions recorded include:
* Movement
* Talking
* Equipping and unequipping items
* Explicit animations
By appending `clear` to the command, all gear on the NPC will be removed before reenactment. By appending `copy` to the command, all gear on the NPC will be copied from the player before reenactment. Which, if either, of these options to use depends on which NPC object will be acting. Usually you want to use `copy`. This can be edited manually later.
This acting is the core of the scene. Later we will learn how to add some interactivity to the scene.
When you are done acting, type `/record-stop` in the chat. This will stop recording your actions in the world.
Save your amazing performance by typing `/record-save <file.xml>` in the chat. **Do not forget to do this before starting your next recording!** This will save your performance to a file relative to where the server is running.
If your scene has multiple NPCs acting, now is the time to switch to the next NPC and repeat the steps above.
#### 1.1. Previewing your performances
See <ahref="./media/preview.mp4">media/preview.mp4</a> for an example of how to preview a performance.
To show a preview of the performance you can type `/record-act (lot) (name)`, this will play the performance. If a lot is specified, the actor will be of that object. If a name is specified, the actor will have that name. If neither is specified, the actor will be a predetermined NPC.
You may load a performance by typing `/record-load <file.xml>` in the chat. This will load a performance from a file relative to where the server is running. You may than type `/record-act` to show a preview of the performance.
### 2. Create prefabs of props in the scene
Prefabs are a collection of objects that can be instantiated together. This is currently done exclusively by writing xml files.
Here is an example of a prefab:
```xml
<Prefab>
<!--
Lot is the id of the object to spawn.
Position is defined in either coordinates (x,y,z).
These are relative to the position of the prefab.
Rotation is defined in either euler angles (rx,ry,rz);
or in a quaternion (qx,qy,qz,qw).
Use /pos and /rot in the chat to get your current position and rotation.
Actors are defined by their name and the file which holds the performance.
See media/my-act.xml and media/my-act-2.xml for these files.
-->
<NPCname="John"act="vanity/acts/my-act.xml"/>
<NPCname="Bill"act="vanity/acts/my-act-2.xml"/>
</Scene>
```
See <ahref="./media/scene.mp4">media/scene.mp4</a> for how the above scene looks in the world.
You preview a scene by typing `/scene-act <file.xml>` in the chat. This will act out the scene for you.
### 4. Edit the performed acts
When you preview a newly created scene the NPCs will act out exactly what you did when you recorded the performance. This is not always what you want. You may want to add some interactivity to the scene. This is done by editing the performed acts.
An act is made out of a collection of records which will be evaluated in order. A record either performs some visual action or provides for flow control.
Here is an example of a slightly modified act which adds some interactivity:
```xml
<!--
See media/my-act-mod.xml for this file.
-->
<Recorder>
<!-- The following three records were added automaticly because I appended 'copy' to the command when I acted, but these may be modified freely here. -->
The following records will assure that before the act continues, the player is within 10 units of the NPC.
If the player is not within 10 units of them within 5 seconds, the NPC will ask the player to come closer. The NPC will continue to ask the player to come closer every 5 seconds until the player is within 10 units of them.
-->
<!--
This is flow-control, the act will jump to the record with the name "check-player". This makes sure that if the player is already close enough, the NPC does not tell them to come closer.
-->
<JumpRecordlabel="check-player"t="0"/>
<!--
This is a manually added speak record, which will have the NPC speak, telling the player to come closer.
This is a player proximity record, it can branch two different ways. If the player comes within 10 units of the NPC within 5 seconds, the act will continue to the record. If however, the player is not within 10 units within 5 seconds, the act will jump to the record named "join-me", the record above this one.
See <ahref="./media/interactive.mp4">media/interactive.mp4</a> for how the above scene looks in the world.
The list of available records is extensive.
#### 4.1. Records
Each record specifies a time `t`. This is how long after this record is evaluated that the next record will be evaluated.
A record may also specify a `name`. This is used for flow control. If a record specifies a name, it may be jumped to by for example `JumpRecord` or `ForkRecord`.
#### 4.1. MovementRecord
This record sets the properties of the actors controllable physics component. This is the only record which isn't meant to be edited manually.
#### 4.2. SpeakRecord
This record makes the actor speak.
```xml
<SpeakRecordtext="Hello!"t="3.0"/>
```
#### 4.3. EquipRecord
This record makes the actor equip an item.
```xml
<EquipRecorditem="9856"t="0"/>
```
#### 4.4. UnequipRecord
This record makes the actor unequip an item.
```xml
<UnequipRecorditem="9856"t="0"/>
```
#### 4.5. ClearEquippedRecord
This record makes the actor unequip all items.
```xml
<ClearEquippedRecordt="0"/>
```
#### 4.6. AnimationRecord
This record makes the actor play an animation.
```xml
<AnimationRecordanimation="salute"t="2.0"/>
```
#### 4.7. WaitRecord
This record makes the actor wait for a specified amount of time.
```xml
<WaitRecordt="5.5"/>
```
#### 4.8. JumpRecord
This record makes the act jump to a record with a specified name.
```xml
<JumpRecordlabel="check-player"t="0"/>
```
#### 4.9. ForkRecord
This record makes a decision based on a condition, and jumps accordingly. The condition may either be a scene variable or a precondtion.
```xml
<!-- Jump to 'jump-true' if my-variable=1, else jump to 'jump-false'. -->
This record checks if the player is within a specified distance of the actor. If the player is within the distance, the act will continue to the next record. If the player is not within the distance, the act will jump to a record with a specified name.
```xml
<!-- Specifying the timeout is optional. If it is not specified, the act will wait forever for the player to come within the distance. -->
This record makes the act wait until it gets a signal to continue from another act, or until an optional timeout is reached. This is useful for synchronizing multiple actors, for example in a conversation.
```xml
<!-- Specifying the timeout is optional. If it is not specified, the act will wait forever for the signal. -->
### 5. Setting up the scene to be performed automatically
Scenes can be appended with metadata to describe when they should be performed and what consequences they have. This is done by editing the scene file.
#### 5.1. Scene metadata
There attributes can be added to the `Scene` tag:
| Attribute | Description |
| --- | --- |
| `x y z` | The center of where the following two attributes <br> are measured. |
| `showingDistance` | The distance at which the scene will <br> be loaded for a player.<br><br> If the player exits this area the scene is unloaded. <br> If the scene has been registered as having been<br>viewed by the player, is is concluded. |
| `performingDistance` | The scene is registred as having been <br>viewed by the player. This doesn't mean <br>it can't be viewed again.<br><br>A signal named `"audiance"` will be <br> sent when the player enters this area. <br>This can be used to trigger the main <br>part of the scene. |
| `acceptMission` | The mission with the given id will be <br> accepted when the scene is concluded. |
| `completeMission` | The mission with the given id will be <br> completed when the scene is concluded. |
In either the worldconfig.ini or sharedconfig.ini file, add the following:
```
# Path to where scenes are located.
scenes_directory=vanity/scenes/
```
Now move the scene into a subdirectory of the scenes directory. The name of the subdirectory should be **the zone id** of the zone the scene is located in.
For example:
```
build/
├── vanity/
│ ├── scenes/
│ │ ├── 1900/
│ │ │ ├── my-scene.xml
```
Now the scene will be setup automatically and loaded when the player enters the `showingDistance` of the scene.
#### 5.3. Adding conditions
Conditions can be added to the scene to make it only performable when the player fulfills specified preconditions. This is done by editing the scene file.
<Preconditionexpression="42,99"/><!-- The player must fulfill preconditions 42 and 99. -->
<Preconditionexpression="666"not="1"/><!-- The player cannot fulfill precondition 666. -->
...
</Scene>
```
### 6. Hiding zone objects while performing
When a scene should be performed, you might want to hide some objects in the zone. This is done by adding server preconditions. This is a seperate file.
In either the worldconfig.ini or sharedconfig.ini file, add the following: