Files
Foundry-VTT-Docker/resources/app/client/config.js

2173 lines
65 KiB
JavaScript
Raw Normal View History

2025-01-04 00:34:03 +01:00
/**
* Runtime configuration settings for Foundry VTT which exposes a large number of variables which determine how
* aspects of the software behaves.
*
* Unlike the CONST analog which is frozen and immutable, the CONFIG object may be updated during the course of a
* session or modified by system and module developers to adjust how the application behaves.
*
* @type {object}
*/
const CONFIG = globalThis.CONFIG = {
/**
* Configure debugging flags to display additional information
*/
debug: {
applications: false,
audio: false,
combat: false,
dice: false,
documents: false,
fog: {
extractor: false,
manager: false
},
hooks: false,
av: false,
avclient: false,
mouseInteraction: false,
time: false,
keybindings: false,
polygons: false,
gamepad: false,
canvas: {
primary: {
bounds: false
}
},
rollParsing: false
},
/**
* Configure the verbosity of compatibility warnings generated throughout the software.
* The compatibility mode defines the logging level of any displayed warnings.
* The includePatterns and excludePatterns arrays provide a set of regular expressions which can either only
* include or specifically exclude certain file paths or warning messages.
* Exclusion rules take precedence over inclusion rules.
*
* @see {@link CONST.COMPATIBILITY_MODES}
* @type {{mode: number, includePatterns: RegExp[], excludePatterns: RegExp[]}}
*
* @example Include Specific Errors
* ```js
* const includeRgx = new RegExp("/systems/dnd5e/module/documents/active-effect.mjs");
* CONFIG.compatibility.includePatterns.push(includeRgx);
* ```
*
* @example Exclude Specific Errors
* ```js
* const excludeRgx = new RegExp("/systems/dnd5e/");
* CONFIG.compatibility.excludePatterns.push(excludeRgx);
* ```
*
* @example Both Include and Exclude
* ```js
* const includeRgx = new RegExp("/systems/dnd5e/module/actor/");
* const excludeRgx = new RegExp("/systems/dnd5e/module/actor/sheets/base.js");
* CONFIG.compatibility.includePatterns.push(includeRgx);
* CONFIG.compatibility.excludePatterns.push(excludeRgx);
* ```
*
* @example Targeting more than filenames
* ```js
* const includeRgx = new RegExp("applyActiveEffects");
* CONFIG.compatibility.includePatterns.push(includeRgx);
* ```
*/
compatibility: {
mode: CONST.COMPATIBILITY_MODES.WARNING,
includePatterns: [],
excludePatterns: []
},
compendium: {
/**
* Configure a table of compendium UUID redirects. Must be configured before the game *ready* hook is fired.
* @type {Record<string, string>}
*
* @example Re-map individual UUIDs
* ```js
* CONFIG.compendium.uuidRedirects["Compendium.system.heroes.Actor.Tf0JDPzHOrIxz6BH"] = "Compendium.system.villains.Actor.DKYLeIliXXzlAZ2G";
* ```
*
* @example Redirect UUIDs from one compendium to another.
* ```js
* CONFIG.compendium.uuidRedirects["Compendium.system.heroes"] = "Compendium.system.villains";
* ```
*/
uuidRedirects: {},
},
/**
* Configure the DatabaseBackend used to perform Document operations
* @type {foundry.data.ClientDatabaseBackend}
*/
DatabaseBackend: new foundry.data.ClientDatabaseBackend(),
/**
* Configuration for the Actor document
*/
Actor: {
documentClass: Actor,
collection: Actors,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/actor-banner.webp",
sidebarIcon: "fas fa-user",
dataModels: {},
typeLabels: {},
typeIcons: {},
trackableAttributes: {}
},
/**
* Configuration for the Adventure document.
* Currently for internal use only.
* @private
*/
Adventure: {
documentClass: Adventure,
exporterClass: AdventureExporter,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/adventure-banner.webp",
sidebarIcon: "fa-solid fa-treasure-chest"
},
/**
* Configuration for the Cards primary Document type
*/
Cards: {
collection: CardStacks,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/cards-banner.webp",
documentClass: Cards,
sidebarIcon: "fa-solid fa-cards",
dataModels: {},
presets: {
pokerDark: {
type: "deck",
label: "CARDS.DeckPresetPokerDark",
src: "cards/poker-deck-dark.json"
},
pokerLight: {
type: "deck",
label: "CARDS.DeckPresetPokerLight",
src: "cards/poker-deck-light.json"
}
},
typeLabels: {},
typeIcons: {
deck: "fas fa-cards",
hand: "fa-duotone fa-cards",
pile: "fa-duotone fa-layer-group"
}
},
/**
* Configuration for the ChatMessage document
*/
ChatMessage: {
documentClass: ChatMessage,
collection: Messages,
template: "templates/sidebar/chat-message.html",
sidebarIcon: "fas fa-comments",
dataModels: {},
typeLabels: {},
typeIcons: {},
batchSize: 100
},
/**
* Configuration for the Combat document
*/
Combat: {
documentClass: Combat,
collection: CombatEncounters,
sidebarIcon: "fas fa-swords",
dataModels: {},
typeLabels: {},
typeIcons: {},
initiative: {
formula: null,
decimals: 2
},
sounds: {
epic: {
label: "COMBAT.Sounds.Epic",
startEncounter: ["sounds/combat/epic-start-3hit.ogg", "sounds/combat/epic-start-horn.ogg"],
nextUp: ["sounds/combat/epic-next-horn.ogg"],
yourTurn: ["sounds/combat/epic-turn-1hit.ogg", "sounds/combat/epic-turn-2hit.ogg"]
},
mc: {
label: "COMBAT.Sounds.MC",
startEncounter: ["sounds/combat/mc-start-battle.ogg", "sounds/combat/mc-start-begin.ogg", "sounds/combat/mc-start-fight.ogg", "sounds/combat/mc-start-fight2.ogg"],
nextUp: ["sounds/combat/mc-next-itwillbe.ogg", "sounds/combat/mc-next-makeready.ogg", "sounds/combat/mc-next-youare.ogg"],
yourTurn: ["sounds/combat/mc-turn-itisyour.ogg", "sounds/combat/mc-turn-itsyour.ogg"]
}
}
},
/**
* @typedef {object} DiceFulfillmentConfiguration
* @property {Record<string, DiceFulfillmentDenomination>} dice The die denominations available for configuration.
* @property {Record<string, DiceFulfillmentMethod>} methods The methods available for fulfillment.
* @property {string} defaultMethod Designate one of the methods to be used by default
* for dice fulfillment, if the user hasn't specified
* otherwise. Leave this blank to use the configured
* randomUniform to generate die rolls.
*/
/**
* @typedef {object} DiceFulfillmentDenomination
* @property {string} label The human-readable label for the die.
* @property {string} icon An icon to display on the configuration sheet.
*/
/**
* @typedef {object} DiceFulfillmentMethod
* @property {string} label The human-readable label for the fulfillment method.
* @property {string} [icon] An icon to represent the fulfillment method.
* @property {boolean} [interactive=false] Whether this method requires input from the user or if it is
* fulfilled entirely programmatically.
* @property {DiceFulfillmentHandler} [handler] A function to invoke to programmatically fulfil a given term for non-
* interactive fulfillment methods.
* @property {typeof RollResolver} [resolver] A custom RollResolver implementation. If the only interactive methods
* the user has configured are this method and manual, this resolver
* will be used to resolve interactive rolls, instead of the default
* resolver. This resolver must therefore be capable of handling manual
* rolls.
*/
/**
* Only used for non-interactive fulfillment methods. If a die configured to use this fulfillment method is rolled,
* this handler is called and awaited in order to produce the die roll result.
* @callback DiceFulfillmentHandler
* @param {DiceTerm} term The term being fulfilled.
* @param {object} [options] Additional options to configure fulfillment.
* @returns {Promise<number|void>} The fulfilled value, or undefined if it could not be fulfilled.
*/
/**
* @callback RollFunction
* @param {...any} args
* @returns {Promise<number>|number}
*/
/**
* Configuration for dice rolling behaviors in the Foundry Virtual Tabletop client.
* @type {object}
*/
Dice: {
/**
* The Dice types which are supported.
* @type {Array<typeof DiceTerm>}
*/
types: [foundry.dice.terms.Die, foundry.dice.terms.FateDie],
rollModes: Object.entries(CONST.DICE_ROLL_MODES).reduce((obj, e) => {
let [k, v] = e;
obj[v] = `CHAT.Roll${k.titleCase()}`;
return obj;
}, {}),
/**
* Configured Roll class definitions
* @type {Array<typeof Roll>}
*/
rolls: [Roll],
/**
* Configured DiceTerm class definitions
* @type {Record<string, typeof RollTerm>}
*/
termTypes: {
DiceTerm: foundry.dice.terms.DiceTerm,
FunctionTerm: foundry.dice.terms.FunctionTerm,
NumericTerm: foundry.dice.terms.NumericTerm,
OperatorTerm: foundry.dice.terms.OperatorTerm,
ParentheticalTerm: foundry.dice.terms.ParentheticalTerm,
PoolTerm: foundry.dice.terms.PoolTerm,
StringTerm: foundry.dice.terms.StringTerm
},
/**
* Configured roll terms and the classes they map to.
* @enum {typeof DiceTerm}
*/
terms: {
c: foundry.dice.terms.Coin,
d: foundry.dice.terms.Die,
f: foundry.dice.terms.FateDie
},
/**
* A function used to provide random uniform values.
* @type {function():number}
*/
randomUniform: foundry.dice.MersenneTwister.random,
/**
* A parser implementation for parsing Roll expressions.
* @type {typeof RollParser}
*/
parser: foundry.dice.RollParser,
/**
* A collection of custom functions that can be included in roll expressions.
* @type {Record<string, RollFunction>}
*/
functions: {},
/**
* Dice roll fulfillment configuration.
* @type {DiceFulfillmentConfiguration}
* @type {{dice: Record<string, DiceFulfillmentDenomination>, methods: Record<string, DiceFulfillmentMethod>}}
*/
fulfillment: {
dice: {
d4: { label: "d4", icon: '<i class="fas fa-dice-d4"></i>' },
d6: { label: "d6", icon: '<i class="fas fa-dice-d6"></i>' },
d8: { label: "d8", icon: '<i class="fas fa-dice-d8"></i>' },
d10: { label: "d10", icon: '<i class="fas fa-dice-d10"></i>' },
d12: { label: "d12", icon: '<i class="fas fa-dice-d12"></i>' },
d20: { label: "d20", icon: '<i class="fas fa-dice-d20"></i>' },
d100: { label: "d100", icon: '<i class="fas fa-percent"></i>' }
},
methods: {
mersenne: {
label: "DICE.FULFILLMENT.Mersenne",
interactive: false,
handler: term => term.mapRandomFace(foundry.dice.MersenneTwister.random())
},
manual: {
label: "DICE.FULFILLMENT.Manual",
icon: '<i class="fas fa-keyboard"></i>',
interactive: true
}
},
defaultMethod: ""
}
},
/**
* Configuration for the FogExploration document
*/
FogExploration: {
documentClass: FogExploration,
collection: FogExplorations
},
/**
* Configuration for the Folder document
*/
Folder: {
documentClass: Folder,
collection: Folders,
sidebarIcon: "fas fa-folder"
},
/**
* Configuration for Item document
*/
Item: {
documentClass: Item,
collection: Items,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/item-banner.webp",
sidebarIcon: "fas fa-suitcase",
dataModels: {},
typeLabels: {},
typeIcons: {}
},
/**
* Configuration for the JournalEntry document
*/
JournalEntry: {
documentClass: JournalEntry,
collection: Journal,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/journalentry-banner.webp",
noteIcons: {
Anchor: "icons/svg/anchor.svg",
Barrel: "icons/svg/barrel.svg",
Book: "icons/svg/book.svg",
Bridge: "icons/svg/bridge.svg",
Cave: "icons/svg/cave.svg",
Castle: "icons/svg/castle.svg",
Chest: "icons/svg/chest.svg",
City: "icons/svg/city.svg",
Coins: "icons/svg/coins.svg",
Fire: "icons/svg/fire.svg",
"Hanging Sign": "icons/svg/hanging-sign.svg",
House: "icons/svg/house.svg",
Mountain: "icons/svg/mountain.svg",
"Oak Tree": "icons/svg/oak.svg",
Obelisk: "icons/svg/obelisk.svg",
Pawprint: "icons/svg/pawprint.svg",
Ruins: "icons/svg/ruins.svg",
Skull: "icons/svg/skull.svg",
Statue: "icons/svg/statue.svg",
Sword: "icons/svg/sword.svg",
Tankard: "icons/svg/tankard.svg",
Temple: "icons/svg/temple.svg",
Tower: "icons/svg/tower.svg",
Trap: "icons/svg/trap.svg",
Village: "icons/svg/village.svg",
Waterfall: "icons/svg/waterfall.svg",
Windmill: "icons/svg/windmill.svg"
},
sidebarIcon: "fas fa-book-open"
},
/**
* Configuration for the Macro document
*/
Macro: {
documentClass: Macro,
collection: Macros,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/macro-banner.webp",
sidebarIcon: "fas fa-code"
},
/**
* Configuration for the Playlist document
*/
Playlist: {
documentClass: Playlist,
collection: Playlists,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/playlist-banner.webp",
sidebarIcon: "fas fa-music",
autoPreloadSeconds: 20
},
/**
* Configuration for RollTable random draws
*/
RollTable: {
documentClass: RollTable,
collection: RollTables,
compendiumIndexFields: ["formula"],
compendiumBanner: "ui/banners/rolltable-banner.webp",
sidebarIcon: "fas fa-th-list",
resultIcon: "icons/svg/d20-black.svg",
resultTemplate: "templates/dice/table-result.html"
},
/**
* Configuration for the Scene document
*/
Scene: {
documentClass: Scene,
collection: Scenes,
compendiumIndexFields: [],
compendiumBanner: "ui/banners/scene-banner.webp",
sidebarIcon: "fas fa-map"
},
Setting: {
documentClass: Setting,
collection: WorldSettings
},
/**
* Configuration for the User document
*/
User: {
documentClass: User,
collection: Users
},
/* -------------------------------------------- */
/* Canvas */
/* -------------------------------------------- */
/**
* Configuration settings for the Canvas and its contained layers and objects
* @type {object}
*/
Canvas: {
blurStrength: 8,
blurQuality: 4,
darknessColor: 0x303030,
daylightColor: 0xEEEEEE,
brightestColor: 0xFFFFFF,
chatBubblesClass: ChatBubbles,
darknessLightPenalty: 0.25,
dispositionColors: {
HOSTILE: 0xE72124,
NEUTRAL: 0xF1D836,
FRIENDLY: 0x43DFDF,
INACTIVE: 0x555555,
PARTY: 0x33BC4E,
CONTROLLED: 0xFF9829,
SECRET: 0xA612D4
},
/**
* The class used to render door control icons.
* @type {typeof DoorControl}
*/
doorControlClass: DoorControl,
exploredColor: 0x000000,
unexploredColor: 0x000000,
darknessToDaylightAnimationMS: 10000,
daylightToDarknessAnimationMS: 10000,
darknessSourceClass: foundry.canvas.sources.PointDarknessSource,
lightSourceClass: foundry.canvas.sources.PointLightSource,
globalLightSourceClass: foundry.canvas.sources.GlobalLightSource,
visionSourceClass: foundry.canvas.sources.PointVisionSource,
soundSourceClass: foundry.canvas.sources.PointSoundSource,
groups: {
hidden: {
groupClass: HiddenCanvasGroup,
parent: "stage"
},
rendered: {
groupClass: RenderedCanvasGroup,
parent: "stage"
},
environment: {
groupClass: EnvironmentCanvasGroup,
parent: "rendered"
},
primary: {
groupClass: PrimaryCanvasGroup,
parent: "environment"
},
effects: {
groupClass: EffectsCanvasGroup,
parent: "environment"
},
visibility: {
groupClass: CanvasVisibility,
parent: "rendered"
},
interface: {
groupClass: InterfaceCanvasGroup,
parent: "rendered",
zIndexDrawings: 500,
zIndexScrollingText: 1100
},
overlay: {
groupClass: OverlayCanvasGroup,
parent: "stage"
}
},
layers: {
weather: {
layerClass: WeatherEffects,
group: "primary"
},
grid: {
layerClass: GridLayer,
group: "interface"
},
regions: {
layerClass: RegionLayer,
group: "interface"
},
drawings: {
layerClass: DrawingsLayer,
group: "interface"
},
templates: {
layerClass: TemplateLayer,
group: "interface"
},
tiles: {
layerClass: TilesLayer,
group: "interface"
},
walls: {
layerClass: WallsLayer,
group: "interface"
},
tokens: {
layerClass: TokenLayer,
group: "interface"
},
sounds: {
layerClass: SoundsLayer,
group: "interface"
},
lighting: {
layerClass: LightingLayer,
group: "interface"
},
notes: {
layerClass: NotesLayer,
group: "interface"
},
controls: {
layerClass: ControlsLayer,
group: "interface"
}
},
lightLevels: {
dark: 0,
halfdark: 0.5,
dim: 0.25,
bright: 1.0
},
fogManager: FogManager,
/**
* @enum {typeof PointSourcePolygon}
*/
polygonBackends: {
sight: ClockwiseSweepPolygon,
light: ClockwiseSweepPolygon,
sound: ClockwiseSweepPolygon,
move: ClockwiseSweepPolygon
},
darknessSourcePaddingMultiplier: 0.5,
visibilityFilter: VisibilityFilter,
visualEffectsMaskingFilter: VisualEffectsMaskingFilter,
rulerClass: Ruler,
dragSpeedModifier: 0.8,
maxZoom: 3.0,
objectBorderThickness: 4,
gridStyles: {
solidLines: {
label: "GRID.STYLES.SolidLines",
shaderClass: GridShader,
shaderOptions: {
style: 0
}
},
dashedLines: {
label: "GRID.STYLES.DashedLines",
shaderClass: GridShader,
shaderOptions: {
style: 1
}
},
dottedLines: {
label: "GRID.STYLES.DottedLines",
shaderClass: GridShader,
shaderOptions: {
style: 2
}
},
squarePoints: {
label: "GRID.STYLES.SquarePoints",
shaderClass: GridShader,
shaderOptions: {
style: 3
}
},
diamondPoints: {
label: "GRID.STYLES.DiamondPoints",
shaderClass: GridShader,
shaderOptions: {
style: 4
}
},
roundPoints: {
label: "GRID.STYLES.RoundPoints",
shaderClass: GridShader,
shaderOptions: {
style: 5
}
}
},
/**
* A light source animation configuration object.
* @typedef {Record<string, {label: string, animation: Function, backgroundShader: AdaptiveBackgroundShader,
* illuminationShader: AdaptiveIlluminationShader,
* colorationShader: AdaptiveColorationShader}>} LightSourceAnimationConfig
*/
/** @type {LightSourceAnimationConfig} */
lightAnimations: {
flame: {
label: "LIGHT.AnimationFlame",
animation: foundry.canvas.sources.PointLightSource.prototype.animateFlickering,
illuminationShader: FlameIlluminationShader,
colorationShader: FlameColorationShader
},
torch: {
label: "LIGHT.AnimationTorch",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTorch,
illuminationShader: TorchIlluminationShader,
colorationShader: TorchColorationShader
},
revolving: {
label: "LIGHT.AnimationRevolving",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: RevolvingColorationShader
},
siren: {
label: "LIGHT.AnimationSiren",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTorch,
illuminationShader: SirenIlluminationShader,
colorationShader: SirenColorationShader
},
pulse: {
label: "LIGHT.AnimationPulse",
animation: foundry.canvas.sources.PointLightSource.prototype.animatePulse,
illuminationShader: PulseIlluminationShader,
colorationShader: PulseColorationShader
},
chroma: {
label: "LIGHT.AnimationChroma",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: ChromaColorationShader
},
wave: {
label: "LIGHT.AnimationWave",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
illuminationShader: WaveIlluminationShader,
colorationShader: WaveColorationShader
},
fog: {
label: "LIGHT.AnimationFog",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: FogColorationShader
},
sunburst: {
label: "LIGHT.AnimationSunburst",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
illuminationShader: SunburstIlluminationShader,
colorationShader: SunburstColorationShader
},
dome: {
label: "LIGHT.AnimationLightDome",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: LightDomeColorationShader
},
emanation: {
label: "LIGHT.AnimationEmanation",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: EmanationColorationShader
},
hexa: {
label: "LIGHT.AnimationHexaDome",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: HexaDomeColorationShader
},
ghost: {
label: "LIGHT.AnimationGhostLight",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
illuminationShader: GhostLightIlluminationShader,
colorationShader: GhostLightColorationShader
},
energy: {
label: "LIGHT.AnimationEnergyField",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: EnergyFieldColorationShader
},
vortex: {
label: "LIGHT.AnimationVortex",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
illuminationShader: VortexIlluminationShader,
colorationShader: VortexColorationShader
},
witchwave: {
label: "LIGHT.AnimationBewitchingWave",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
illuminationShader: BewitchingWaveIlluminationShader,
colorationShader: BewitchingWaveColorationShader
},
rainbowswirl: {
label: "LIGHT.AnimationSwirlingRainbow",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: SwirlingRainbowColorationShader
},
radialrainbow: {
label: "LIGHT.AnimationRadialRainbow",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: RadialRainbowColorationShader
},
fairy: {
label: "LIGHT.AnimationFairyLight",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
illuminationShader: FairyLightIlluminationShader,
colorationShader: FairyLightColorationShader
},
grid: {
label: "LIGHT.AnimationForceGrid",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: ForceGridColorationShader
},
starlight: {
label: "LIGHT.AnimationStarLight",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
colorationShader: StarLightColorationShader
},
smokepatch: {
label: "LIGHT.AnimationSmokePatch",
animation: foundry.canvas.sources.PointLightSource.prototype.animateTime,
illuminationShader: SmokePatchIlluminationShader,
colorationShader: SmokePatchColorationShader
}
},
/**
* A darkness source animation configuration object.
* @typedef {Record<string, {label: string, animation: Function,
* darknessShader: AdaptiveDarknessShader}>} DarknessSourceAnimationConfig
*/
/** @type {DarknessSourceAnimationConfig} */
darknessAnimations: {
magicalGloom: {
label: "LIGHT.AnimationMagicalGloom",
animation: foundry.canvas.sources.PointDarknessSource.prototype.animateTime,
darknessShader: MagicalGloomDarknessShader
},
roiling: {
label: "LIGHT.AnimationRoilingMass",
animation: foundry.canvas.sources.PointDarknessSource.prototype.animateTime,
darknessShader: RoilingDarknessShader
},
hole: {
label: "LIGHT.AnimationBlackHole",
animation: foundry.canvas.sources.PointDarknessSource.prototype.animateTime,
darknessShader: BlackHoleDarknessShader
}
},
/**
* A registry of Scenes which are managed by a specific SceneManager class.
* @type {Record<string, typeof foundry.canvas.SceneManager>}
*/
managedScenes: {},
pings: {
types: {
PULSE: "pulse",
ALERT: "alert",
PULL: "chevron",
ARROW: "arrow"
},
styles: {
alert: {
class: AlertPing,
color: "#ff0000",
size: 1.5,
duration: 900
},
arrow: {
class: ArrowPing,
size: 1,
duration: 900
},
chevron: {
class: ChevronPing,
size: 1,
duration: 2000
},
pulse: {
class: PulsePing,
size: 1.5,
duration: 900
}
},
pullSpeed: 700
},
targeting: {
size: .15
},
/**
* The hover-fading configuration.
* @type {object}
*/
hoverFade: {
/**
* The delay in milliseconds before the (un)faded animation starts on (un)hover.
* @type {number}
*/
delay: 250,
/**
* The duration in milliseconds of the (un)fade animation on (un)hover.
* @type {number}
*/
duration: 750
},
/* -------------------------------------------- */
/* Transcoders */
/* -------------------------------------------- */
/**
* Allow specific transcoders for assets
* @type {Record<string, boolean>}
*/
transcoders: {
basis: false // set to true to activate basis support
},
/* -------------------------------------------- */
/**
* The set of VisionMode definitions which are available to be used for Token vision.
* @type {Record<string, VisionMode>}
*/
visionModes: {
// Default (Basic) Vision
basic: new VisionMode({
id: "basic",
label: "VISION.ModeBasicVision",
vision: {
defaults: { attenuation: 0, contrast: 0, saturation: 0, brightness: 0 },
preferred: true // Takes priority over other vision modes
}
}),
// Darkvision
darkvision: new VisionMode({
id: "darkvision",
label: "VISION.ModeDarkvision",
canvas: {
shader: ColorAdjustmentsSamplerShader,
uniforms: { contrast: 0, saturation: -1.0, brightness: 0 }
},
lighting: {
levels: {
[VisionMode.LIGHTING_LEVELS.DIM]: VisionMode.LIGHTING_LEVELS.BRIGHT
},
background: { visibility: VisionMode.LIGHTING_VISIBILITY.REQUIRED }
},
vision: {
darkness: { adaptive: false },
defaults: { attenuation: 0, contrast: 0, saturation: -1.0, brightness: 0 }
}
}),
// Darkvision
monochromatic: new VisionMode({
id: "monochromatic",
label: "VISION.ModeMonochromatic",
canvas: {
shader: ColorAdjustmentsSamplerShader,
uniforms: { contrast: 0, saturation: -1.0, brightness: 0 }
},
lighting: {
background: {
postProcessingModes: ["SATURATION"],
uniforms: { saturation: -1.0, tint: [1, 1, 1] }
},
illumination: {
postProcessingModes: ["SATURATION"],
uniforms: { saturation: -1.0, tint: [1, 1, 1] }
},
coloration: {
postProcessingModes: ["SATURATION"],
uniforms: { saturation: -1.0, tint: [1, 1, 1] }
}
},
vision: {
darkness: { adaptive: false },
defaults: { attenuation: 0, contrast: 0, saturation: -1, brightness: 0 }
}
}),
// Blindness
blindness: new VisionMode({
id: "blindness",
label: "VISION.ModeBlindness",
tokenConfig: false,
canvas: {
shader: ColorAdjustmentsSamplerShader,
uniforms: { contrast: -0.75, saturation: -1, exposure: -0.3 }
},
lighting: {
background: { visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED },
illumination: { visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED },
coloration: { visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED }
},
vision: {
darkness: { adaptive: false },
defaults: { color: null, attenuation: 0, contrast: -0.5, saturation: -1, brightness: -1 }
}
}),
// Tremorsense
tremorsense: new VisionMode({
id: "tremorsense",
label: "VISION.ModeTremorsense",
canvas: {
shader: ColorAdjustmentsSamplerShader,
uniforms: { contrast: 0, saturation: -0.8, exposure: -0.65 }
},
lighting: {
background: { visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED },
illumination: { visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED },
coloration: { visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED },
darkness: { visibility: VisionMode.LIGHTING_VISIBILITY.DISABLED }
},
vision: {
darkness: { adaptive: false },
defaults: { attenuation: 0, contrast: 0.2, saturation: -0.3, brightness: 1 },
background: { shader: WaveBackgroundVisionShader },
coloration: { shader: WaveColorationVisionShader }
}
}, {animated: true}),
// Light Amplification
lightAmplification: new VisionMode({
id: "lightAmplification",
label: "VISION.ModeLightAmplification",
canvas: {
shader: AmplificationSamplerShader,
uniforms: { saturation: -0.5, tint: [0.38, 0.8, 0.38] }
},
lighting: {
background: {
visibility: VisionMode.LIGHTING_VISIBILITY.REQUIRED,
postProcessingModes: ["SATURATION", "EXPOSURE"],
uniforms: { saturation: -0.5, exposure: 1.5, tint: [0.38, 0.8, 0.38] }
},
illumination: {
postProcessingModes: ["SATURATION"],
uniforms: { saturation: -0.5 }
},
coloration: {
postProcessingModes: ["SATURATION", "EXPOSURE"],
uniforms: { saturation: -0.5, exposure: 1.5, tint: [0.38, 0.8, 0.38] }
},
levels: {
[VisionMode.LIGHTING_LEVELS.DIM]: VisionMode.LIGHTING_LEVELS.BRIGHT,
[VisionMode.LIGHTING_LEVELS.BRIGHT]: VisionMode.LIGHTING_LEVELS.BRIGHTEST
}
},
vision: {
darkness: { adaptive: false },
defaults: { attenuation: 0, contrast: 0, saturation: -0.5, brightness: 1 },
background: { shader: AmplificationBackgroundVisionShader }
}
})
},
/* -------------------------------------------- */
/**
* The set of DetectionMode definitions which are available to be used for visibility detection.
* @type {Record<string, DetectionMode>}
*/
detectionModes: {
lightPerception: new DetectionModeLightPerception({
id: "lightPerception",
label: "DETECTION.LightPerception",
type: DetectionMode.DETECTION_TYPES.SIGHT
}),
basicSight: new DetectionModeBasicSight({
id: "basicSight",
label: "DETECTION.BasicSight",
type: DetectionMode.DETECTION_TYPES.SIGHT
}),
seeInvisibility: new DetectionModeInvisibility({
id: "seeInvisibility",
label: "DETECTION.SeeInvisibility",
type: DetectionMode.DETECTION_TYPES.SIGHT
}),
senseInvisibility: new DetectionModeInvisibility({
id: "senseInvisibility",
label: "DETECTION.SenseInvisibility",
walls: false,
angle: false,
type: DetectionMode.DETECTION_TYPES.OTHER
}),
feelTremor: new DetectionModeTremor({
id: "feelTremor",
label: "DETECTION.FeelTremor",
walls: false,
angle: false,
type: DetectionMode.DETECTION_TYPES.MOVE
}),
seeAll: new DetectionModeAll({
id: "seeAll",
label: "DETECTION.SeeAll",
type: DetectionMode.DETECTION_TYPES.SIGHT
}),
senseAll: new DetectionModeAll({
id: "senseAll",
label: "DETECTION.SenseAll",
walls: false,
angle: false,
type: DetectionMode.DETECTION_TYPES.OTHER
})
}
},
/* -------------------------------------------- */
/**
* Configure the default Token text style so that it may be reused and overridden by modules
* @type {PIXI.TextStyle}
*/
canvasTextStyle: new PIXI.TextStyle({
fontFamily: "Signika",
fontSize: 36,
fill: "#FFFFFF",
stroke: "#111111",
strokeThickness: 1,
dropShadow: true,
dropShadowColor: "#000000",
dropShadowBlur: 2,
dropShadowAngle: 0,
dropShadowDistance: 0,
align: "center",
wordWrap: false,
padding: 1
}),
/**
* Available Weather Effects implementations
* @typedef {Object} WeatherAmbienceConfiguration
* @param {string} id
* @param {string} label
* @param {{enabled: boolean, blendMode: PIXI.BLEND_MODES}} filter
* @param {WeatherEffectConfiguration[]} effects
*
* @typedef {Object} WeatherEffectConfiguration
* @param {string} id
* @param {typeof ParticleEffect|WeatherShaderEffect} effectClass
* @param {PIXI.BLEND_MODES} blendMode
* @param {object} config
*/
weatherEffects: {
leaves: {
id: "leaves",
label: "WEATHER.AutumnLeaves",
effects: [{
id: "leavesParticles",
effectClass: AutumnLeavesWeatherEffect
}]
},
rain: {
id: "rain",
label: "WEATHER.Rain",
filter: {
enabled: false
},
effects: [{
id: "rainShader",
effectClass: WeatherShaderEffect,
shaderClass: RainShader,
blendMode: PIXI.BLEND_MODES.SCREEN,
config: {
opacity: 0.25,
tint: [0.7, 0.9, 1.0],
intensity: 1,
strength: 1,
rotation: 0.2618,
speed: 0.2,
}
}]
},
rainStorm: {
id: "rainStorm",
label: "WEATHER.RainStorm",
filter: {
enabled: false
},
effects: [{
id: "fogShader",
effectClass: WeatherShaderEffect,
shaderClass: FogShader,
blendMode: PIXI.BLEND_MODES.SCREEN,
performanceLevel: 2,
config: {
slope: 1.5,
intensity: 0.050,
speed: -55.0,
scale: 25,
}
},
{
id: "rainShader",
effectClass: WeatherShaderEffect,
shaderClass: RainShader,
blendMode: PIXI.BLEND_MODES.SCREEN,
config: {
opacity: 0.45,
tint: [0.7, 0.9, 1.0],
intensity: 1.5,
strength: 1.5,
rotation: 0.5236,
speed: 0.30,
}
}]
},
fog: {
id: "fog",
label: "WEATHER.Fog",
filter: {
enabled: false
},
effects: [{
id: "fogShader",
effectClass: WeatherShaderEffect,
shaderClass: FogShader,
blendMode: PIXI.BLEND_MODES.SCREEN,
config: {
slope: 0.45,
intensity: 0.4,
speed: 0.4,
}
}]
},
snow: {
id: "snow",
label: "WEATHER.Snow",
filter: {
enabled: false
},
effects: [{
id: "snowShader",
effectClass: WeatherShaderEffect,
shaderClass: SnowShader,
blendMode: PIXI.BLEND_MODES.SCREEN,
config: {
tint: [0.85, 0.95, 1],
direction: 0.5,
speed: 2,
scale: 2.5,
}
}]
},
blizzard: {
id: "blizzard",
label: "WEATHER.Blizzard",
filter: {
enabled: false
},
effects: [{
id: "snowShader",
effectClass: WeatherShaderEffect,
shaderClass: SnowShader,
blendMode: PIXI.BLEND_MODES.SCREEN,
config: {
tint: [0.95, 1, 1],
direction: 0.80,
speed: 8,
scale: 2.5,
}
},
{
id: "fogShader",
effectClass: WeatherShaderEffect,
shaderClass: FogShader,
blendMode: PIXI.BLEND_MODES.SCREEN,
performanceLevel: 2,
config: {
slope: 1.0,
intensity: 0.15,
speed: -4.0,
}
}]
}
},
/**
* The control icons used for rendering common HUD operations
* @type {object}
*/
controlIcons: {
combat: "icons/svg/combat.svg",
visibility: "icons/svg/cowled.svg",
effects: "icons/svg/aura.svg",
lock: "icons/svg/padlock.svg",
up: "icons/svg/up.svg",
down: "icons/svg/down.svg",
defeated: "icons/svg/skull.svg",
light: "icons/svg/light.svg",
lightOff: "icons/svg/light-off.svg",
template: "icons/svg/explosion.svg",
sound: "icons/svg/sound.svg",
soundOff: "icons/svg/sound-off.svg",
doorClosed: "icons/svg/door-closed-outline.svg",
doorOpen: "icons/svg/door-open-outline.svg",
doorSecret: "icons/svg/door-secret-outline.svg",
doorLocked: "icons/svg/door-locked-outline.svg",
wallDirection: "icons/svg/wall-direction.svg"
},
/**
* @typedef {FontFaceDescriptors} FontDefinition
* @property {string} urls An array of remote URLs the font files exist at.
*/
/**
* @typedef {object} FontFamilyDefinition
* @property {boolean} editor Whether the font is available in the rich text editor. This will also enable it
* for notes and drawings.
* @property {FontDefinition[]} fonts Individual font face definitions for this font family. If this is empty, the
* font family may only be loaded from the client's OS-installed fonts.
*/
/**
* A collection of fonts to load either from the user's local system, or remotely.
* @type {Record<string, FontFamilyDefinition>}
*/
fontDefinitions: {
Arial: {editor: true, fonts: []},
Amiri: {
editor: true,
fonts: [
{urls: ["fonts/amiri/amiri-regular.woff2"]},
{urls: ["fonts/amiri/amiri-bold.woff2"], weight: 700}
]
},
"Bruno Ace": {editor: true, fonts: [
{urls: ["fonts/bruno-ace/bruno-ace.woff2"]}
]},
Courier: {editor: true, fonts: []},
"Courier New": {editor: true, fonts: []},
"Modesto Condensed": {
editor: true,
fonts: [
{urls: ["fonts/modesto-condensed/modesto-condensed.woff2"]},
{urls: ["fonts/modesto-condensed/modesto-condensed-bold.woff2"], weight: 700}
]
},
Signika: {
editor: true,
fonts: [
{urls: ["fonts/signika/signika-regular.woff2"]},
{urls: ["fonts/signika/signika-bold.woff2"], weight: 700}
]
},
Times: {editor: true, fonts: []},
"Times New Roman": {editor: true, fonts: []}
},
/**
* The default font family used for text labels on the PIXI Canvas
* @type {string}
*/
defaultFontFamily: "Signika",
/**
* @typedef {object} _StatusEffectConfig Configured status effects which are recognized by the game system
* @property {string} id A string identifier for the effect
* @property {string} label Alias for ActiveEffectData#name (deprecated)
* @property {string} icon Alias for ActiveEffectData#img (deprecated)
* @property {boolean|{actorTypes?: string[]}} [hud=true] Should this effect be selectable in the Token HUD?
* This effect is only selectable in the Token HUD if the Token's
* Actor sub-type is one of the configured ones.
*/
/**
* Configured status effects which are recognized by the game system.
* @typedef {_StatusEffectConfig & Partial<ActiveEffectData>} StatusEffectConfig
*/
/**
* The array of status effects which can be applied to an Actor.
* @type {Array<StatusEffectConfig>}
*/
statusEffects: [
{
id: "dead",
name: "EFFECT.StatusDead",
img: "icons/svg/skull.svg"
},
{
id: "unconscious",
name: "EFFECT.StatusUnconscious",
img: "icons/svg/unconscious.svg"
},
{
id: "sleep",
name: "EFFECT.StatusAsleep",
img: "icons/svg/sleep.svg"
},
{
id: "stun",
name: "EFFECT.StatusStunned",
img: "icons/svg/daze.svg"
},
{
id: "prone",
name: "EFFECT.StatusProne",
img: "icons/svg/falling.svg"
},
{
id: "restrain",
name: "EFFECT.StatusRestrained",
img: "icons/svg/net.svg"
},
{
id: "paralysis",
name: "EFFECT.StatusParalysis",
img: "icons/svg/paralysis.svg"
},
{
id: "fly",
name: "EFFECT.StatusFlying",
img: "icons/svg/wing.svg"
},
{
id: "blind",
name: "EFFECT.StatusBlind",
img: "icons/svg/blind.svg"
},
{
id: "deaf",
name: "EFFECT.StatusDeaf",
img: "icons/svg/deaf.svg"
},
{
id: "silence",
name: "EFFECT.StatusSilenced",
img: "icons/svg/silenced.svg"
},
{
id: "fear",
name: "EFFECT.StatusFear",
img: "icons/svg/terror.svg"
},
{
id: "burning",
name: "EFFECT.StatusBurning",
img: "icons/svg/fire.svg"
},
{
id: "frozen",
name: "EFFECT.StatusFrozen",
img: "icons/svg/frozen.svg"
},
{
id: "shock",
name: "EFFECT.StatusShocked",
img: "icons/svg/lightning.svg"
},
{
id: "corrode",
name: "EFFECT.StatusCorrode",
img: "icons/svg/acid.svg"
},
{
id: "bleeding",
name: "EFFECT.StatusBleeding",
img: "icons/svg/blood.svg"
},
{
id: "disease",
name: "EFFECT.StatusDisease",
img: "icons/svg/biohazard.svg"
},
{
id: "poison",
name: "EFFECT.StatusPoison",
img: "icons/svg/poison.svg"
},
{
id: "curse",
name: "EFFECT.StatusCursed",
img: "icons/svg/sun.svg"
},
{
id: "regen",
name: "EFFECT.StatusRegen",
img: "icons/svg/regen.svg"
},
{
id: "degen",
name: "EFFECT.StatusDegen",
img: "icons/svg/degen.svg"
},
{
id: "hover",
name: "EFFECT.StatusHover",
img: "icons/svg/wingfoot.svg"
},
{
id: "burrow",
name: "EFFECT.StatusBurrow",
img: "icons/svg/mole.svg"
},
{
id: "upgrade",
name: "EFFECT.StatusUpgrade",
img: "icons/svg/upgrade.svg"
},
{
id: "downgrade",
name: "EFFECT.StatusDowngrade",
img: "icons/svg/downgrade.svg"
},
{
id: "invisible",
name: "EFFECT.StatusInvisible",
img: "icons/svg/invisible.svg"
},
{
id: "target",
name: "EFFECT.StatusTarget",
img: "icons/svg/target.svg"
},
{
id: "eye",
name: "EFFECT.StatusMarked",
img: "icons/svg/eye.svg"
},
{
id: "bless",
name: "EFFECT.StatusBlessed",
img: "icons/svg/angel.svg"
},
{
id: "fireShield",
name: "EFFECT.StatusFireShield",
img: "icons/svg/fire-shield.svg"
},
{
id: "coldShield",
name: "EFFECT.StatusIceShield",
img: "icons/svg/ice-shield.svg"
},
{
id: "magicShield",
name: "EFFECT.StatusMagicShield",
img: "icons/svg/mage-shield.svg"
},
{
id: "holyShield",
name: "EFFECT.StatusHolyShield",
img: "icons/svg/holy-shield.svg"
}
].map(status => {
/** @deprecated since v12 */
for ( const [oldKey, newKey] of Object.entries({label: "name", icon: "img"}) ) {
const msg = `StatusEffectConfig#${oldKey} has been deprecated in favor of StatusEffectConfig#${newKey}`;
Object.defineProperty(status, oldKey, {
get() {
foundry.utils.logCompatibilityWarning(msg, {since: 12, until: 14, once: true});
return this[newKey];
},
set(value) {
foundry.utils.logCompatibilityWarning(msg, {since: 12, until: 14, once: true});
this[newKey] = value;
},
enumerable: false,
configurable: true
});
}
return status;
}),
/**
* A mapping of status effect IDs which provide some additional mechanical integration.
* @enum {string}
*/
specialStatusEffects: {
DEFEATED: "dead",
INVISIBLE: "invisible",
BLIND: "blind",
BURROW: "burrow",
HOVER: "hover",
FLY: "fly"
},
/**
* A mapping of core audio effects used which can be replaced by systems or mods
* @type {object}
*/
sounds: {
dice: "sounds/dice.wav",
lock: "sounds/lock.wav",
notification: "sounds/notify.wav",
combat: "sounds/drums.wav"
},
/**
* Define the set of supported languages for localization
* @type {{string, string}}
*/
supportedLanguages: {
en: "English"
},
/**
* Localization constants.
* @type {object}
*/
i18n: {
/**
* In operations involving the document index, search prefixes must have at least this many characters to avoid too
* large a search space. Languages that have hundreds or thousands of characters will typically have very shallow
* search trees, so it should be safe to lower this number in those cases.
*/
searchMinimumCharacterLength: 4
},
/**
* Configuration for time tracking
* @type {{turnTime: number}}
*/
time: {
turnTime: 0,
roundTime: 0
},
/* -------------------------------------------- */
/* Embedded Documents */
/* -------------------------------------------- */
/**
* Configuration for the ActiveEffect embedded document type
*/
ActiveEffect: {
documentClass: ActiveEffect,
dataModels: {},
typeLabels: {},
typeIcons: {},
/**
* If true, Active Effects on Items will be copied to the Actor when the Item is created on the Actor if the
* Active Effect's transfer property is true, and will be deleted when that Item is deleted from the Actor.
* If false, Active Effects are never copied to the Actor, but will still apply to the Actor from within the Item
* if the transfer property on the Active Effect is true.
* @deprecated since v11
*/
legacyTransferral: true
},
/**
* Configuration for the ActorDelta embedded document type.
*/
ActorDelta: {
documentClass: ActorDelta
},
/**
* Configuration for the Card embedded Document type
*/
Card: {
documentClass: Card,
dataModels: {},
typeLabels: {},
typeIcons: {}
},
/**
* Configuration for the TableResult embedded document type
*/
TableResult: {
documentClass: TableResult
},
/**
* Configuration for the JournalEntryPage embedded document type.
*/
JournalEntryPage: {
documentClass: JournalEntryPage,
dataModels: {},
typeLabels: {},
typeIcons: {
image: "fas fa-file-image",
pdf: "fas fa-file-pdf",
text: "fas fa-file-lines",
video: "fas fa-file-video"
},
defaultType: "text",
sidebarIcon: "fas fa-book-open"
},
/**
* Configuration for the PlaylistSound embedded document type
*/
PlaylistSound: {
documentClass: PlaylistSound,
sidebarIcon: "fas fa-music"
},
/**
* Configuration for the AmbientLight embedded document type and its representation on the game Canvas
* @enum {Function}
*/
AmbientLight: {
documentClass: AmbientLightDocument,
objectClass: AmbientLight,
layerClass: LightingLayer
},
/**
* Configuration for the AmbientSound embedded document type and its representation on the game Canvas
* @enum {Function}
*/
AmbientSound: {
documentClass: AmbientSoundDocument,
objectClass: AmbientSound,
layerClass: SoundsLayer
},
/**
* Configuration for the Combatant embedded document type within a Combat document
* @enum {Function}
*/
Combatant: {
documentClass: Combatant,
dataModels: {},
typeLabels: {},
typeIcons: {}
},
/**
* Configuration for the Drawing embedded document type and its representation on the game Canvas
* @type {{
* documentClass: typeof DrawingDocument,
* objectClass: typeof Drawing,
* layerClass: typeof DrawingsLayer,
* hudClass: typeof DrawingHUD
* }}
*/
Drawing: {
documentClass: DrawingDocument,
objectClass: Drawing,
layerClass: DrawingsLayer,
hudClass: DrawingHUD
},
/**
* Configuration for the MeasuredTemplate embedded document type and its representation on the game Canvas
* @enum {Function}
*/
MeasuredTemplate: {
defaults: {
angle: 53.13,
width: 1
},
types: {
circle: "Circle",
cone: "Cone",
rect: "Rectangle",
ray: "Ray"
},
documentClass: MeasuredTemplateDocument,
objectClass: MeasuredTemplate,
layerClass: TemplateLayer
},
/**
* Configuration for the Note embedded document type and its representation on the game Canvas
* @enum {Function}
*/
Note: {
documentClass: NoteDocument,
objectClass: Note,
layerClass: NotesLayer
},
/**
* Configuration for the Region embedded document type and its representation on the game Canvas
*/
Region: {
documentClass: RegionDocument,
objectClass: Region,
layerClass: RegionLayer
},
/**
* Configuration for the RegionBehavior embedded document type
*/
RegionBehavior: {
documentClass: RegionBehavior,
dataModels: {
adjustDarknessLevel: foundry.data.regionBehaviors.AdjustDarknessLevelRegionBehaviorType,
displayScrollingText: foundry.data.regionBehaviors.DisplayScrollingTextRegionBehaviorType,
executeMacro: foundry.data.regionBehaviors.ExecuteMacroRegionBehaviorType,
executeScript: foundry.data.regionBehaviors.ExecuteScriptRegionBehaviorType,
pauseGame: foundry.data.regionBehaviors.PauseGameRegionBehaviorType,
suppressWeather: foundry.data.regionBehaviors.SuppressWeatherRegionBehaviorType,
teleportToken: foundry.data.regionBehaviors.TeleportTokenRegionBehaviorType,
toggleBehavior: foundry.data.regionBehaviors.ToggleBehaviorRegionBehaviorType
},
typeLabels: {},
typeIcons: {
adjustDarknessLevel: "fa-solid fa-circle-half-stroke",
displayScrollingText: "fa-solid fa-message-arrow-up",
executeMacro: "fa-solid fa-code",
executeScript: "fa-brands fa-js",
pauseGame: "fa-solid fa-pause",
suppressWeather: "fa-solid fa-cloud-slash",
teleportToken: "fa-solid fa-transporter-1",
toggleBehavior: "fa-solid fa-sliders"
}
},
/**
* Configuration for the Tile embedded document type and its representation on the game Canvas
* @type {{
* documentClass: typeof TileDocument,
* objectClass: typeof Tile,
* layerClass: typeof TilesLayer,
* hudClass: typeof TileHUD
* }}
*/
Tile: {
documentClass: TileDocument,
objectClass: Tile,
layerClass: TilesLayer,
hudClass: TileHUD
},
/**
* Configuration for the Token embedded document type and its representation on the game Canvas
* @type {{
* documentClass: typeof TokenDocument,
* objectClass: typeof Token,
* layerClass: typeof TokenLayer,
* prototypeSheetClass: typeof TokenConfig,
* hudClass: typeof TokenHUD,
* adjectivesPrefix: string,
* ring: foundry.canvas.tokens.TokenRingConfig
* }}
*/
Token: {
documentClass: TokenDocument,
objectClass: Token,
layerClass: TokenLayer,
prototypeSheetClass: TokenConfig,
hudClass: TokenHUD,
adjectivesPrefix: "TOKEN.Adjectives"
// ring property is initialized in foundry.canvas.tokens.TokenRingConfig.initialize
},
/**
* @typedef {Object} WallDoorSound
* @property {string} label A localization string label
* @property {string} close A sound path when the door is closed
* @property {string} lock A sound path when the door becomes locked
* @property {string} open A sound path when opening the door
* @property {string} test A sound path when attempting to open a locked door
* @property {string} unlock A sound path when the door becomes unlocked
*/
/**
* Configuration for the Wall embedded document type and its representation on the game Canvas
* @property {typeof ClientDocument} documentClass
* @property {typeof PlaceableObject} objectClass
* @property {typeof CanvasLayer} layerClass
* @property {number} thresholdAttenuationMultiplier
* @property {WallDoorSound[]} doorSounds
*/
Wall: {
documentClass: WallDocument,
objectClass: Wall,
layerClass: WallsLayer,
thresholdAttenuationMultiplier: 1,
doorSounds: {
futuristicFast: {
label: "WALLS.DoorSound.FuturisticFast",
close: "sounds/doors/futuristic/close-fast.ogg",
lock: "sounds/doors/futuristic/lock.ogg",
open: "sounds/doors/futuristic/open-fast.ogg",
test: "sounds/doors/futuristic/test.ogg",
unlock: "sounds/doors/futuristic/unlock.ogg"
},
futuristicHydraulic: {
label: "WALLS.DoorSound.FuturisticHydraulic",
close: "sounds/doors/futuristic/close-hydraulic.ogg",
lock: "sounds/doors/futuristic/lock.ogg",
open: "sounds/doors/futuristic/open-hydraulic.ogg",
test: "sounds/doors/futuristic/test.ogg",
unlock: "sounds/doors/futuristic/unlock.ogg"
},
futuristicForcefield: {
label: "WALLS.DoorSound.FuturisticForcefield",
close: "sounds/doors/futuristic/close-forcefield.ogg",
lock: "sounds/doors/futuristic/lock.ogg",
open: "sounds/doors/futuristic/open-forcefield.ogg",
test: "sounds/doors/futuristic/test-forcefield.ogg",
unlock: "sounds/doors/futuristic/unlock.ogg"
},
industrial: {
label: "WALLS.DoorSound.Industrial",
close: "sounds/doors/industrial/close.ogg",
lock: "sounds/doors/industrial/lock.ogg",
open: "sounds/doors/industrial/open.ogg",
test: "sounds/doors/industrial/test.ogg",
unlock: "sounds/doors/industrial/unlock.ogg"
},
industrialCreaky: {
label: "WALLS.DoorSound.IndustrialCreaky",
close: "sounds/doors/industrial/close-creaky.ogg",
lock: "sounds/doors/industrial/lock.ogg",
open: "sounds/doors/industrial/open-creaky.ogg",
test: "sounds/doors/industrial/test.ogg",
unlock: "sounds/doors/industrial/unlock.ogg"
},
jail: {
label: "WALLS.DoorSound.Jail",
close: "sounds/doors/jail/close.ogg",
lock: "sounds/doors/jail/lock.ogg",
open: "sounds/doors/jail/open.ogg",
test: "sounds/doors/jail/test.ogg",
unlock: "sounds/doors/jail/unlock.ogg"
},
magicDoor: {
label: "WALLS.DoorSound.MagicDoor",
close: "sounds/doors/magic/door-close.ogg",
lock: "sounds/doors/magic/lock.ogg",
open: "sounds/doors/magic/door-open.ogg",
test: "sounds/doors/magic/test.ogg",
unlock: "sounds/doors/magic/unlock.ogg"
},
magicWall: {
label: "WALLS.DoorSound.MagicWall",
close: "sounds/doors/magic/wall-close.ogg",
lock: "sounds/doors/magic/lock.ogg",
open: "sounds/doors/magic/wall-open.ogg",
test: "sounds/doors/magic/test.ogg",
unlock: "sounds/doors/magic/unlock.ogg"
},
metal: {
label: "WALLS.DoorSound.Metal",
close: "sounds/doors/metal/close.ogg",
lock: "sounds/doors/metal/lock.ogg",
open: "sounds/doors/metal/open.ogg",
test: "sounds/doors/metal/test.ogg",
unlock: "sounds/doors/metal/unlock.ogg"
},
slidingMetal: {
label: "WALLS.DoorSound.SlidingMetal",
close: "sounds/doors/shutter/close.ogg",
lock: "sounds/doors/shutter/lock.ogg",
open: "sounds/doors/shutter/open.ogg",
test: "sounds/doors/shutter/test.ogg",
unlock: "sounds/doors/shutter/unlock.ogg"
},
slidingModern: {
label: "WALLS.DoorSound.SlidingModern",
close: "sounds/doors/sliding/close.ogg",
lock: "sounds/doors/sliding/lock.ogg",
open: "sounds/doors/sliding/open.ogg",
test: "sounds/doors/sliding/test.ogg",
unlock: "sounds/doors/sliding/unlock.ogg"
},
slidingWood: {
label: "WALLS.DoorSound.SlidingWood",
close: "sounds/doors/sliding/close-wood.ogg",
lock: "sounds/doors/sliding/lock.ogg",
open: "sounds/doors/sliding/open-wood.ogg",
test: "sounds/doors/sliding/test.ogg",
unlock: "sounds/doors/sliding/unlock.ogg"
},
stoneBasic: {
label: "WALLS.DoorSound.StoneBasic",
close: "sounds/doors/stone/close.ogg",
lock: "sounds/doors/stone/lock.ogg",
open: "sounds/doors/stone/open.ogg",
test: "sounds/doors/stone/test.ogg",
unlock: "sounds/doors/stone/unlock.ogg"
},
stoneRocky: {
label: "WALLS.DoorSound.StoneRocky",
close: "sounds/doors/stone/close-rocky.ogg",
lock: "sounds/doors/stone/lock.ogg",
open: "sounds/doors/stone/open-rocky.ogg",
test: "sounds/doors/stone/test.ogg",
unlock: "sounds/doors/stone/unlock.ogg"
},
stoneSandy: {
label: "WALLS.DoorSound.StoneSandy",
close: "sounds/doors/stone/close-sandy.ogg",
lock: "sounds/doors/stone/lock.ogg",
open: "sounds/doors/stone/open-sandy.ogg",
test: "sounds/doors/stone/test.ogg",
unlock: "sounds/doors/stone/unlock.ogg"
},
woodBasic: {
label: "WALLS.DoorSound.WoodBasic",
close: "sounds/doors/wood/close.ogg",
lock: "sounds/doors/wood/lock.ogg",
open: "sounds/doors/wood/open.ogg",
test: "sounds/doors/wood/test.ogg",
unlock: "sounds/doors/wood/unlock.ogg"
},
woodCreaky: {
label: "WALLS.DoorSound.WoodCreaky",
close: "sounds/doors/wood/close-creaky.ogg",
lock: "sounds/doors/wood/lock.ogg",
open: "sounds/doors/wood/open-creaky.ogg",
test: "sounds/doors/wood/test.ogg",
unlock: "sounds/doors/wood/unlock.ogg"
},
woodHeavy: {
label: "WALLS.DoorSound.WoodHeavy",
close: "sounds/doors/wood/close-heavy.ogg",
lock: "sounds/doors/wood/lock.ogg",
open: "sounds/doors/wood/open-heavy.ogg",
test: "sounds/doors/wood/test.ogg",
unlock: "sounds/doors/wood/unlock.ogg"
}
}
},
/**
* An enumeration of sound effects which can be applied to Sound instances.
* @enum {{label: string, effectClass: AudioNode}}
*/
soundEffects: {
lowpass: {
label: "SOUND.EFFECTS.LOWPASS",
effectClass: foundry.audio.BiquadFilterEffect
},
highpass: {
label: "SOUND.EFFECTS.HIGHPASS",
effectClass: foundry.audio.BiquadFilterEffect
},
reverb: {
label: "SOUND.EFFECTS.REVERB",
effectClass: foundry.audio.ConvolverEffect
}
},
/* -------------------------------------------- */
/* Integrations */
/* -------------------------------------------- */
/**
* Default configuration options for TinyMCE editors
* @type {object}
*/
TinyMCE: {
branding: false,
menubar: false,
statusbar: false,
content_css: ["/css/mce.css"],
plugins: "lists image table code save link",
toolbar: "styles bullist numlist image table hr link removeformat code save",
save_enablewhendirty: true,
table_default_styles: {},
style_formats: [
{
title: "Custom",
items: [
{
title: "Secret",
block: "section",
classes: "secret",
wrapper: true
}
]
}
],
style_formats_merge: true
},
/**
* @callback TextEditorEnricher
* @param {RegExpMatchArray} match The regular expression match result
* @param {EnrichmentOptions} [options] Options provided to customize text enrichment
* @returns {Promise<HTMLElement|null>} An HTML element to insert in place of the matched text or null to
* indicate that no replacement should be made.
*/
/**
* @typedef {object} TextEditorEnricherConfig
* @property {RegExp} pattern The string pattern to match. Must be flagged as global.
* @property {boolean} [replaceParent] Hoist the replacement element out of its containing element if it replaces
* the entire contents of the element.
* @property {TextEditorEnricher} enricher The function that will be called on each match. It is expected that this
* returns an HTML element to be inserted into the final enriched content.
*/
/**
* Rich text editing configuration.
* @type {object}
*/
TextEditor: {
/**
* A collection of custom enrichers that can be applied to text content, allowing for the matching and handling of
* custom patterns.
* @type {TextEditorEnricherConfig[]}
*/
enrichers: []
},
/**
* Configuration for the WebRTC implementation class
* @type {object}
*/
WebRTC: {
clientClass: SimplePeerAVClient,
detectPeerVolumeInterval: 50,
detectSelfVolumeInterval: 20,
emitVolumeInterval: 25,
speakingThresholdEvents: 2,
speakingHistoryLength: 10,
connectedUserPollIntervalS: 8
},
/* -------------------------------------------- */
/* Interface */
/* -------------------------------------------- */
/**
* Configure the Application classes used to render various core UI elements in the application.
* The order of this object is relevant, as certain classes need to be constructed and referenced before others.
* @type {Record<string, Application>}
*/
ui: {
menu: MainMenu,
sidebar: Sidebar,
pause: Pause,
nav: SceneNavigation,
notifications: Notifications,
actors: ActorDirectory,
cards: CardsDirectory,
chat: ChatLog,
combat: CombatTracker,
compendium: CompendiumDirectory,
controls: SceneControls,
hotbar: Hotbar,
items: ItemDirectory,
journal: JournalDirectory,
macros: MacroDirectory,
players: PlayerList,
playlists: PlaylistDirectory,
scenes: SceneDirectory,
settings: Settings,
tables: RollTableDirectory,
webrtc: CameraViews
}
};
// Define the ring property with a TokenRingConfig instance
Object.defineProperty(CONFIG.Token, 'ring', {
value: new foundry.canvas.tokens.TokenRingConfig(),
enumerable: true
});
/**
* @deprecated since v11
*/
["Actor", "Item", "JournalEntryPage", "Cards", "Card"].forEach(doc => {
const warning = `You are accessing CONFIG.${doc}.systemDataModels which is deprecated. `
+ `Please use CONFIG.${doc}.dataModels instead.`;
Object.defineProperty(CONFIG[doc], "systemDataModels", {
enumerable: false,
get() {
foundry.utils.logCompatibilityWarning(warning, {since: 11, until: 13});
return CONFIG[doc].dataModels;
},
set(models) {
foundry.utils.logCompatibilityWarning(warning, {since: 11, until: 13});
CONFIG[doc].dataModels = models;
}
});
});
/**
* @deprecated since v11
*/
Object.defineProperty(CONFIG.Canvas, "losBackend", {
get() {
const warning = "You are accessing CONFIG.Canvas.losbackend, which is deprecated."
+ " Use CONFIG.Canvas.polygonBackends.sight instead.";
foundry.utils.logCompatibilityWarning(warning, {since: 11, until: 13});
return CONFIG.Canvas.polygonBackends.sight;
},
set(cls) {
const warning = "You are setting CONFIG.Canvas.losbackend, which is deprecated."
+ " Use CONFIG.Canvas.polygonBackends[type] instead.";
foundry.utils.logCompatibilityWarning(warning, {since: 11, until: 13});
for ( const k of Object.keys(CONFIG.Canvas.polygonBackends) ) CONFIG.Canvas.polygonBackends[k] = cls;
}
});