Portal

Portal

A library module for spawning creatures, teleporting tokens, and picking locations. Check the wiki for the scripting API.

Free
Version: V12
FVTT: V12
Any System
Download
Changelog

    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 to 560 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 to true.
      • 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 to false.
    • 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';