Skip to content

Commit

Permalink
Adding documentation related to utility functions
Browse files Browse the repository at this point in the history
  • Loading branch information
moufmouf committed Aug 23, 2021
1 parent 017e57d commit 5c8e28e
Show file tree
Hide file tree
Showing 9 changed files with 261 additions and 169 deletions.
181 changes: 12 additions & 169 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ There are many ways to import the `@workadventure/scripting-api-extra` package.
If you only want to use the extra "features", you can directly import the package in your map,
by adding a "script" property at the map level, pointing to the "bundled" package:

`script: https://unpkg.com/@workadventure/scripting-api-extra@1.0.0-alpha.2/dist/bundle.js`
`script: https://unpkg.com/@workadventure/scripting-api-extra@^1/dist/bundle.js`

Please note that you can change the version number of the package in the URL.

Expand All @@ -22,181 +22,24 @@ Please note that you can change the version number of the package in the URL.
If you are developing your own scripts, you can import the library using NPM.

```
npm install --save @workadventure/scripting-api-extra@
npm install --save @workadventure/scripting-api-extra
```

## Functions
## Table of content

### Utility class to analyze properties
### Features

The JSON map can already be fetched using `WA.room.getTiledMap`. But when it comes to analyzing the JSON map, you are on your own.
- [Doors](docs/doors.md)
- [Bells](docs/bells.md)
- [Generic action zones](docs/generic-action-zones.md)

This library comes with helpers to help you read the map.
### Functions

The `Properties` class can be used to analyze properties (that can be put on a variety of objects in Tiled).
- [`Properties`](docs/functions-properties.md) related functions (utility functions to acces properties...)
- [`Variables`](docs/functions-variables.md) related functions (access variables metadata...)
- [`Layers`](docs/functions-layers.md) related functions (get a list of all layers, find layers boundaries...)

Usage:

```typescript
const map = await WA.room.getTiledMap();

const mapProperties = new Properties(map.properties);

// getOne fetches the value of the property passed in parameter.
// Note that it will throw an exception if many properties have the same name.
const name = mapProperties.getOne('name') as string;

// getMany returns an array of values for all properties whose name is passed in parameter.
const scripts = mapProperties.getMany('scripts');

// getOneString is the same as getOne except it ensures the value is a string (and throws an exception if it is not)
const name = mapProperties.getOneString('name');
```

### Return a list of all variables defined in the map

`getAllVariables(): Promise<Map<string, VariableDescriptor>>`: returns a list of all the variables defined in the map.

Variables are returned as a Map. The key is the name of the variable, the value if an object representing the variable.
You can fetch individual properties defined in Tiled for this variable using this object's `properties` attribute.

For instance:

```typescript
import { getAllVariables, VariableDescriptor } from '../VariablesExtra';

const variables = await getAllVariables();
console.log(variables['my_variable'].properties.getOne('persist'));
```

```typescript
class VariableDescriptor {
name: string // the name of the variable
properties: Properties // an object representing the properties of the variable
}
```

### Return a Map of all layers

Layers can be nested in group layers.

The `getLayersMap()` function returns a map of all layers in a uni-dimensional map.
Layers are renamed: if they are in a group layer, the name of the group layer is prepended with a "/" as a separator.
Layers are indexed by name.

```typescript
const layers = await getLayersMap();
const mylayer = layers.get('my_layer');
for (const layer of layers.values()) {
// Iterate over all layers
}
```

### Get boundaries of a layer

`findLayerBoundaries()` can be used to find the boundaries of a given layer.



## Features

### Changing the value of a variable using an action message in a zone

`bindVariable`: The name of a variable that will be altered when one enters/leaves the zone
`zone`: You need to define a zone property for the layer that contains `bindVariable`.
`enterValue`: The value the variable will be set to when entering the zone
`leaveValue`: The value the variable will be set to when leaving the zone
`triggerMessage` (optional): You can optionally add a "trigger message". In this case, the message will be displayed when entering the zone and the variable will only change value when the trigger message is activated by pressing the space bar.
`tag` (optional): Only users with the "tag" passed in parameter will be allowed to set the value. (Note: this is only enforced client side and could be circumvented)

### Doors

In order to create a door, you need to create a "variable" that will contain the state of the door (so "opened" or "closed").

Set the "default" property to "true" (opened by default) or "false" (closed by default).

Then, add a new "door" boolean property and set it to true.

Add 2 layers in your map. One will contain the open door, and the other one the closed door.

Now, add 2 properties to the variable:

- `openLayer`: this will contain the name of the layer that has the opened door
- `closeLayer`: this will contain the name of the layer that has the closed door

