ワンクリックで
implementation-guide
Step-by-step workflows for adding new item types, mechanics, compendium entries, and features from planning to code.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Step-by-step workflows for adding new item types, mechanics, compendium entries, and features from planning to code.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Look up how the legacy D35E Foundry system stores mechanics. Use when writing migration scripts, designing dnd35e field equivalents, checking actor data paths (abilities, HP, saves, BAB, AC, skills), item type schemas (weapon, buff, spell, class, equipment), or understanding the changes[] modification template. System ID is D35E (all caps).
Look up planning phases, track progress, and understand phase dependencies. Find which phase covers a feature or system.
Compare D35E (legacy Foundry system), dnd5e, and PF2e implementations side-by-side. Use when deciding data structure for a new item type, comparing buff/AE/RuleElement approaches, checking HP/saves/BAB/AC paths across systems, reviewing condition implementations, or understanding why dnd35e chose a particular design over the D35E approach.
Look up raw D&D 3.5e SRD rules as written. Use when asked about spells (Fireball, Cure Moderate Wounds), feats (prerequisites, Power Attack), conditions (Stunned, Prone, Grappled), combat mechanics (iterative attacks, AoO, grapple, two-weapon fighting), saving throw DCs, or any rules-as-written question. Searches local SRD journal and d20srd.org.
Analyze, improve, and maintain phase planning documentation. Use when: consolidating redundant sections, reorganizing phase structure, updating checklists, moving deferred work, adding cross-references, or improving decision frameworks.
Look up Foundry VTT API, data structures, and patterns. Find classes, methods, events, and configuration options.
| name | implementation-guide |
| description | Step-by-step workflows for adding new item types, mechanics, compendium entries, and features from planning to code. |
Ask questions like:
This skill helps you:
File: src/module/system/item/data-models.mjs or equivalent
import { ItemDataModel } from './_item-data-model.mjs';
import { FormulaFamiliar } from '...fields/index.mjs';
class SpecialWeapon extends ItemDataModel {
static defineSchema() {
return foundry.utils.mergeObject(super.defineSchema(), {
// Add custom properties
properties: new SchemaField({
specialAbility: new StringField({ initial: 'none' }),
saveDC: new NumberField({ min: 0, initial: 10 }),
specialEffect: new FormulaFamiliar({ label: "Effect Formula" }),
}),
});
}
// Optional: computed properties
get effectiveSpecialAbility() {
return this.properties.specialAbility;
}
}
Checklist:
defineSchema() call super firstFormulaFamiliarinitial or required: falseFile: system.json or type registration code
// If using system.json (Phase 4)
{
"Item": {
"types": ["weapon", "specialWeapon"], // Add new type
"specialized": {
"specialWeapon": {
"class": "SpecialWeapon",
"dataModel": "SpecialWeapon"
}
}
}
}
// Or dynamic registration
CONFIG.Item.documentClass.register('specialWeapon', SpecialWeapon);
File: src/vue/sheets/item/special-weapon-sheet.vue
<script setup>
import ItemSheetBase from './item-sheet-base.vue';
import FormGroupSection from '../../form/form-group-section.vue';
import StringFormGroup from '../../form/string-form-group.vue';
import NumberFormGroup from '../../form/number-form-group.vue';
import FormulaFormGroup from '../../form/formula-form-group.vue';
defineProps({ documentSheet: Object });
const emit = defineEmits(['update']);
const handleUpdate = (path, value) => {
emit('update', { [path]: value });
};
</script>
<template>
<ItemSheetBase :document-sheet="documentSheet">
<FormGroupSection label="Special Abilities" field-path="system.properties">
<StringFormGroup
label="Ability"
:value="documentSheet.system.properties.specialAbility"
field-path="system.properties.specialAbility"
@update="(val) => handleUpdate('system.properties.specialAbility', val)"
/>
<NumberFormGroup
label="Save DC"
:value="documentSheet.system.properties.saveDC"
field-path="system.properties.saveDC"
:min="0"
@update="(val) => handleUpdate('system.properties.saveDC', val)"
/>
<FormulaFormGroup
label="Effect"
:value="documentSheet.system.properties.specialEffect"
field-path="system.properties.specialEffect"
@update="(val) => handleUpdate('system.properties.specialEffect', val)"
/>
</FormGroupSection>
</ItemSheetBase>
</template>
Checklist:
File: packs/items-special-weapons.json or database pack
[
{
"_id": "special-weapon-01",
"name": "Frost Blade",
"type": "specialWeapon",
"data": {
"properties": {
"specialAbility": "frost",
"saveDC": 15,
"specialEffect": "2d6 + #context.enhancement"
}
}
}
]
Or import via script:
const item = await Item.create({
name: "Frost Blade",
type: "specialWeapon",
system: {
properties: {
specialAbility: "frost",
saveDC: 15,
specialEffect: "2d6 + #context.enhancement" // #context.X syntax resolves from evaluation scope
}
}
});
// Add to compendium pack
await game.packs.get('dnd35e.items-special-weapons').importDocument(item);
Checklist:
// Test: Can create item of new type
const item = await Item.create({
name: "Test",
type: "specialWeapon"
});
// Test: Can access schema fields
console.assert(item.system.properties.specialAbility !== undefined);
// Test: Can update fields
await item.update({ 'system.properties.specialAbility': 'fire' });
// Test: Sheet renders
item.sheet.render(true);
// Test: Formulas evaluate
const scope = { enhancement: 1 };
const result = await item.system.formula('properties.specialEffect', scope);
console.assert(result > 0);
Document what "Defensive Stance" does:
Option A: Active Effect (Simple, reusable)
// Already built-in, GM just creates AE with changes
// changes: [{ key: "system.defense.base", mode: "ADD", value: 2 }]
Option B: Character Sheet Toggle (Complex, custom logic)
// Add to actor schema
class Character extends ActorDataModel {
static defineSchema() {
return {
defenses: new SchemaField({
defensiveStance: new BooleanField({ initial: false })
})
};
}
// Get AC bonus from stance
get defensiveStanceBonus() {
return this.defenses.defensiveStance ? 2 : 0;
}
}
Option C: Feat or Feature (Role-based)
// Add to item type "Feature"
// "Defensive Stance" replaces the feature name
// Feature grants active effect via component chain
Add to actor data model if not in Option A:
class Character extends ActorDataModel {
static defineSchema() {
return foundry.utils.mergeObject(super.defineSchema(), {
defenses: new SchemaField({
defensiveStance: new BooleanField({ initial: false }),
}),
});
}
}
<script setup>
import FormGroupSection from '../../form/form-group-section.vue';
import ToggleFormGroup from '../../form/toggle-form-group.vue';
const emit = defineEmits(['update']);
</script>
<template>
<FormGroupSection label="Defenses" field-path="system.defenses">
<ToggleFormGroup
label="Defensive Stance"
:value="character.system.defenses.defensiveStance"
field-path="system.defenses.defensiveStance"
@update="(val) => emit('update', { 'system.defenses.defensiveStance': val })"
/>
</FormGroupSection>
</template>
// In ActorDataModel
get totalAC() {
const base = this.ac.base || 10;
const defensiveBonus = this.defenses.defensiveStance ? 2 : 0;
const aoeBonus = this.getActiveEffectBonus('ac');
return base + defensiveBonus + aoeBonus;
}
// Or in getter if it's computed during render
get acBonuses() {
return {
base: this.ac.base,
defensive: this.defenses.defensiveStance ? 2 : 0,
effects: this.getActiveEffectBonus('ac'),
};
}
// Create test actor
const actor = await Actor.create({ name: "Test", type: "character" });
// Test: Can toggle stance
await actor.update({ 'system.defenses.defensiveStance': true });
console.assert(actor.system.defenses.defensiveStance === true);
// Test: AC changes
const baseAC = actor.totalAC;
await actor.update({ 'system.defenses.defensiveStance': true });
const stanceAC = actor.totalAC;
console.assert(stanceAC === baseAC + 2);
// Test: UI renders
actor.sheet.render(true);
Workflow:
.db file// Use script to batch import
const entries = [
{
name: "Longsword",
type: "weapon",
system: { damageFormula: "1d8+@str.mod" }
},
{
name: "Armor Proficiency (Light)",
type: "feat",
system: { level: 1 }
}
];
for (const entry of entries) {
const doc = await Item.create(entry);
await game.packs.get('dnd35e.weapons').importDocument(doc);
}