Classes

Components

Class Envelope

The Class Envelope is the infinite bag that contains the Character Box to create new characters for that class.

Properties

Tags

Class Envelope

Lua Script

The Class Envelope should register the class during the onLoad event. Details about the data format can be found at registerClass. If the class also has custom conditions they should be registered here, too (see registerCondition for details about the data structure).

api/GloomApi.ttslua
local ClassApi = require("api.ClassApi")
local ConditionApi = require("api.ConditionApi")

function onLoad()
  local classData = {
       -- ...
  }
  ClassApi.registerClass("Name of the Class", classData)

  -- if the class also has custom conditions, they should be registered here, too
  local conditionInfo = {
      -- ...
  }
  ConditionApi.registerCondition("Name of the condition", conditionInfo)
end

Character Box

The Character Box contains all the components for a new character of that class. Each Character Box should contain:

  • The Figure.

  • A deck named Starting Abilities for abilities unlocked at level 1.

  • A deck named Advanced Abilities for abilities that are unlocked at level up.

  • A Character Sheet.

  • A Player Mat

Properties

Name

Name of the class

Lua Script

This script ensures, that the character box is unpacked when it’s dropped onto a player mat.

require("Component.CharacterBox")

Figure

Name

Full name of the class.

Tags

Required tags will be set automatically through the script.

Lua Script

Add this script to figure’s script and adjust the shown values to your need.

Figures/CharacterMini.ttslua
info = {
    hpColour = "#5080C1",
    hpTextColour = "#B70F0F",
    startingHealth = 10,
}

FrameOffset = 230

require("Figures.CharacterMini")

The value for hpColour is the background color of the HP bar over the figure. Similar hpTextColour is the color of the text appearing on the HP bar. This is optional and defaults to black. startingHealth is the HP value for the character on level 1. The FrameOffset is the position where the HP bar will appear relative to the figure. The correct value can be found by experimenting a bit and see what looks good.

Stances/Resources
Example 1. Figures/CharacterMini.ttslua
info = {
    hpColour = "#5080C1",
    hpTextColour = "#B70F0F",
    startingHealth = 10,
    stances = {
      {
        label = "First Stance",
        color = "Red",
        textColor = "Black",
      },
      {
        label = "Second Stance",
        color = "Blue",
        textColor = "Black",
      },
      {
        label = "Third Stance",
        color = "Green",
        textColor = "Black",
      }
    },
    startingStance = 2,
    resources = {
      {
        name = "Resource 1",
        starting = 0,
        max = 5,
        color = "Red",
        textColor = "Black"
      },
      {
        name = "Resource 2",
        starting = 3,
        max = 5,
        color = "Blue",
        textColor = "Black"
      },
      -- up to 3 resources are supported
    }
}

FrameOffset = 230

require("Figures.CharacterMini")

Xml Ui

Add this script to figure’s UI script. No other values need to be set.

Figures/CharacterMini.xml
<Include src="Figures/CharacterMini.xml" />

Player Mat

Character Mat

Character Sheet

Name

Character Sheet

Use the Character Sheet Creator to generate the required script for the character sheet.

Ability Cards

Name

Name of the ability followed by its initiative value

Description

Full name of the class.

The initiative value of a card has to be a two-digit number enclosed by parentheses (e.g. Perverse Edge (08)). When an ability has multiple initiative values (like the Blinkblade from Frosthaven), multiple parentheses can be used. The initiative tracker then shows all of them and users can remove them if needed.

Within the class box the ability cards then need to be placed into a deck. The deck needs to be named Starting Abilities for abilities that are unlocked by the class at level 1. All those cards will be put the players' hand when a new character is created. All other ability cards need to be in a deck named Advanced Abilities. This ensures that the Campaign Manager can correctly find them.

Lua Script

Abilities only need a script, when it’s an ability that can spawn Summons. The script adds a button to the card that can be clicked and creates the Summon figure. The Summon also needs to be registered accordingly.

Component/SummonCard.ttslua
local SummonCard = require("Component.SummonCard")

SummonCard.forSummon("Rat Swarm", SummonCard.Position.GHTop, "http://imageurl.com/example1")

Change the name of the first parameter to the name of the Summon this card will spawn. The second parameter is the position of the button that will appear. SummonCard.Position contains the default values for Gloomhaven and Frosthaven abilities and items you can use: GHTop, GHBottom, FHTop, FHBottom and Item. The third parameter is a thumbnail image for the summon to be used in the Context Menu.

Attack Modifiers

Trackers

Summons

Name

Unique name across all Summons.

Tags