Note: for both `openLayer` and `closeLayer`, you can input several layer names separated by a new line character.

Whenever the value of the variable switches from true to false (or the opposite), the door will open or close.

#### Door sound

You can add an opening or closing sound to the door by using the `openSound` or `closeSound` properties of the door variable.

The value of these properties should be a URL to a MP3 file of a sound opening or closing the door.

- `openSound`: URL of the sound of a door opening
- `closeSound`: URL of the sound of a door closing

Anybody on the map will hear the sound of the door opening or closing.
If you want to limit the sound to a certain area, you can use the `soundRadius` property.
`soundRadius` is expressed in pixels. If you are further than `soundRadius` pixels from the center of the door,
you will not hear the door opening or closing. Also, the further you are, the fainter will be the sound.


### Door step

To open or close a door, you can define a special "doorstep" layer that will trigger the opening/closing
when the user walks on it.

You can configure the doorstep to open/close **automatically** or **manually** (by pressing the space key).
You can define special tags a user must have to open/close a door, or even add a code on the door.

```
zone: string // Compulsory: the name of a zone
doorVariable: string // The name of the variable holding the state of the door
autoOpen: boolean // True to open automatically. False to force an interaction
autoClose: boolean // True to close automatically when zone is left. False to force an interaction
openTriggerMessage: string // Message to be displayed to open the door
closeTriggerMessage: string // Message to be displayed to close the door
code: string // The code to open the door (clear text, so not very secure)
codeVariable: string // The name of the variable containing the secret code
tag: string // If set, a user needs to have the given tag to open this door.
```

Note that if you set both a `tag` and a `code`, the door will open without asking the code for people who have the requested tag.

### Bells / Knocking on a door

You can add a bell that will ring automatically or manually when a user walks in a given zone.

In order to create a bell, you need to create a "variable" that will be used to share the fact the bell is ringing.
The value of the variable has no importance, it is just used to propagate the event that the bell is ringing.

Add a new "bell" boolean property and set it to true.

Unlike with classical variables, the position of the variable object is important. The sound will be emitted from this point.

Then add 2 properties

- `bellSound`: URL of the sound of the bell ringing (you can also use a knock-knock-knock sound if you have a door :) )
- `soundRadius` (optional): The radius at which one can hear the sound (expressed in pixels, the sound center being the position of the variable)

The farther you are from the sound center, the less you will hear the sound. If you don't set any soundRadius, the whole
map will hear the sound.

Now, we need to define the position on the map from where the bell sound will be triggered.

Add a tile layer in your map.

On the layer add those properties:

- `zone`: (Compulsory) the name of a zone
- `bellVariable`: (Compulsory) the name of the "bell" variable that will be triggered when someone walks on this layer
- `bellPopup`: the name of a square object on an object layer in the map that will display the "Ring" button to ring the bell. If not set, the bell
will ring automatically when a player enters the zone.
- `bellButtonText`: the text to display in the button to ring the bell. Defaults to "Ring"

### Contributing
## Contributing

```console
# install dependencies
Expand Down
77 changes: 77 additions & 0 deletions docs/functions-layers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{.section-title.accent.text-primary}
# Layers utility functions

{.alert.alert-info}
**Important!** To use these functions, you need to [import the "Scripting API Extra"](utils.md#importing-the-utility-functions) library.

### Return a Map of all layers

Layers can be nested in group layers.

The `getLayersMap()` function returns a map of all layers in a uni-dimensional map.

Layers are **renamed**: if they are in a group layer, the name of the group layer is prepended with a "/" as a separator.

Layers are indexed by name.

```typescript
import {getLayersMap} from '@workadventure/scripting-api-extra';

const layers = await getLayersMap();

// Access a layer directly by name
const mylayer = layers.get('my_layer');

// Iterate over all layers
for (const layer of layers.values()) {
// ...
}
```

### Get boundaries of a layer

`findLayerBoundaries` returns the boundaries of a given layer as an object with properties: { top: number, left: number, right: number, bottom: number }

Numbers are expressed in "tiles", not pixels.

```
findLayerBoundaries(layer: ITiledMapTileLayer): {
top: number;
left: number;
right: number;
bottom: number;
}
```

Example:

```typescript
import {getLayersMap, findLayerBoundaries} from '@workadventure/scripting-api-extra';
import {ITiledMapTileLayer} from "@workadventure/tiled-map-type-guard/dist/ITiledMapTileLayer";

const layers = await getLayersMap();

const layer = layers.get("my_layer") as ITiledMapTileLayer;

