Portal
A library module for spawning creatures, teleporting tokens, and picking locations. Check the wiki for the scripting API.
Portal Class Documentation
Overview
The Portal
class provides a flexible interface for creating and managing portals. It allows you to set various properties such as origin, size, color, and texture, and supports functionalities like adding creatures, spawning them, teleporting tokens, and displaying dialogs.
Properties
- template: Returns the current template of the portal.
- tokens: Returns an array of tokens associated with the portal.
- origin: Returns the origin coordinates of the portal.
- radius: Returns the radius of the portal.
- texture: Returns the texture of the portal.
Methods
addCreature
Adds a creature to the portal.
Syntax:
addCreature(creature, { updateData = null, count = 1 } = {})
Parameters:
creature
: Can be a single creature, an array of creatures, a token, token document, actor, or a string identifier (uuid or name).updateData
: Optional. Update data for the creature.count
: Optional. Number of creatures to add (default is 1).
Example:
portal.addCreature("Aboleth", { count: 3 });
Example updateData:
Click to expand
const updateData = {
token: {
name: "Aboleth Clone",
texture: {
src: "icons/svg/dice-target.svg",
}
elevation: 10,
},
actor: {
system: {
attributes: {
hp: {
value: 150,
max: 150
}
}
}
},
embedded: {
Item: {
"Fireball": {
name: "Improved Fireball",
system: {
damage: {
parts: [["8d6", "fire"]]
}
}
}
}
}
};
origin
Sets the origin of the portal.
Syntax:
origin(origin)
Parameters:
origin
: Coordinates or a token/document.
Example:
portal.origin({ x: 100, y: 200 });
size
Sets the radius of the portal.
Syntax:
size(radius)
Parameters:
radius
: The radius value.
Example:
portal.size(30);
color
Sets the color of the portal.
Syntax:
color(color)
Parameters:
color
: The color value.
Example:
portal.color("#ff0000");
range
Sets the range of the portal.
Syntax:
range(range)
Parameters:
range
: The range value.
Example:
portal.range(60);
texture
Sets the texture of the portal.
Syntax:
texture(texture)
Parameters:
texture
: The texture URL or path.
Example:
portal.texture("icons/svg/dice-target.svg");
delay
Sets ta delay between a location beeing picked and the tokens being spawned.
Syntax:
delay(delay)
Parameters:
delay
: The delay in milliseconds.
Example:
portal.delay(1000);
setLocation
Sets the location of the portal bypassing the picking process.
Syntax:
setLocation(origin)
Parameters:
origin
: An object with x and y properties or a MeasuredTemplate or MeasuredTemplateDocument.
Example:
portal.setLocation({x: 100, y: 200});
pick
Picks a location for the portal template asynchronously.
Syntax:
async pick(options = {})
Parameters:
options
: Options for picking the template.
Example:
const position = await portal.pick();
spawn
Spawns the portal and its associated tokens.
Syntax:
async spawn(options = {})
Parameters:
options
: Options for spawning.
Example:
await portal.spawn();
dialog
Opens a dialog for user interaction to configure and/or spawn the portal.
Syntax:
async dialog(options = { spawn: true, multipleChoice: false, title: `${MODULE_ID}.DIALOG.Title` })
Parameters:
options
: Options for the dialog.spawn
: Whether to spawn the portal after the dialog (default is true).multipleChoice
: Whether multiple selections are allowed (default is false).title
: The title of the dialog.
Example:
await portal.dialog({ spawn: true, multipleChoice: false, title: "Portal Configuration" });
teleport
Teleports a token to the portal location.
Syntax:
async teleport(options = {})
Parameters:
options
: Options for teleporting.
Example:
await portal.teleport();
transform
Transforms the origin
to a creature added with addCreature
.
Syntax:
async transform(options = {})
Parameters:
options
: Options for transforming.
Example:
await portal.transform();
addActorAttribute
Adds an attribute key which should be kept when the actor is transformed.
Syntax:
addActorAttribute(attributeKey)
Parameters:
attributeKey
: The attribute key to add.
Example:
portal.addActorAttribute("system.attributes");
addTokenAttribute
Adds an attribute key which should be kept when the token is transformed.
Syntax:
addTokenAttribute(attributeKey)
Parameters:
attributeKey
: The attribute key to add.
Example:
portal.addTokenAttribute("texture.src");
Static Methods
spawn
Creates and spawns a new portal.
Syntax:
static async spawn(options = {})
Parameters:
options
: Options for spawning.
Example:
await Portal.spawn({ creature: "Aboleth", count: 3 });
Examples
Spawning a creature
Basic Spawning
new Portal()
.addCreature("Aboleth", {count: 3})
.spawn()
or using the quick shorthand
Portal.spawn("Aboleth")
Advanced Spawning
new Portal()
.addCreature("Aboleth", {count: 3})
.color("#ff0000")
.texture("icons/svg/dice-target.svg")
.origin(token)
.range(60)
.spawn()
Getting the spawned creatures
const portal = new Portal();
//...setup the portal
const creatures = await portal.spawn();
Using the spawned creatures with Sequencer
There is nothing special to know for using Portal with Sequencer, simply spawn the creature and pass it over to Sequencer like you would any other token.
const portal = new Portal();
portal.addCreature("Aboleth", {count: 1});
const [summon] = await portal.spawn();
new Sequence()
.effect("modules/animated-spell-effects-cartoon/spell-effects/cartoon/water/acid_splash_CIRCLE_01.webm")
.atLocation(summon)
.play();
Picking and Spawning Separately
const portal = new Portal();
portal.addCreature("Aboleth", {count: 1});
const location = await portal.pick();
//Do something with the location for example a Sequencer animation
new Sequence()
.effect("modules/animated-spell-effects-cartoon/spell-effects/cartoon/water/acid_splash_CIRCLE_01.webm")
.atLocation(location)
.play();
const [summon] = await portal.spawn();
Teleporting a token
Basic Teleporting
new Portal()
.origin(token)
.teleport()
Advanced Teleporting
new Portal()
.color("#ff0000")
.texture("icons/svg/dice-target.svg")
.origin(token)
.range(60)
.teleport()
Picking a location
Basic Picking
new Portal()
.pick()
Advanced Picking
new Portal()
.color("#ff0000")
.texture("icons/svg/dice-target.svg")
.origin(token)
.range(60)
.pick()
Spawning with a Choice Dialog
new Portal()
.addCreature("Acolyte", {count: 3})
.addCreature("Aboleth", {count: 3})
.dialog();
Transforming Tokens
Basic Transformation
new Portal()
.origin(token)
.addCreature("Aboleth")
.transform()
Transformation with Actor Attributes
new Portal()
.origin(token)
.addCreature("Aboleth")
.addActorAttribute("system.attributes")
.addActorAttribute("system.resources.hp")
.addTokenAttribute("texture.src")
.transform()
Form Builder
The Form Builder is a simple way to create forms with a easy to use macro syntax.
API Reference
render()
Asynchronously renders the form and returns a promise that resolves when the form user confirms the submission and returns the form data. If the form is closed, returns false
.
const formBuilder = new FormBuilder();
// Configure the form
const data = await form.render();
form()
Returns an instance of FormHelper
configured with the current state of tabs, fields, buttons, and options.
const formHelper = formBuilder.form();
title(title)
Sets the title of the form.
-
Parameters:
title
(String): The title of the form.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.title("Character Creation Form");
info(info)
Sets the info text of the form.
-
Parameters:
info
(String): The info text of the form. Can be HTML.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.info("This is a form for creating a character");
size({width, height})
Sets the size of the form.
-
Parameters:
width
(Number, optional): The width of the form in pixels. Defaults to560
if not provided.height
(Number|String, optional): The height of the form in pixels. Defaults to"auto"
if not provided.
-
Returns:
FormBuilder
instance (for method chaining).
Example:
formBuilder.size({width: 800, height: 600});
object(object)
Associates an object with the form, populating fields values with the object's properties.
-
Parameters:
object
(Object): The object whose properties will populate the form fields values.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.object(characterData);
submitButton({enabled = true, label = "Confirm", icon = "fa-solid fa-check"} = {})
Configures the submit button. The submit button is enabled by default.
-
Parameters:
enabled
(Boolean, optional): Whether the submit button is enabled. Defaults totrue
.label
(String, optional): The label for the submit button. Defaults to"Confirm"
.icon
(String, optional): The icon class for the submit button. Defaults to"fa-solid fa-check"
.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.submitButton({label: "Create Character", icon: "fa-solid fa-dice-d20"});
tab({id, group, icon, label, active = false} = {})
Creates a new tab or closes the current tab if id
is not provided.
-
Parameters:
id
(String): The identifier for the tab.group
(String, optional): The group to which the tab belongs. Defaults to"sheet"
.icon
(String, optional): The icon class for the tab.label
(String, optional): The label for the tab.active
(Boolean, optional): Whether the tab is active. Defaults tofalse
.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.tab({id: "general", label: "General Info", icon: "fa-solid fa-info-circle", active: true});
fieldset({legend} = {})
Creates a new fieldset or closes the current fieldset if legend
is not provided.
-
Parameters:
legend
(String): The legend for the fieldset.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.fieldset({legend: "Attributes"});
text({name, label, hint, value})
Adds a text input field to the form.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(String): The default value for the field.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.text({name: "characterName", label: "Character Name", hint: "Enter your character's name", value: ""});
number({name, label, hint, value, min, max, step})
Adds a number input field to the form.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(Number): The default value for the field.min
(Number, optional): The minimum value.max
(Number, optional): The maximum value.step
(Number, optional): The step increment.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.number({name: "strength", label: "Strength", hint: "Enter your character's strength", value: 10, min: 1, max: 20, step: 1});
checkbox({name, label, hint, value})
Adds a checkbox input field to the form.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(Boolean): The default value for the field.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.checkbox({name: "darkVision", label: "Dark Vision", hint: "Check if your character has dark vision", value: false});
color({name, label, hint, value})
Adds a color picker input field to the form.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(String): The default value for the field (in hex format).
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.color({name: "eyeColor", label: "Eye Color", hint: "Select your character's eye color", value: "#0000ff"});
file({name, type, label, hint, value})
Adds a file picker input field to the form.
-
Parameters:
name
(String): The name of the field.type
(String, optional): The type of file picker. Defaults to"imagevideo"
.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(String): The default value for the field.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.file({name: "characterPortrait", type: "image", label: "Character Portrait", hint: "Upload your character's portrait", value: ""});
select({name, label, hint, value, options})
Adds a select (dropdown) input field to the form.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(String|Number): The default value for the field.options
(Object): The options for the dropdown. Keys are option values and values are option labels.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.select({name: "characterClass", label: "Class", hint: "Select your character's class", value: "warrior", options: {"warrior": "Warrior", "mage": "Mage", "rogue": "Rogue"}});
multiSelect({name, label, hint, value, options})
Adds a multi-select (dropdown) input field to the form.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(Array): The default values for the field.options
(Object): The options for the dropdown. Keys are option values and values are option labels.
-
Returns:
FormBuilder
instance (for method chaining).
formBuilder.multiSelect({name: "skills", label: "Skills", hint: "Select your character's skills", value: ["stealth", "archery"], options: {"stealth": "Stealth", "archery": "Archery", "magic": "Magic"}});
editor({name, label, hint, value})
Adds a rich text editor input field to the form.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(String): The default value for the field, which can contain HTML content.
-
Returns:
FormBuilder
instance (for method chaining).
Example:
formBuilder.editor({
name: "characterBackstory",
label: "Character Backstory",
hint: "Enter a detailed backstory for your character",
value: "<p>Once upon a time...</p>"
});
textArea({name, label, hint, value})
Adds a text area input field to the form for entering multiline text.
-
Parameters:
name
(String): The name of the field.label
(String): The label for the field.hint
(String): A hint or placeholder for the field.value
(Object): The default value for the field.
-
Returns:
FormBuilder
instance (for method chaining).
Example:
formBuilder.textArea({
name: "inventory",
label: "Inventory",
hint: "Enter your character's inventory",
value: "A sword, a shield, and a potion"
});
button({label, action, icon, callback})
Adds a custom button to the form.
- Parameters:
label
(String): The label for the button.action
(String, optional): The action identifier for the button. Defaults to a random ID.icon
(String, optional): The
Basic Example
const formBuilder = new Portal.FormBuilder();
formBuilder.title("Simple RPG Character Form")
.text({name: "character-name", label: "Character Name", hint: "Enter the character's name", value: ""})
.select({
name: "character-class", label: "Class", hint: "Select the character's class", value: "", options: {
"warrior": "Warrior",
"mage": "Mage",
"rogue": "Rogue",
"cleric": "Cleric"
}
})
.number({name: "character-age", label: "Age", hint: "Enter the character's age", value: 18, min: 0, max: 100, step: 1})
const data = await formBuilder.render();
console.log(data);
Button Example
const formBuilder = new Portal.FormBuilder();
formBuilder.title("Button Only Form")
.info("Press a button")
.button({label: "Start", icon: "fas fa-play", callback: function (e) { console.log("Start button clicked", this, e); }})
.button({label: "Pause", icon: "fas fa-pause", callback: function (e) { console.log("Pause button clicked", this, e); }})
.button({label: "Stop", icon: "fas fa-stop", callback: function (e) { console.log("Stop button clicked", this, e); }})
.button({label: "Reset", icon: "fas fa-undo", callback: function (e) { console.log("Reset button clicked", this, e); }})
// Disable the submit button
.submitButton({enabled: false})
.render()
Closing the Form when a custom button is clicked
const formBuilder = new Portal.FormBuilder();
formBuilder.title("Button Only Form")
.info("Press a button")
.button({label: "Close", icon: "fas fa-times", callback: function (e) {
//Do something when the button is clicked
const formData = this.getFormData(); // Retrieve the form data from a custom button
console.log(formData);
this.close();
}})
// Disable the submit button
.submitButton({enabled: false})
.render()
Permanently Store the Form Data
This example shows how to store your form data on the currently selected actor.
const formBuilder = new Portal.FormBuilder();
formBuilder.title("Form Title")
.object(token.actor.flags.core)
.text({name: "text-field", label: "Text Field", hint: "Enter some text", value: ""})
.number({name: "number-field", label: "Number Field", hint: "Enter a number", value: 0, min: 0, max: 100, step: 1})
.checkbox({name: "checkbox-field", label: "Checkbox Field", hint: "Check a checkbox", value: false})
.color({name: "color-field", label: "Color Field", hint: "Select a color", value: "#000000"})
const data = await formBuilder.render();
if (data) token.actor.update({"flags.core": data})
The next time you run this macro, the form will have stored the data you entered the first time.
GM-Notes like module replacement with a macro
//Open a persisted secret notes window for the currently selected actor
const data = await new Portal.FormBuilder().title("Simple RPG Character Form")
.object(token.actor.flags.core)
.editor({name: "gm-notes", label: "Secret Notes", hint: "Enter your secret notes", value: ""})
.render();
if (data) token.actor.update({ "flags.core": data });
Complex Example
const formBuilder = new Portal.FormBuilder();
formBuilder.title("RPG Character Creation Form")
// Character Info Tab
.tab({id: "character-info", icon: "fa-solid fa-user", label: "Character Info"})
.text({name: "character-name", label: "Character Name", hint: "Enter the character's name", value: ""})
.select({
name: "character-race", label: "Race", hint: "Select the character's race", value: "", options: {
"human": "Human",
"elf": "Elf",
"dwarf": "Dwarf",
"orc": "Orc"
}
})
.select({
name: "character-class", label: "Class", hint: "Select the character's class", value: "", options: {
"warrior": "Warrior",
"mage": "Mage",
"rogue": "Rogue",
"cleric": "Cleric"
}
})
.number({name: "character-age", label: "Age", hint: "Enter the character's age", value: 18, min: 0, max: 100, step: 1})
.color({name: "character-color", label: "Favorite Color", hint: "Select the character's favorite color", value: "#000000"})
.file({name: "character-portrait", label: "Portrait", hint: "Upload the character's portrait", value: ""})
// Abilities Tab
.tab({id: "abilities", icon: "fa-solid fa-dumbbell", label: "Abilities"})
.fieldset({legend: "Physical Abilities"})
.number({name: "strength", label: "Strength", hint: "Enter the strength value", value: 10, min: 0, max: 20, step: 1})
.number({name: "dexterity", label: "Dexterity", hint: "Enter the dexterity value", value: 10, min: 0, max: 20, step: 1})
.fieldset()
.fieldset({legend: "Mental Abilities"})
.number({name: "intelligence", label: "Intelligence", hint: "Enter the intelligence value", value: 10, min: 0, max: 20, step: 1})
.number({name: "wisdom", label: "Wisdom", hint: "Enter the wisdom value", value: 10, min: 0, max: 20, step: 1})
.fieldset()
.fieldset({legend: "Other Abilities"})
.number({name: "charisma", label: "Charisma", hint: "Enter the charisma value", value: 10, min: 0, max: 20, step: 1})
.number({name: "luck", label: "Luck", hint: "Enter the luck value", value: 10, min: 0, max: 20, step: 1})
.fieldset()
// Equipment Tab
.tab({id: "equipment", icon: "fa-solid fa-sword", label: "Equipment"})
.multiSelect({
name: "weapons", label: "Weapons", hint: "Select the character's weapons", value: [], options: {
"sword": "Sword",
"bow": "Bow",
"dagger": "Dagger",
"staff": "Staff"
}
})
.multiSelect({
name: "armor", label: "Armor", hint: "Select the character's armor", value: [], options: {
"leather": "Leather Armor",
"chainmail": "Chainmail Armor",
"plate": "Plate Armor",
"robe": "Robe"
}
})
.multiSelect({
name: "potions", label: "Potions", hint: "Select the character's potions", value: [], options: {
"healing": "Healing Potion",
"mana": "Mana Potion",
"strength": "Strength Potion",
"speed": "Speed Potion"
}
})
// Randomize Button
.button({label: "Randomize", icon: "fas fa-d6", callback: function (e) { console.log(this, e); }});
const data = await formBuilder.render();
console.log(data);
//Do what you need with the data
```import {createPortal} from 'react-dom';