Required tags will be set automatically through the script.

Summons need to be inside a Custom Content Box to be registered correctly.

Lua Script

Add this script to a Summons' figure script and adjust the shown values to your need.

Figures/Summon.ttslua
stats = {
   health = 2,
   move = 3,
   attack = 0,
   range = 0,
   attributes = {}
}

info = {
  hpColour = "#AD735C"
}

FrameOffset = 230

require("Figures.Summon")

The stats table describes the base stats for the Summon. The values should be self-explanatory. The attributes table describes the default attributes the summon has (like flying, shield or infusing an element). The format is the same as for Enemy Stats.

The info table and the FrameOffset use the same format as the one for the class Figure.

Xml Ui

Add this script to figure’s UI script. No other values need to be set.

Figures/Summon.xml
<Include src="Figures/Summon.xml" />

Extra Components

Within the class envelope LUA, you can define other objects contained in the tuck box to automatically unpack with the class. This function takes two parameters: * The NAME of the object * The TARGET area within the player zone where the object should be placed * Valid values for TARGET are "Hand", "HandTwo", "CharacterMat", and "CharacterSheet" * You can specify a specific position relative to their target

To easily get the position in the local coordinate system you can place the object where you want it and then paste that into the chat window:

How to find a relative position value
--Replace "targetObjectGUID" with the GUID where you want to place your object (e.g. the Player Mat) and "objectGUID" with the GUID of the extra object
/execute print(logString(getObjectFromGUID("targetObjectGUID").positionToLocal(getObjectFromGUID("objectGUID").getPosition())))

An example looks as follows:

Extra class content
extra = {
  {
    name = "Special Rules",
    target = "CharacterSheet",
  },
  {
    name = "Special Overlay Tokens",
    target = { PlayerMat = { 1, 0, 1 }}
  },
},

Registration

Registration of the class is done via the ClassApi.registerClass function. This function takes two parameters: * The name of the class * The information about the class, like abilities, perks, etc.

An example looks as follows:

Brute class definition
local ClassApi = require("api.ClassApi")

function onLoad()
  ClassApi.registerClass("Brute", {
    -- The GUID of the Class envelope object.
    -- Since the registration script is on the envelope itselt, it can be referenced here
    boxGuid = self.getGUID(),
    -- Number of HP per level
    -- Default values are available in ClassApi.HpProgression with Low, Medium and High
    hp = ClassApi.HpProgression.High,
    -- Definition for the tracker image
    tracker = {
      -- Link to the Asset for the tracker image
      image = "http://cloud-3.steamusercontent.com/ugc/83722391140264566/DC437F88C225F04C6CCE924EA4C3BB31FCD3F3A9/",
      -- any other property that is available to conditions can be used, too, e.g. max to make the tracker stackable
    },
    -- List of perk information
    perks = {
      [1] = { remove = { "(-1)", "(-1)" } },
      [2] = { add = { "(+1)" }, remove = { "(-1)" } },
      -- Perks 3 .. 14 would be here too
      [14] = { add = { "(+1)" }, ignore = ClassApi.PerkType.IgnoreItem },
      [15] = { ignore = ClassApi.PerkType.IgnoreScenario },
      [16] = { unlock = "Perk 16 Reminder Cardname" },
      -- up to 18 perks are supported (for Frosthaven support)
    },
    abilities = {
      ["Eye for an Eye"] = {
        level = 1,
        enhancements = {
          [1] = { position = { -0.46, -0.92 }, multi = false, side = "T", main = true, type = ClassApi.AbilityType.Retaliate },
          [2] = { position = { -0.35, 0.53 }, multi = false, side = "B", main = true, type = ClassApi.AbilityType.Heal },
          [3] = { position = { -0.50, 0.55 }, multi = false, side = "B", main = true, type = ClassApi.AbilityType.Heal },
        }
      },
      ["Brute Force"] = {
        level = 3,
        enhancements = {
          [1] = { position = { -0.06, -0.75 }, multi = true, side = "T", main = true, type = ClassApi.AbilityType.Attack },
          [2] = { position = { -0.25, -0.78 }, multi = true, side = "T", main = true, type = ClassApi.AbilityType.Hex, baseHex = 3, otherHex = { 3 } },
          [3] = { position = { -0.26, -0.40 }, multi = true, side = "T", main = true, type = ClassApi.AbilityType.Hex, baseHex = 3, otherHex = { 2 } },
          [4] = { position = { -0.41, 0.67 }, multi = false, side = "B", main = true, type = ClassApi.AbilityType.Shield },
        }
      },
    },
  })
end