const boundaries = findLayerBoundaries(layer);
console.log('Top:' , boundaries.top);
console.log('Left:' , boundaries.left);
console.log('Bottom:' , boundaries.bottom);
console.log('Right:' , boundaries.right);
```

### Get boundaries of several layers

If you are looking for the boundaries of several layers at once, you can use the `findLayersBoundaries` variant.

```
findLayersBoundaries(layers: ITiledMapTileLayer[]): {
top: number;
left: number;
right: number;
bottom: number;
}
```

It will return a square containing all the tiles of all the layers passed in parameters.

39 changes: 39 additions & 0 deletions docs/functions-properties.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{.section-title.accent.text-primary}
# Tiled properties

{.alert.alert-info}
**Important!** To use these functions, you need to [import the "Scripting API Extra"](utils.md#importing-the-utility-functions) library.

In your Tiled map, a number of items can have "properties" (the map itself, layers, tiles, tilesets, objects...).

The JSON map can be fetched using `WA.room.getTiledMap`. But when it comes to analyzing the JSON map, you are on your own.

The Scripting API Extra package comes with a useful `Properties` class to analyze these properties.

Usage:

```typescript
const map = await WA.room.getTiledMap();

const mapProperties = new Properties(map.properties);

// getOne fetches the value of the property passed in parameter.
const name = mapProperties.get('name') as string;

// getString is the same as get except it ensures the value is a string (and throws an exception if it is not)
const name = mapProperties.getString('name');
```

Methods available:

```typescript
class Properties {
get(name: string): string | boolean | number | undefined; // returns the property
getString(name: string): string | undefined; // returns the property (and checks it is a string)
getNumber(name: string): number | undefined; // returns the property (and checks it is a number)
getBoolean(name: string): boolean | undefined; // returns the property (and checks it is a boolean)
mustGetString(name: string): string; // returns the property as a string (throws an Error if not found)
mustGetNumber(name: string): string; // returns the property as a number (throws an Error if not found)
mustGetBoolean(name: string): string; // returns the property as a boolean (throws an Error if not found)
}
```
41 changes: 41 additions & 0 deletions docs/functions-variables.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{.section-title.accent.text-primary}
# Variables metadata

{.alert.alert-info}
**Important!** To use these functions, you need to [import the "Scripting API Extra"](utils.md#importing-the-utility-functions) library.

## Return a list of all variables defined in the map

```
// returns a list of all the variables defined in the map.
getAllVariables(): Promise<Map<string, VariableDescriptor>>
```

Variables are returned as a Map. The key is the name of the variable, the value if an object representing the variable.
You can fetch individual properties defined in Tiled for this variable using this object's `properties` attribute.

For instance:

```typescript
import { getAllVariables, VariableDescriptor } from '@workadventure/scripting-api-extra';

const variables = await getAllVariables();
console.log(variables['my_variable'].properties.getOne('persist'));
```

Note: the `VariableDescriptor` class returned does not contain the value of the variable itself. It represents the
variable object as defined in the Tiled map. This can be useful to access additional metadata that can be stored
in special properties of the variable, or to access the variable "position" in the map (since a variable is represented
by a "Point" object in a map).

```typescript
class VariableDescriptor {
// the name of the variable
name: string
// an object representing the properties of the variable
properties: Properties
// The position of the variable
x: number
y: number
}
```
33 changes: 33 additions & 0 deletions docs/generic-action-zones.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{.section-title.accent.text-primary}
# Action zones

{.alert.alert-info}
**Important!** To use these action zones, you need to [import the "Scripting API Extra" script in your map](about.md#importing-the-extended-features)

You can define special zones that will **alter the value of a ["variable"](https://workadventu.re/map-building/api-state.md)**
when walked upon.

To define such a zone, create a new "tile layer" in Tiled.

In this layer, add these properties:

- `zone`: A unique name for this zone
- `bindVariable`: The name of the variable that will be altered when one enters/leaves the zone
- `enterValue`: (optional) The value the variable will be set to when entering the zone
- `leaveValue`: (optional) The value the variable will be set to when leaving the zone

## User interaction

By default, as soon as anyone enters or leaves the zone, the value of the variable will be changed.

Optionally, you can request a user interaction to trigger the change of the value. Use the `triggerMessage` property
to display a message to the player. When the player presses "SPACE", the value of the variable will be changed to `enterValue`.

## Managing rights

You can restrict who will trigger an action zone using user **tags**.

{.alert.alert-info}
User tags is a feature of the "pro" accounts.

Add a `tag` property on the layer. The variable will only change value if the player walking on the layer has the specified tag.
Loading

0 comments on commit 5c8e28e

Please sign in to comment.