1598 lines
48 KiB
Markdown
1598 lines
48 KiB
Markdown
# Foundry VTT + PF1e Module Development Environment
|
|
|
|
> **Version**: 1.0.0 | **Last Updated**: 2025-01-29 | **Maintainer**: Development Team
|
|
|
|
## Project Overview
|
|
|
|
### Purpose
|
|
This is a development environment for creating custom macros and debugging the Foundry VTT virtual tabletop with the Pathfinder 1e (PF1e) game system. The project combines the Foundry VTT core application (v11.315) with the PF1e system module (v10.8) to enable macro development, automation scripting, and troubleshooting of game mechanics.
|
|
|
|
### Key Objectives
|
|
- Develop custom macros for Pathfinder 1e character automation
|
|
- Debug and troubleshoot Foundry VTT and PF1e system issues
|
|
- Automate complex character abilities (e.g., Magus Arcane Pool, Haste buff management)
|
|
- Provide AI-assisted development via Claude Code with extensive MCP server integration
|
|
- Maintain a professional development environment with linting, formatting, and type checking
|
|
|
|
### Project Type
|
|
- [x] Virtual Tabletop Platform (Foundry VTT)
|
|
- [x] Game System Module (Pathfinder 1e)
|
|
- [x] Macro Development (JavaScript automation scripts)
|
|
- [x] Electron Application (Desktop runtime)
|
|
- [ ] Web Application
|
|
- [ ] CLI Tool
|
|
- [ ] Library/Package
|
|
|
|
### Target Users/Audience
|
|
Game Masters (GMs) and players using Foundry VTT for Pathfinder 1e campaigns who need custom automation, particularly for complex character abilities and buff management.
|
|
|
|
---
|
|
|
|
## Technology Stack
|
|
|
|
### Core Technologies
|
|
- **Language(s)**: JavaScript (ES6+), TypeScript definitions (.d.ts)
|
|
- **Runtime**: Node.js v16-19 (via Electron)
|
|
- **Platform**: Electron (cross-platform desktop app)
|
|
- **Foundry VTT Version**: v11.315 (stable)
|
|
- **Game System**: Pathfinder 1e v10.8
|
|
|
|
### Frontend Technologies
|
|
|
|
#### Rendering & UI
|
|
- **Canvas Engine**: PIXI.js v7.2.4 (WebGL/Canvas2D rendering)
|
|
- `@pixi/graphics-smooth` - Smooth graphics rendering
|
|
- `@pixi/particle-emitter` - Particle effects
|
|
- **DOM Manipulation**: jQuery v3.6.4
|
|
- **Template Engine**: Handlebars v4.7.7
|
|
- **Rich Text Editor**: ProseMirror v1.x (modular editor)
|
|
- **Alternative Editor**: TinyMCE v6.7.1
|
|
- **Styling**: LESS → CSS compilation
|
|
|
|
#### UI Framework
|
|
```javascript
|
|
// Foundry VTT uses vanilla JavaScript with global objects
|
|
game // Main game instance
|
|
ui // UI managers (notifications, chat, etc.)
|
|
canvas // Canvas rendering system
|
|
CONFIG // Global configuration
|
|
```
|
|
|
|
### Backend Technologies
|
|
|
|
#### Server Framework
|
|
- **Web Server**: Express.js v4.18.2
|
|
- **Session Management**: express-session with NeDB store
|
|
- **File Upload**: express-fileupload
|
|
- **Compression**: compression middleware
|
|
- **Static Files**: serve-static
|
|
|
|
#### Database & Storage
|
|
- **Primary Database**: NeDB v1.8.0 (embedded NoSQL)
|
|
- World data storage
|
|
- Compendium packs
|
|
- Session management
|
|
- **Alternative**: classic-level (LevelDB abstraction)
|
|
- **File Storage**: Local filesystem (fs-extra v11.1.1)
|
|
- **Cloud Storage**: AWS S3 (@aws-sdk/client-s3 v3.312.0)
|
|
|
|
#### Real-Time Communication
|
|
- **Protocol**: Socket.io v4.6.1 (WebSocket + fallbacks)
|
|
- **Features**:
|
|
- Room-based communication (per world)
|
|
- Real-time document synchronization
|
|
- Audio/video signaling
|
|
- Client-server data updates
|
|
|
|
### PF1 System Technologies
|
|
|
|
#### Build & Development
|
|
- **Module System**: ES Modules (.mjs files)
|
|
- **Build Tool**: Vite v4.5.0 (with HMR support)
|
|
- **Linting**: ESLint v8.53.0
|
|
- **Code Formatting**: Prettier v3.1.0
|
|
- **Testing Framework**: @ethaks/fvtt-quench (Foundry-specific testing)
|
|
- **Documentation Generator**: TypeDoc v0.25.3
|
|
- **Git Hooks**: Husky v8.0.3 with lint-staged
|
|
|
|
#### Development Scripts
|
|
```json
|
|
{
|
|
"build": "vite build",
|
|
"build:watch": "vite build --mode development --watch",
|
|
"packs:extract": "node ./tools/packs.mjs extract",
|
|
"packs:compile": "node ./tools/packs.mjs compile",
|
|
"lint": "eslint . --cache",
|
|
"format": "prettier --write --cache .",
|
|
"docs": "typedoc"
|
|
}
|
|
```
|
|
|
|
### Infrastructure & DevOps
|
|
- **Version Control**: Git
|
|
- **AI Development**: Claude Code with 8 MCP servers
|
|
- serena (code navigation + memory)
|
|
- sequential-thinking (complex reasoning)
|
|
- context7 (library documentation)
|
|
- memory (knowledge graph)
|
|
- fetch (web content)
|
|
- windows-mcp (desktop automation)
|
|
- playwright (browser automation)
|
|
- database-server (SQL access)
|
|
|
|
### Development Tools
|
|
- **IDE**: Visual Studio Code (recommended)
|
|
- **Package Manager**: npm
|
|
- **Node Version**: 16-19 (Electron compatible)
|
|
- **Module Format**: ES Modules (.mjs) for PF1 system, CommonJS for Foundry core
|
|
|
|
---
|
|
|
|
## Project Structure
|
|
|
|
### Directory Layout
|
|
```
|
|
c:\DEV\Foundry/
|
|
├── src/ # Source code root
|
|
│ ├── FoundryVTT-11.315/ # Foundry VTT core application
|
|
│ │ └── resources/app/ # Electron app resources
|
|
│ │ ├── main.js # Electron main process entry
|
|
│ │ ├── package.json # Core dependencies (Node 16-19)
|
|
│ │ ├── client/ # Client-side JavaScript
|
|
│ │ │ ├── game.js # Main game client (Game class)
|
|
│ │ │ ├── config.js # Configuration constants
|
|
│ │ │ ├── apps/ # Application windows (FormApplication)
|
|
│ │ │ ├── audio/ # Audio/sound management
|
|
│ │ │ ├── av/ # Audio/video (WebRTC)
|
|
│ │ │ ├── canvas/ # PIXI.js canvas rendering layers
|
|
│ │ │ ├── core/ # Core utilities (hooks, settings)
|
|
│ │ │ ├── dice/ # Dice rolling system (Roll, DiceTerm)
|
|
│ │ │ ├── pixi/ # PIXI.js extensions
|
|
│ │ │ ├── tours/ # User onboarding tours
|
|
│ │ │ └── ui/ # UI components (notifications, dialogs)
|
|
│ │ ├── common/ # Shared client/server code
|
|
│ │ │ ├── documents/ # Document base classes
|
|
│ │ │ ├── abstract/ # Abstract data models
|
|
│ │ │ ├── config.mjs # Shared configuration
|
|
│ │ │ ├── constants.mjs # Constants and enums
|
|
│ │ │ ├── utils/ # Utility functions
|
|
│ │ │ └── packages/ # Package management
|
|
│ │ ├── dist/ # Compiled/bundled code
|
|
│ │ ├── public/ # Public web assets
|
|
│ │ │ ├── scripts/ # Bundled client scripts
|
|
│ │ │ │ ├── foundry.js # Main bundled script (~2MB)
|
|
│ │ │ │ └── worker.js # Web worker for background tasks
|
|
│ │ │ ├── lang/en.json # English localization
|
|
│ │ │ ├── tours/ # Tour definitions (JSON)
|
|
│ │ │ └── nue/ # NUE engine assets
|
|
│ │ ├── templates/ # Handlebars templates (.html)
|
|
│ │ ├── prosemirror/ # ProseMirror rich text editor
|
|
│ │ └── node_modules/ # Foundry core dependencies
|
|
│ │
|
|
│ ├── foundryvtt-pathfinder1-v10.8/ # Pathfinder 1e System Module
|
|
│ │ ├── pf1.js # System entry point (imports pf1.mjs)
|
|
│ │ ├── pf1.mjs # Main system module (ES module)
|
|
│ │ ├── package.json # PF1 dev dependencies & scripts
|
|
│ │ ├── public/ # Public system files
|
|
│ │ │ └── system.json # System manifest (metadata)
|
|
│ │ ├── module/ # System source code (ES modules)
|
|
│ │ │ ├── config.mjs # PF1 game configuration
|
|
│ │ │ │ # Defines: abilities, skills, alignments, saves, etc.
|
|
│ │ │ ├── config.d.ts # TypeScript definitions for config
|
|
│ │ │ ├── modules.mjs # Module registry/loader
|
|
│ │ │ ├── migration.mjs # Data migration system
|
|
│ │ │ ├── patch-core.mjs # Foundry core monkey patches
|
|
│ │ │ ├── socket.mjs # Socket event handlers
|
|
│ │ │ ├── action-use/ # Action usage system
|
|
│ │ │ │ ├── action-use.mjs # Main action resolution
|
|
│ │ │ │ ├── chat-attack.mjs # Attack chat cards
|
|
│ │ │ │ └── chat-context.mjs # Chat context menu
|
|
│ │ │ ├── applications/ # UI applications
|
|
│ │ │ │ ├── actor/ # Actor sheets by type
|
|
│ │ │ │ │ ├── character-sheet.mjs
|
|
│ │ │ │ │ ├── npc-sheet.mjs
|
|
│ │ │ │ │ └── vehicle-sheet.mjs
|
|
│ │ │ │ ├── item/ # Item sheets
|
|
│ │ │ │ │ └── item-sheet.mjs
|
|
│ │ │ │ ├── compendium-browser/ # Compendium browser
|
|
│ │ │ │ ├── sidebar/ # Sidebar applications
|
|
│ │ │ │ └── settings/ # Settings dialogs
|
|
│ │ │ ├── canvas/ # Canvas layer extensions
|
|
│ │ │ ├── chat/ # Chat message handlers
|
|
│ │ │ ├── components/ # Reusable UI components
|
|
│ │ │ ├── dice/ # Dice rolling extensions
|
|
│ │ │ │ └── terms/ # Custom dice terms
|
|
│ │ │ ├── documents/ # Document classes
|
|
│ │ │ │ ├── actor/ # ActorPF class
|
|
│ │ │ │ │ ├── entity.mjs # Main actor class
|
|
│ │ │ │ │ ├── calculate.mjs # Stat calculation
|
|
│ │ │ │ │ ├── rest.mjs # Rest mechanics
|
|
│ │ │ │ │ └── spellcasting.mjs # Spellcasting logic
|
|
│ │ │ │ ├── item/ # ItemPF class
|
|
│ │ │ │ │ ├── entity.mjs # Main item class
|
|
│ │ │ │ │ └── types/ # Item type handlers
|
|
│ │ │ │ ├── chat-message.mjs # ChatMessagePF
|
|
│ │ │ │ └── combat.mjs # CombatPF
|
|
│ │ │ ├── migration/ # Version migration scripts
|
|
│ │ │ ├── registry/ # Feature registries
|
|
│ │ │ ├── test/ # Unit tests (Quench)
|
|
│ │ │ ├── utils/ # Utility functions
|
|
│ │ │ └── _module.mjs # Re-exports for easy import
|
|
│ │ ├── lang/ # Localization files
|
|
│ │ │ ├── en.json # English (primary language)
|
|
│ │ │ ├── de.json # German
|
|
│ │ │ ├── fr.json # French
|
|
│ │ │ ├── es.json # Spanish
|
|
│ │ │ ├── it.json # Italian
|
|
│ │ │ ├── cn.json # Chinese
|
|
│ │ │ └── pt_BR.json # Portuguese (Brazil)
|
|
│ │ ├── less/ # LESS stylesheets
|
|
│ │ │ ├── pf1.less # Main stylesheet
|
|
│ │ │ └── [various component styles]
|
|
│ │ ├── packs/ # Compendium packs (.db files)
|
|
│ │ │ # Pre-packaged actors, items, spells, feats, etc.
|
|
│ │ ├── help/ # Help documentation
|
|
│ │ ├── changelogs/ # Version changelogs
|
|
│ │ ├── tools/ # Build/dev tools
|
|
│ │ │ └── packs.mjs # Compendium pack compiler
|
|
│ │ ├── .eslintrc.js # ESLint configuration
|
|
│ │ ├── .prettierrc.json # Prettier formatting config
|
|
│ │ ├── vite.config.js # Vite build configuration
|
|
│ │ ├── typedoc.json # TypeDoc documentation config
|
|
│ │ └── hooks.d.ts # TypeScript hook definitions
|
|
│ │
|
|
│ ├── macro.js # Custom Arcane Pool macro
|
|
│ │ # Magus class feature automation with dialog UI
|
|
│ ├── macro_haste.js # Haste buff automation macro
|
|
│ │ # Intercepts attacks to apply Haste effects
|
|
│ └── zeratal.json # Character data export
|
|
│ # Example Magus character for testing
|
|
│
|
|
├── .claude/ # Claude Code configuration
|
|
│ ├── settings.json # Shared Claude settings
|
|
│ ├── settings.local.json # Local user settings
|
|
│ ├── agents/ # Specialized AI agents (8 total)
|
|
│ ├── commands/ # Slash commands (9 total)
|
|
│ ├── output-styles/ # Output formatting (6 styles)
|
|
│ ├── skills/ # Custom skills
|
|
│ ├── hooks/ # Event hooks
|
|
│ └── tools/ # Utility scripts
|
|
│
|
|
├── .mcp.json # MCP server configuration
|
|
├── .git/ # Git repository
|
|
├── .gitignore # Git ignore rules
|
|
├── CLAUDE.md # This file - project documentation
|
|
├── README.md # Project overview
|
|
└── QUICKSTART.md # Quick start guide
|
|
```
|
|
|
|
### Key Files
|
|
- **Foundry Entry**: [main.js](src/FoundryVTT-11.315/resources/app/main.js) - Electron main process
|
|
- **Client Entry**: [foundry.js](src/FoundryVTT-11.315/resources/app/public/scripts/foundry.js) - Bundled client
|
|
- **PF1 Entry**: [pf1.js](src/foundryvtt-pathfinder1-v10.8/pf1.js) → [pf1.mjs](src/foundryvtt-pathfinder1-v10.8/pf1.mjs) - System initialization
|
|
- **PF1 Config**: [config.mjs](src/foundryvtt-pathfinder1-v10.8/module/config.mjs) - Game system configuration
|
|
- **System Manifest**: [system.json](src/foundryvtt-pathfinder1-v10.8/public/system.json) - System metadata
|
|
- **Custom Macros**: [macro.js](src/macro.js), [macro_haste.js](src/macro_haste.js) - Automation scripts
|
|
- **Character Data**: [zeratal.json](src/zeratal.json) - Test character export
|
|
|
|
### Module Organization
|
|
The project follows a clear separation between:
|
|
1. **Foundry Core** - Generic VTT platform code
|
|
2. **PF1 System** - Pathfinder 1e game rules and mechanics
|
|
3. **Custom Macros** - User-specific automation scripts
|
|
|
|
Each layer builds on the previous:
|
|
```
|
|
Custom Macros
|
|
↓ (uses)
|
|
PF1 System API (ActorPF, ItemPF, CONFIG.PF1)
|
|
↓ (extends)
|
|
Foundry Core API (Actor, Item, game, ui, canvas)
|
|
↓ (runs on)
|
|
Electron + Node.js
|
|
```
|
|
|
|
---
|
|
|
|
## Code Style & Standards
|
|
|
|
### Naming Conventions
|
|
|
|
#### Variables & Functions
|
|
- Use `camelCase` for local variables and function names
|
|
- Use `_camelCase` for private/internal variables (PF1 system uses this convention)
|
|
- Use descriptive names that reveal intent
|
|
- Prefix boolean variables with `is`, `has`, `can`, or `should`
|
|
|
|
```javascript
|
|
// Good
|
|
const arcanePool = actor.system.resources.classFeat_arcanePool;
|
|
let selectedBuffs = [];
|
|
const isActive = buff.system.active;
|
|
const hasHasteBuff = actor.items.find(i => i.name === "Haste");
|
|
|
|
// Avoid
|
|
const ap = actor.system.resources.classFeat_arcanePool;
|
|
let x = [];
|
|
const flag = buff.system.active;
|
|
```
|
|
|
|
#### Classes & Interfaces
|
|
- Use `PascalCase` for classes and constructors
|
|
- Suffix with descriptive type (e.g., `Sheet`, `Application`, `Service`)
|
|
- Foundry documents often use a suffix (e.g., `ActorPF`, `ItemPF`)
|
|
|
|
```javascript
|
|
// Good
|
|
class ActorPF extends Actor { }
|
|
class CharacterSheetPF extends ActorSheet { }
|
|
class DicePoolBuilder { }
|
|
|
|
// Avoid
|
|
class actor { }
|
|
class sheet1 { }
|
|
```
|
|
|
|
#### Constants & Configuration
|
|
- Use `UPPER_SNAKE_CASE` for true constants
|
|
- Use `camelCase` for configuration objects
|
|
- Global CONFIG uses `UPPER_CASE` keys with nested objects
|
|
|
|
```javascript
|
|
// Good
|
|
const MAX_ARCANE_POOL = 10;
|
|
const config = { abilities: { str: "Strength" } };
|
|
CONFIG.PF1.abilities = { str: "STR", dex: "DEX" };
|
|
|
|
// Avoid
|
|
const maxarcanepool = 10;
|
|
const CONFIG = { abilities: { str: "Strength" } };
|
|
```
|
|
|
|
#### Files & Folders
|
|
- Use `kebab-case.mjs` for ES module files (PF1 system)
|
|
- Use `kebab-case.js` for CommonJS files (Foundry core)
|
|
- Use `descriptive_name.js` or `camelCase.js` for macro files
|
|
- Use `_module.mjs` for re-export aggregation files
|
|
|
|
```
|
|
actor-sheet.mjs # PF1 system module
|
|
game.js # Foundry core
|
|
macro_arcane_pool.js # Custom macro
|
|
_module.mjs # Re-export file
|
|
```
|
|
|
|
### Code Organization
|
|
|
|
#### File Size
|
|
- Keep files under 500 lines when possible
|
|
- Split large classes using mixins or composition
|
|
- Use `_module.mjs` files to aggregate related exports
|
|
|
|
#### Function Complexity
|
|
- Functions should do one thing well
|
|
- Keep functions under 50 lines when possible
|
|
- Maximum 5-6 parameters; use options objects for more
|
|
- Use async/await for all asynchronous operations
|
|
|
|
```javascript
|
|
// Good - focused function
|
|
async function applyArcanePoolBuff(actor, buffName, duration) {
|
|
const buff = actor.items.find(i => i.name === buffName);
|
|
if (!buff) return false;
|
|
|
|
await buff.update({
|
|
"system.active": true,
|
|
"system.duration.value": duration
|
|
});
|
|
|
|
return true;
|
|
}
|
|
|
|
// Avoid - doing too much
|
|
function processArcanePool(actor, buffName, duration, bonusType,
|
|
bonusAmount, target, options, callback) {
|
|
// 200+ lines of mixed concerns
|
|
}
|
|
```
|
|
|
|
#### Module Import Organization
|
|
Order imports in this sequence:
|
|
1. Foundry core imports
|
|
2. PF1 system imports
|
|
3. Utility imports
|
|
4. Local module imports
|
|
|
|
```javascript
|
|
// Good
|
|
import { ActorSheet } from "../../common/documents/actor.mjs";
|
|
import { CONFIG } from "../../common/config.mjs";
|
|
import { ActorPF } from "../documents/actor/entity.mjs";
|
|
import { applyBuff } from "../utils/buffs.mjs";
|
|
import { CharacterSheetHelper } from "./_helper.mjs";
|
|
|
|
// Avoid mixing import sources
|
|
```
|
|
|
|
### Comments & Documentation
|
|
|
|
#### When to Comment
|
|
- **DO**: Explain *why* something is done, especially workarounds
|
|
- **DO**: Document complex Pathfinder 1e rules implementation
|
|
- **DO**: Add TODOs with context: `// TODO: Support metamagic feats`
|
|
- **DO**: Explain Foundry API quirks or version-specific behavior
|
|
- **DON'T**: State the obvious
|
|
- **DON'T**: Leave commented-out code (use git history)
|
|
|
|
```javascript
|
|
// Good - explains why
|
|
// Using setTimeout to ensure Foundry's hook cycle completes
|
|
// before updating the actor. See Foundry issue #7234
|
|
setTimeout(() => actor.update(data), 0);
|
|
|
|
// Avoid - states the obvious
|
|
// Set arcane pool to 5
|
|
arcanePool.value = 5;
|
|
```
|
|
|
|
#### JSDoc Documentation
|
|
Document all public APIs, classes, and exported functions:
|
|
|
|
```javascript
|
|
/**
|
|
* Applies an Arcane Pool enhancement to a weapon
|
|
* @param {ActorPF} actor - The character using Arcane Pool
|
|
* @param {ItemPF} weapon - The weapon to enhance
|
|
* @param {number} bonus - Enhancement bonus (1-5)
|
|
* @param {string[]} abilities - Special abilities (e.g., "keen", "flaming")
|
|
* @returns {Promise<boolean>} True if successfully applied
|
|
* @example
|
|
* await applyArcanePoolEnhancement(actor, weapon, 2, ["keen"]);
|
|
*/
|
|
async function applyArcanePoolEnhancement(actor, weapon, bonus, abilities) {
|
|
// Implementation
|
|
}
|
|
```
|
|
|
|
### Error Handling
|
|
|
|
#### Strategy
|
|
- Use try-catch blocks for Foundry API calls that may fail
|
|
- Use `ui.notifications` for user-facing errors
|
|
- Log errors to console for debugging
|
|
- Never swallow errors silently
|
|
- Validate inputs early (fail fast)
|
|
|
|
```javascript
|
|
// Good
|
|
try {
|
|
if (!actor) {
|
|
ui.notifications.warn("You must select a token!");
|
|
return;
|
|
}
|
|
|
|
const result = await actor.update({"system.hp.value": newHP});
|
|
ui.notifications.info(`HP updated to ${newHP}`);
|
|
} catch (error) {
|
|
console.error("Failed to update HP:", error);
|
|
ui.notifications.error("Failed to update HP. Check console for details.");
|
|
}
|
|
|
|
// Avoid
|
|
try {
|
|
actor.update({"system.hp.value": newHP});
|
|
} catch (e) {
|
|
// Silent failure
|
|
}
|
|
```
|
|
|
|
### Performance Considerations
|
|
- Use `fromUuidSync()` instead of `fromUuid()` when possible (synchronous is faster)
|
|
- Cache actor/item lookups instead of repeated searches
|
|
- Batch document updates when updating multiple fields
|
|
- Use `actor.updateSource()` for preparation phase (before rendering)
|
|
- Avoid unnecessary re-renders in dialogs
|
|
|
|
```javascript
|
|
// Good - batch update
|
|
await actor.update({
|
|
"system.hp.value": newHP,
|
|
"system.resources.arcanePool.value": newPool,
|
|
"system.attributes.ac.total": newAC
|
|
});
|
|
|
|
// Avoid - multiple updates
|
|
await actor.update({"system.hp.value": newHP});
|
|
await actor.update({"system.resources.arcanePool.value": newPool});
|
|
await actor.update({"system.attributes.ac.total": newAC});
|
|
```
|
|
|
|
---
|
|
|
|
## Foundry VTT API Reference
|
|
|
|
### Official Documentation
|
|
|
|
**Primary API Documentation**: [Foundry VTT API v11](https://foundryvtt.com/api/v11/)
|
|
|
|
**Key API Modules**:
|
|
- **Documents**: [foundry.documents](https://foundryvtt.com/api/v11/modules/foundry.documents.html) - Actor, Item, ChatMessage, etc.
|
|
- **Client Classes**: [client](https://foundryvtt.com/api/v11/modules/client.html) - Game, Canvas, UI managers
|
|
- **Applications**: [client.applications](https://foundryvtt.com/api/v11/modules/client.applications.html) - FormApplication, Dialog
|
|
- **PIXI**: [pixi](https://foundryvtt.com/api/v11/modules/pixi.html) - Canvas rendering
|
|
- **Dice**: [client.dice](https://foundryvtt.com/api/v11/modules/client.dice.html) - Roll, DiceTerm
|
|
|
|
### Global Objects
|
|
|
|
Foundry VTT provides several global objects available in all scripts:
|
|
|
|
```javascript
|
|
// Core game instance
|
|
game // Main Game object
|
|
game.actors // Actor collection
|
|
game.items // Item collection
|
|
game.scenes // Scene collection
|
|
game.users // User collection
|
|
game.macros // Macro collection
|
|
game.settings // Settings registry
|
|
game.i18n // Localization
|
|
|
|
// UI managers
|
|
ui // UI manager
|
|
ui.notifications // Toast notifications
|
|
ui.chat // Chat sidebar
|
|
ui.combat // Combat tracker
|
|
ui.actors // Actor directory
|
|
ui.items // Item directory
|
|
|
|
// Canvas rendering
|
|
canvas // Canvas manager
|
|
canvas.tokens // Token layer
|
|
canvas.lighting // Lighting layer
|
|
canvas.walls // Walls layer
|
|
|
|
// Configuration
|
|
CONFIG // Global configuration object
|
|
CONFIG.Actor // Actor configuration
|
|
CONFIG.Item // Item configuration
|
|
CONFIG.PF1 // PF1 system configuration
|
|
|
|
// Utilities
|
|
Hooks // Hook system
|
|
fromUuid() // Get document by UUID
|
|
fromUuidSync() // Synchronous UUID lookup
|
|
```
|
|
|
|
### Common API Patterns
|
|
|
|
#### Document Access
|
|
```javascript
|
|
// Get by ID
|
|
const actor = game.actors.get(actorId);
|
|
const item = game.items.get(itemId);
|
|
|
|
// Get by name
|
|
const actor = game.actors.getName("Character Name");
|
|
const macro = game.macros.getName("Macro Name");
|
|
|
|
// Get by UUID
|
|
const doc = await fromUuid("Actor.abc123.Item.def456");
|
|
const doc = fromUuidSync("Actor.abc123.Item.def456"); // Faster, synchronous
|
|
|
|
// Search collection
|
|
const magus = game.actors.find(a => a.name === "Zeratal");
|
|
const hastes = game.items.filter(i => i.name.includes("Haste"));
|
|
```
|
|
|
|
#### Document Updates
|
|
```javascript
|
|
// Update single field
|
|
await actor.update({"system.hp.value": 50});
|
|
|
|
// Update multiple fields (preferred - single transaction)
|
|
await actor.update({
|
|
"system.hp.value": 50,
|
|
"system.attributes.ac.total": 25
|
|
});
|
|
|
|
// Update embedded documents (items)
|
|
await actor.updateEmbeddedDocuments("Item", [
|
|
{_id: itemId, "system.active": true}
|
|
]);
|
|
|
|
// Create embedded documents
|
|
await actor.createEmbeddedDocuments("Item", [itemData]);
|
|
|
|
// Delete embedded documents
|
|
await actor.deleteEmbeddedDocuments("Item", [itemId]);
|
|
```
|
|
|
|
#### Hooks System
|
|
```javascript
|
|
// One-time hooks (initialization)
|
|
Hooks.once("init", () => {
|
|
console.log("Foundry initializing...");
|
|
});
|
|
|
|
Hooks.once("ready", () => {
|
|
console.log("Foundry ready!");
|
|
});
|
|
|
|
// Recurring hooks
|
|
Hooks.on("updateActor", (actor, change, options, userId) => {
|
|
console.log(`${actor.name} was updated`);
|
|
});
|
|
|
|
Hooks.on("preCreateItem", (item, data, options, userId) => {
|
|
// Can modify data or return false to prevent
|
|
return true;
|
|
});
|
|
|
|
// Call custom hooks
|
|
Hooks.call("myCustomHook", arg1, arg2);
|
|
Hooks.callAll("myCustomHook", arg1, arg2);
|
|
```
|
|
|
|
#### Dialog API
|
|
```javascript
|
|
// Simple dialog
|
|
new Dialog({
|
|
title: "Dialog Title",
|
|
content: "<p>Dialog content HTML</p>",
|
|
buttons: {
|
|
yes: {
|
|
icon: '<i class="fas fa-check"></i>',
|
|
label: "Yes",
|
|
callback: (html) => {
|
|
console.log("Yes clicked");
|
|
}
|
|
},
|
|
no: {
|
|
icon: '<i class="fas fa-times"></i>',
|
|
label: "No"
|
|
}
|
|
},
|
|
default: "yes",
|
|
render: (html) => {
|
|
// Setup event listeners
|
|
html.find('.my-input').focus();
|
|
},
|
|
close: (html) => {
|
|
console.log("Dialog closed");
|
|
}
|
|
}).render(true);
|
|
```
|
|
|
|
#### Notifications
|
|
```javascript
|
|
// Toast notifications
|
|
ui.notifications.info("Information message");
|
|
ui.notifications.warn("Warning message");
|
|
ui.notifications.error("Error message");
|
|
|
|
// Persistent notification
|
|
ui.notifications.notify("Message", "info", {permanent: true});
|
|
```
|
|
|
|
#### Templates
|
|
```javascript
|
|
// Render template with data
|
|
const html = await renderTemplate(
|
|
"systems/pf1/templates/actors/character-sheet.hbs",
|
|
{ actor: actor, data: actor.system }
|
|
);
|
|
|
|
// Load template
|
|
const template = await getTemplate("path/to/template.hbs");
|
|
```
|
|
|
|
### PF1 System API
|
|
|
|
#### Actor API (ActorPF)
|
|
```javascript
|
|
// Access actor data
|
|
actor.system.attributes.hp.value // Current HP
|
|
actor.system.attributes.hp.max // Max HP
|
|
actor.system.attributes.ac.normal.total // AC
|
|
actor.system.resources.classFeat_arcanePool.value // Class resource
|
|
|
|
// Class information
|
|
actor.classes // Object of class items
|
|
actor.classes["magus"] // Specific class
|
|
actor.classes["magus"].level // Class level
|
|
|
|
// Buff management
|
|
const buffs = actor.items.filter(i => i.type === "buff");
|
|
const activeBuff = actor.items.find(i =>
|
|
i.type === "buff" &&
|
|
i.system.active &&
|
|
i.name === "Haste"
|
|
);
|
|
|
|
// Spellcasting
|
|
const spellbook = actor.system.spells.spellbooks.primary;
|
|
spellbook.spells.level1 // 1st level spells
|
|
```
|
|
|
|
#### Item API (ItemPF)
|
|
```javascript
|
|
// Access item data
|
|
item.system.active // Buff active state
|
|
item.system.duration.value // Duration remaining
|
|
item.system.enhancement // Enhancement bonus
|
|
|
|
// Item usage
|
|
await item.use(options); // Use item (attack, spell, etc.)
|
|
await item.roll(); // Roll item
|
|
|
|
// Item types
|
|
item.type === "weapon" // Weapon
|
|
item.type === "buff" // Buff/effect
|
|
item.type === "spell" // Spell
|
|
item.type === "feat" // Feat
|
|
item.type === "class" // Class
|
|
```
|
|
|
|
#### Configuration (pf1.config)
|
|
```javascript
|
|
// Access PF1 configuration
|
|
pf1.config.abilities // Ability scores
|
|
pf1.config.skills // Skills
|
|
pf1.config.alignments // Alignments
|
|
pf1.config.saves // Saving throws
|
|
pf1.config.buffTargets // Buff target types
|
|
pf1.config.bonusTypes // Bonus types
|
|
|
|
// Via CONFIG global
|
|
CONFIG.PF1.abilities // Same as pf1.config.abilities
|
|
```
|
|
|
|
---
|
|
|
|
## Macro Development Patterns
|
|
|
|
### Basic Macro Structure
|
|
|
|
All macros should follow this IIFE (Immediately Invoked Function Expression) pattern:
|
|
|
|
```javascript
|
|
(async () => {
|
|
// 1. Validation - check prerequisites
|
|
if (!token) {
|
|
ui.notifications.warn("You must select a token!");
|
|
return;
|
|
}
|
|
|
|
if (!actor) {
|
|
ui.notifications.warn("Selected token has no actor!");
|
|
return;
|
|
}
|
|
|
|
// 2. Data access - get required data
|
|
const arcanePool = actor.system.resources.classFeat_arcanePool;
|
|
const magusLevel = actor.classes["magus"]?.level || 0;
|
|
|
|
// 3. Business logic - main macro functionality
|
|
async function doSomething() {
|
|
// Implementation
|
|
}
|
|
|
|
// 4. Execution
|
|
await doSomething();
|
|
|
|
// 5. User feedback
|
|
ui.notifications.info("Macro completed successfully!");
|
|
})();
|
|
```
|
|
|
|
### Dialog-Based Macros
|
|
|
|
For complex user interactions, use the Dialog API:
|
|
|
|
```javascript
|
|
(async () => {
|
|
// Validation
|
|
if (!token) {
|
|
ui.notifications.warn("You must select a token!");
|
|
return;
|
|
}
|
|
|
|
const actor = token.actor;
|
|
|
|
// Define dialog function
|
|
function showDialog() {
|
|
// Build HTML content with inline styles
|
|
const dialogContent = `
|
|
<html>
|
|
<head>
|
|
<style>
|
|
.macro-dialog { padding: 10px; }
|
|
.macro-option { margin: 5px 0; }
|
|
.macro-button {
|
|
padding: 5px 10px;
|
|
margin: 2px;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="macro-dialog">
|
|
<h3>Select Options</h3>
|
|
<div class="macro-option">
|
|
<label>
|
|
<input type="checkbox" name="option1" value="keen">
|
|
Keen
|
|
</label>
|
|
</div>
|
|
<div class="macro-option">
|
|
<label>
|
|
<input type="checkbox" name="option2" value="flaming">
|
|
Flaming
|
|
</label>
|
|
</div>
|
|
<div class="macro-option">
|
|
<label>Bonus:
|
|
<select name="bonus">
|
|
<option value="1">+1</option>
|
|
<option value="2">+2</option>
|
|
<option value="3">+3</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
// Create dialog
|
|
new Dialog({
|
|
title: "Macro Dialog",
|
|
content: dialogContent,
|
|
buttons: {
|
|
confirm: {
|
|
icon: '<i class="fas fa-check"></i>',
|
|
label: "Confirm",
|
|
callback: async (html) => {
|
|
// Extract user selections
|
|
const selectedOptions = [];
|
|
html.find('input[type="checkbox"]:checked').each(function() {
|
|
selectedOptions.push($(this).val());
|
|
});
|
|
|
|
const bonus = parseInt(html.find('select[name="bonus"]').val());
|
|
|
|
// Process selections
|
|
await processSelection(selectedOptions, bonus);
|
|
|
|
ui.notifications.info("Macro applied successfully!");
|
|
}
|
|
},
|
|
cancel: {
|
|
icon: '<i class="fas fa-times"></i>',
|
|
label: "Cancel"
|
|
}
|
|
},
|
|
render: (html) => {
|
|
// Setup dynamic event handlers
|
|
html.find('input[type="checkbox"]').on('change', function() {
|
|
updatePreview(html);
|
|
});
|
|
}
|
|
}).render(true);
|
|
}
|
|
|
|
// Helper functions
|
|
async function processSelection(options, bonus) {
|
|
// Implementation
|
|
}
|
|
|
|
function updatePreview(html) {
|
|
// Update UI based on selections
|
|
}
|
|
|
|
// Execute
|
|
showDialog();
|
|
})();
|
|
```
|
|
|
|
### Macro Chaining
|
|
|
|
Call other macros from within a macro:
|
|
|
|
```javascript
|
|
(async () => {
|
|
// Get macro by name
|
|
const buffMacro = game.macros.getName("_applyBuff");
|
|
|
|
if (!buffMacro) {
|
|
ui.notifications.error("Required macro '_applyBuff' not found!");
|
|
return;
|
|
}
|
|
|
|
// Execute macro with arguments
|
|
await buffMacro.execute({
|
|
actorId: actor.id,
|
|
buffName: "Haste",
|
|
duration: 5,
|
|
active: true
|
|
});
|
|
|
|
// Continue with other logic
|
|
ui.notifications.info("Buff applied!");
|
|
})();
|
|
```
|
|
|
|
### Buff Management Pattern
|
|
|
|
```javascript
|
|
(async () => {
|
|
const actor = token.actor;
|
|
const buffName = "Haste";
|
|
|
|
// Find buff on actor
|
|
const buff = actor.items.find(i =>
|
|
i.type === "buff" &&
|
|
i.name === buffName
|
|
);
|
|
|
|
if (!buff) {
|
|
ui.notifications.warn(`Buff "${buffName}" not found on ${actor.name}!`);
|
|
return;
|
|
}
|
|
|
|
// Toggle buff
|
|
const newState = !buff.system.active;
|
|
await buff.update({
|
|
"system.active": newState,
|
|
"system.duration.value": newState ? 5 : 0
|
|
});
|
|
|
|
ui.notifications.info(
|
|
`${buffName} ${newState ? "activated" : "deactivated"} on ${actor.name}`
|
|
);
|
|
})();
|
|
```
|
|
|
|
### Hook Interception Pattern
|
|
|
|
For advanced macros that intercept game events:
|
|
|
|
```javascript
|
|
(async () => {
|
|
// Register a temporary hook
|
|
const hookId = Hooks.on("pf1.itemRoll", (item, options) => {
|
|
// Check if this is the right item
|
|
if (item.type !== "weapon") return;
|
|
|
|
// Check if actor has Haste buff
|
|
const hasHaste = item.actor.items.find(i =>
|
|
i.type === "buff" &&
|
|
i.name === "Haste" &&
|
|
i.system.active
|
|
);
|
|
|
|
if (!hasHaste) return;
|
|
|
|
// Modify roll options
|
|
options.extraAttacks = (options.extraAttacks || 0) + 1;
|
|
ui.notifications.info("Haste: Added extra attack!");
|
|
});
|
|
|
|
// Clean up hook after some time or condition
|
|
setTimeout(() => {
|
|
Hooks.off("pf1.itemRoll", hookId);
|
|
}, 60000); // Remove after 1 minute
|
|
})();
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
### Foundry VTT Configuration
|
|
|
|
#### System Manifest (system.json)
|
|
|
|
Located at: [system.json](src/foundryvtt-pathfinder1-v10.8/public/system.json)
|
|
|
|
```json
|
|
{
|
|
"id": "pf1",
|
|
"title": "Pathfinder 1e",
|
|
"description": "The Pathfinder First Edition game system for Foundry VTT",
|
|
"version": "10.8",
|
|
"compatibility": {
|
|
"minimum": "11",
|
|
"verified": "11",
|
|
"maximum": "11"
|
|
},
|
|
"esmodules": ["pf1.js"],
|
|
"styles": ["pf1.css"],
|
|
"packs": [
|
|
{
|
|
"name": "classes",
|
|
"label": "Classes",
|
|
"type": "Item",
|
|
"system": "pf1"
|
|
}
|
|
// ... more compendium packs
|
|
],
|
|
"languages": [
|
|
{
|
|
"lang": "en",
|
|
"name": "English",
|
|
"path": "lang/en.json"
|
|
}
|
|
// ... more languages
|
|
],
|
|
"socket": true,
|
|
"initiative": "1d20 + @attributes.init.total + (@attributes.init.total / 100)"
|
|
}
|
|
```
|
|
|
|
**Key Fields**:
|
|
- `id`: System identifier (must be unique)
|
|
- `esmodules`: JavaScript entry points (loaded as ES modules)
|
|
- `styles`: CSS stylesheets to load
|
|
- `packs`: Compendium packs (pre-packaged content)
|
|
- `languages`: Localization files
|
|
- `socket`: Enable socket communication for multiplayer
|
|
- `initiative`: Formula for initiative rolls
|
|
|
|
### PF1 System Configuration
|
|
|
|
#### Development Scripts
|
|
|
|
```bash
|
|
# Build for production
|
|
npm run build
|
|
|
|
# Development build with watch mode
|
|
npm run build:watch
|
|
|
|
# Extract compendium packs to JSON
|
|
npm run packs:extract
|
|
|
|
# Compile JSON to compendium packs
|
|
npm run packs:compile
|
|
|
|
# Lint code
|
|
npm run lint
|
|
|
|
# Format code
|
|
npm run format
|
|
|
|
# Generate documentation
|
|
npm run docs
|
|
```
|
|
|
|
#### ESLint Configuration (.eslintrc.js)
|
|
|
|
```javascript
|
|
module.exports = {
|
|
env: {
|
|
browser: true,
|
|
es2021: true,
|
|
jquery: true
|
|
},
|
|
extends: [
|
|
"eslint:recommended",
|
|
"plugin:prettier/recommended"
|
|
],
|
|
parserOptions: {
|
|
ecmaVersion: 2022,
|
|
sourceType: "module"
|
|
},
|
|
globals: {
|
|
game: "readonly",
|
|
ui: "readonly",
|
|
canvas: "readonly",
|
|
CONFIG: "readonly",
|
|
Hooks: "readonly",
|
|
foundry: "readonly",
|
|
Actor: "readonly",
|
|
Item: "readonly"
|
|
},
|
|
rules: {
|
|
"no-unused-vars": ["warn", {
|
|
argsIgnorePattern: "^_",
|
|
varsIgnorePattern: "^_"
|
|
}]
|
|
}
|
|
};
|
|
```
|
|
|
|
#### Prettier Configuration (.prettierrc.json)
|
|
|
|
```json
|
|
{
|
|
"printWidth": 120,
|
|
"tabWidth": 2,
|
|
"useTabs": false,
|
|
"semi": true,
|
|
"singleQuote": false,
|
|
"trailingComma": "es5",
|
|
"bracketSpacing": true,
|
|
"arrowParens": "always"
|
|
}
|
|
```
|
|
|
|
### Claude Code Configuration
|
|
|
|
#### MCP Servers (.mcp.json)
|
|
|
|
The project uses 8 MCP servers for AI-assisted development:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"serena": {
|
|
"description": "Code navigation, symbol search, and project memory",
|
|
"capabilities": ["semantic search", "symbol manipulation", "memory"]
|
|
},
|
|
"sequential-thinking": {
|
|
"description": "Complex problem decomposition and reasoning"
|
|
},
|
|
"context7": {
|
|
"description": "Up-to-date library documentation retrieval"
|
|
},
|
|
"memory": {
|
|
"description": "Knowledge graph for persistent context"
|
|
},
|
|
"fetch": {
|
|
"description": "Web content retrieval and scraping"
|
|
},
|
|
"windows-mcp": {
|
|
"description": "Windows desktop automation and interaction"
|
|
},
|
|
"playwright": {
|
|
"description": "Browser automation and testing"
|
|
},
|
|
"database-server": {
|
|
"description": "SQL Server database access"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Claude Settings
|
|
|
|
- **Agents**: 8 specialized AI agents in [.claude/agents/](.claude/agents/)
|
|
- **Commands**: 9 custom slash commands in [.claude/commands/](.claude/commands/)
|
|
- **Output Styles**: 6 formatting styles in [.claude/output-styles/](.claude/output-styles/)
|
|
|
|
---
|
|
|
|
## Running the Application
|
|
|
|
### Prerequisites
|
|
- Foundry VTT installed (v11.315 recommended)
|
|
- Node.js v16-19 (for PF1 system development)
|
|
- npm (Node Package Manager)
|
|
- Visual Studio Code (recommended IDE)
|
|
|
|
### Initial Setup
|
|
|
|
```bash
|
|
# Navigate to project root
|
|
cd "C:\DEV\Foundry"
|
|
|
|
# Install PF1 system dependencies (if developing system)
|
|
cd src/foundryvtt-pathfinder1-v10.8
|
|
npm install
|
|
|
|
# Build PF1 system
|
|
npm run build
|
|
|
|
# Or use watch mode for development
|
|
npm run build:watch
|
|
```
|
|
|
|
### Running Foundry VTT
|
|
|
|
#### Option 1: Run Electron Application
|
|
```bash
|
|
# Navigate to Foundry directory
|
|
cd "C:\DEV\Foundry\src\FoundryVTT-11.315"
|
|
|
|
# Run Foundry (Windows)
|
|
.\foundryvtt.exe
|
|
|
|
# Or run via Node.js
|
|
node resources/app/main.js
|
|
```
|
|
|
|
#### Option 2: Launch from Start Menu/Desktop
|
|
- Double-click Foundry VTT shortcut
|
|
- Or launch from Windows Start Menu
|
|
|
|
### Accessing the Application
|
|
|
|
Once Foundry VTT is running:
|
|
1. **Setup Screen**: First launch shows setup page
|
|
2. **Select World**: Choose or create a world
|
|
3. **Launch World**: Click "Launch World"
|
|
4. **Login**: Enter game master password (if set)
|
|
|
|
### Creating/Using Macros
|
|
|
|
#### Import Macro from File
|
|
1. Open Foundry VTT
|
|
2. Click "Macro Directory" in sidebar
|
|
3. Click "Create Macro" button
|
|
4. Set macro type to "Script"
|
|
5. Copy content from [macro.js](src/macro.js) or [macro_haste.js](src/macro_haste.js)
|
|
6. Paste into macro editor
|
|
7. Save macro
|
|
8. Drag to hotbar for quick access
|
|
|
|
#### Testing Macros
|
|
1. Select a token on the canvas
|
|
2. Click macro from hotbar
|
|
3. Follow dialog prompts
|
|
4. Check console (F12) for errors/logs
|
|
|
|
### Development Workflow
|
|
|
|
```bash
|
|
# 1. Make changes to PF1 system or macros
|
|
# Edit files in src/foundryvtt-pathfinder1-v10.8/module/
|
|
|
|
# 2. Build system (if modified system code)
|
|
cd src/foundryvtt-pathfinder1-v10.8
|
|
npm run build:watch # Auto-rebuilds on changes
|
|
|
|
# 3. Reload Foundry
|
|
# Press F5 in Foundry VTT to reload
|
|
|
|
# 4. Test changes
|
|
# Execute macros or test system features
|
|
|
|
# 5. Check for issues
|
|
# Open browser console (F12) for errors
|
|
|
|
# 6. Format code before committing
|
|
npm run format
|
|
npm run lint
|
|
|
|
# 7. Commit changes
|
|
git add .
|
|
git commit -m "feat: add new macro feature"
|
|
```
|
|
|
|
---
|
|
|
|
## Testing Requirements
|
|
|
|
### Manual Testing
|
|
|
|
For macro development:
|
|
1. **Token Selection**: Ensure macro validates token selection
|
|
2. **Actor Data**: Verify correct actor data access
|
|
3. **Dialog UI**: Test all dialog buttons and inputs
|
|
4. **Error Handling**: Test with invalid inputs
|
|
5. **User Feedback**: Verify notifications display correctly
|
|
6. **Edge Cases**: Test with missing items, zero resources, etc.
|
|
|
|
### Console Debugging
|
|
|
|
```javascript
|
|
// Add debug logging to macros
|
|
(async () => {
|
|
console.log("=== Macro Start ===");
|
|
console.log("Token:", token);
|
|
console.log("Actor:", actor);
|
|
console.log("Actor Data:", actor.system);
|
|
|
|
try {
|
|
// Macro logic
|
|
} catch (error) {
|
|
console.error("Macro Error:", error);
|
|
ui.notifications.error(`Error: ${error.message}`);
|
|
}
|
|
|
|
console.log("=== Macro End ===");
|
|
})();
|
|
```
|
|
|
|
### PF1 System Testing
|
|
|
|
The PF1 system uses Quench for unit testing:
|
|
|
|
```bash
|
|
# Run tests (in Foundry VTT console)
|
|
quench.runAll();
|
|
|
|
# Or access test UI
|
|
# Game Settings > System Settings > Test Runner
|
|
```
|
|
|
|
### Browser Console Access
|
|
|
|
- Press **F12** to open browser developer tools
|
|
- Use **Console** tab for logs and errors
|
|
- Use **Network** tab for API call debugging
|
|
- Use **Elements** tab for DOM inspection
|
|
|
|
---
|
|
|
|
## Git & Version Control
|
|
|
|
### Commit Message Format
|
|
|
|
Follow the Conventional Commits specification:
|
|
|
|
```
|
|
<type>(<scope>): <subject>
|
|
|
|
<body>
|
|
|
|
<footer>
|
|
```
|
|
|
|
#### Types
|
|
- **feat**: New feature (macro, system enhancement)
|
|
- **fix**: Bug fix
|
|
- **docs**: Documentation changes
|
|
- **refactor**: Code refactoring
|
|
- **test**: Adding or updating tests
|
|
- **chore**: Maintenance tasks
|
|
- **style**: Code style changes (formatting)
|
|
|
|
#### Scopes
|
|
- **macro**: Macro development
|
|
- **system**: PF1 system changes
|
|
- **core**: Foundry core modifications
|
|
- **config**: Configuration changes
|
|
- **docs**: Documentation
|
|
|
|
#### Examples
|
|
|
|
```bash
|
|
# New macro
|
|
feat(macro): add arcane pool enhancement UI
|
|
|
|
# Bug fix
|
|
fix(macro): correct haste buff duration calculation
|
|
|
|
# Documentation
|
|
docs(readme): update macro installation instructions
|
|
|
|
# Refactoring
|
|
refactor(macro): extract dialog HTML to separate function
|
|
|
|
# System enhancement
|
|
feat(system): add support for mythic rules
|
|
```
|
|
|
|
### Branching Strategy
|
|
|
|
```bash
|
|
# Main branch for stable code
|
|
main
|
|
|
|
# Feature branches
|
|
feature/arcane-pool-macro
|
|
feature/haste-automation
|
|
|
|
# Bug fix branches
|
|
fix/dialog-validation
|
|
|
|
# Create feature branch
|
|
git checkout -b feature/new-macro
|
|
|
|
# Commit changes
|
|
git add src/macro_new.js
|
|
git commit -m "feat(macro): add new macro feature"
|
|
|
|
# Merge to main
|
|
git checkout main
|
|
git merge feature/new-macro
|
|
```
|
|
|
|
### Ignoring Files
|
|
|
|
The `.gitignore` should exclude:
|
|
```
|
|
# Foundry user data
|
|
src/FoundryVTT-11.315/Data/
|
|
|
|
# Node modules
|
|
node_modules/
|
|
|
|
# Build artifacts
|
|
dist/
|
|
*.log
|
|
|
|
# OS files
|
|
.DS_Store
|
|
Thumbs.db
|
|
|
|
# IDE files
|
|
.vscode/
|
|
.idea/
|
|
|
|
# Temporary files
|
|
*.tmp
|
|
*.bak
|
|
```
|
|
|
|
---
|
|
|
|
## Claude Code Specific Instructions
|
|
|
|
### Mandatory Tooling Usage Policy
|
|
|
|
**CRITICAL**: Claude Code must maximize the use of available advanced features for efficiency and quality:
|
|
|
|
#### 🎯 Agent Usage (REQUIRED)
|
|
- **ALWAYS** consider using specialized agents for their intended tasks:
|
|
- `Explore` agent: For codebase exploration, file pattern searches, keyword searches
|
|
- `test-engineer`: For generating test suites
|
|
- `code-reviewer`: For code quality reviews
|
|
- `refactoring-specialist`: For code cleanup
|
|
- `debugger`: For systematic bug diagnosis
|
|
- `architect`: For system design planning
|
|
- `documentation-writer`: For comprehensive documentation
|
|
- `security-analyst`: For security reviews
|
|
|
|
- **When NOT to use agents**:
|
|
- Single file reads with known path
|
|
- Simple edits to existing macros
|
|
- Tasks completable in 1-2 tool calls
|
|
|
|
**IF YOU DECIDE NOT TO USE AN AGENT**: State explicitly at the beginning:
|
|
```
|
|
🔧 Agent Decision: Not using agents because [reason: e.g., "single file edit", "straightforward macro modification"]
|
|
```
|
|
|
|
#### ⚡ Slash Command Usage (REQUIRED)
|
|
- **ALWAYS** check available slash commands before starting tasks
|
|
- Use custom commands when applicable:
|
|
- `/test [file]`: Generate tests
|
|
- `/review [file]`: Code review
|
|
- `/explain [file]`: Explain code
|
|
- `/analyze [path]`: Code analysis
|
|
- `/scaffold [type]`: Generate boilerplate
|
|
|
|
**IF YOU DECIDE NOT TO USE SLASH COMMANDS**: State explicitly:
|
|
```
|
|
🔧 Slash Command Decision: Not using slash commands because [reason]
|
|
```
|
|
|
|
#### 🔌 MCP Server Usage (REQUIRED)
|
|
- **ALWAYS** leverage MCP servers:
|
|
- `serena`: Semantic code search, symbol manipulation
|
|
- `context7`: Library documentation (Foundry VTT, PIXI.js)
|
|
- `fetch`: Web content retrieval
|
|
- `sequential-thinking`: Complex reasoning
|
|
- `memory`: Knowledge graph
|
|
- `playwright`: Browser automation
|
|
- `windows-mcp`: Desktop interaction
|
|
|
|
**IF YOU DECIDE NOT TO USE MCP SERVERS**: State explicitly:
|
|
```
|
|
🔧 MCP Server Decision: Not using MCP servers because [reason]
|
|
```
|
|
|
|
### When Working with This Project
|
|
|
|
Claude should:
|
|
- ✅ **ALWAYS** provide tooling decision statements at the start of each task
|
|
- ✅ Follow Foundry VTT API best practices
|
|
- ✅ Use async/await for all asynchronous operations
|
|
- ✅ Validate user input in macros (token selection, actor data)
|
|
- ✅ Use `ui.notifications` for user feedback
|
|
- ✅ Add console logging for debugging
|
|
- ✅ Use jQuery for DOM manipulation in dialogs
|
|
- ✅ Follow the IIFE pattern for macros
|
|
- ✅ Test macros with actual Foundry VTT instance
|
|
- ✅ Document complex Pathfinder 1e rules implementation
|
|
- ✅ Handle API errors gracefully
|
|
- ✅ Use parallel tool calls for efficiency
|
|
- ✅ Leverage specialized agents and MCP servers
|
|
|
|
### Important Project Context
|
|
|
|
**Critical Files to Understand**:
|
|
- [foundry.js](src/FoundryVTT-11.315/resources/app/public/scripts/foundry.js) - Bundled Foundry client (large, avoid reading directly)
|
|
- [config.mjs](src/foundryvtt-pathfinder1-v10.8/module/config.mjs) - PF1 system configuration
|
|
- [system.json](src/foundryvtt-pathfinder1-v10.8/public/system.json) - System manifest
|
|
- [macro.js](src/macro.js) - Arcane Pool macro example
|
|
- [macro_haste.js](src/macro_haste.js) - Haste automation example
|
|
- [zeratal.json](src/zeratal.json) - Test character data
|
|
|
|
**API Documentation**:
|
|
- **Official Foundry API**: https://foundryvtt.com/api/v11/
|
|
- **Documents Module**: https://foundryvtt.com/api/v11/modules/foundry.documents.html
|
|
|
|
**Common Tasks**:
|
|
1. **Creating a new macro**: Follow IIFE pattern, validate inputs, use Dialog API
|
|
2. **Debugging macros**: Add console.log statements, check browser console (F12)
|
|
3. **Modifying PF1 system**: Edit files in `module/`, run `npm run build:watch`
|
|
4. **Testing changes**: Reload Foundry (F5), execute macro, check console
|
|
|
|
**Project-Specific Patterns**:
|
|
- All macros use IIFE: `(async () => { /* code */ })();`
|
|
- Dialog HTML includes inline CSS for styling
|
|
- Buff management via `actor.items.find(i => i.type === "buff")`
|
|
- Resource access via `actor.system.resources.*`
|
|
- Macro chaining via `game.macros.getName("MacroName")`
|
|
- Notifications via `ui.notifications.[info|warn|error]()`
|
|
|
|
---
|
|
|
|
## Task Initiation Requirements
|
|
|
|
**MANDATORY**: At the START of EVERY task response, provide:
|
|
|
|
### 🎯 Tooling Strategy Decision
|
|
|
|
**Task Analysis**: [Brief description of the task]
|
|
|
|
**Tooling Decisions**:
|
|
- **Agents**: Using [agent-name] / Not using - Reason: [specific justification]
|
|
- **Slash Commands**: Using [/command] / Not using - Reason: [specific justification]
|
|
- **MCP Servers**: Using [server: tool] / Not using - Reason: [specific justification]
|
|
- **Approach**: [Overall strategy for completing the task]
|
|
|
|
---
|
|
|
|
## Task Completion Status Messages
|
|
|
|
**IMPORTANT**: At the end of EVERY response where you performed work, provide:
|
|
|
|
### 📊 Task Completion Summary
|
|
|
|
**What Was Done**: [Brief description of tasks completed]
|
|
|
|
**Features Involved**:
|
|
- Agents: [Agent1, Agent2, or None - with usage justification]
|
|
- Slash Commands: [/command1, /command2, or None - with usage justification]
|
|
- MCP Servers: [Server1: tool1/tool2, Server2: tool3, or None - with usage justification]
|
|
- Core Tools: [Read, Write, Edit, Glob, Grep, Bash, WebFetch, WebSearch, Task]
|
|
- Files Modified: [file1.js, file2.mjs, or None]
|
|
- Performance: [Parallel ops, extended thinking, or N/A]
|
|
|
|
**Efficiency Notes**: [Any observations about tooling choices and their impact]
|
|
|
|
---
|
|
|
|
## Additional Resources
|
|
|
|
### Documentation
|
|
- **Foundry VTT Knowledge Base**: https://foundryvtt.com/kb/
|
|
- **Foundry VTT API v11**: https://foundryvtt.com/api/v11/
|
|
- **Foundry Documents**: https://foundryvtt.com/api/v11/modules/foundry.documents.html
|
|
- **PF1 System GitHub**: https://github.com/Furyspark/foundryvtt-pathfinder1
|
|
- **PIXI.js Documentation**: https://pixijs.com/
|
|
|
|
### Community
|
|
- **Foundry VTT Discord**: https://discord.gg/foundryvtt
|
|
- **Foundry VTT Reddit**: https://reddit.com/r/FoundryVTT
|
|
- **PF1 System Issues**: https://github.com/Furyspark/foundryvtt-pathfinder1/issues
|
|
|
|
### Troubleshooting
|
|
- **Browser Console**: Press F12 to access developer tools
|
|
- **Foundry Logs**: Check logs in `Data/Logs/` directory
|
|
- **Module Conflicts**: Disable modules to isolate issues
|
|
- **Cache Issues**: Clear browser cache or Foundry cache
|
|
|
|
---
|
|
|
|
## Contact & Support
|
|
|
|
**Maintainers**:
|
|
- Development Team
|
|
|
|
**Getting Help**:
|
|
1. Check browser console (F12) for errors
|
|
2. Review Foundry VTT API documentation
|
|
3. Consult PF1 system GitHub issues
|
|
4. Ask in Foundry VTT Discord community
|
|
|
|
---
|
|
|
|
**Last Updated**: 2025-01-29
|
|
**Project Version**: 1.0.0
|
|
**Foundry VTT Version**: v11.315
|
|
**PF1 System Version**: v10.8
|