Foundry v14 changes

Foundry v14 changes
This commit is contained in:
Aaron Lutomski
2026-06-18 17:07:18 -07:00
committed by GitHub
20 changed files with 313 additions and 147 deletions
+9
View File
@@ -9,5 +9,14 @@
"[handlebars]": {
"editor.defaultFormatter": "monosans.djlint"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
+31
View File
@@ -737,6 +737,37 @@ div .exhausted-section {
margin-bottom: 5px;
}
.tab.about {
.dg-about-links {
gap: 0.5rem;
margin-bottom: 1rem;
a {
display: inline-flex;
align-items: center;
gap: 0.5rem;
width: fit-content;
max-width: 100%;
i {
flex: 0 0 auto;
}
span {
flex: 1 1 auto;
line-height: 1.4;
text-align: left;
}
}
}
.dg-about-legal {
p {
margin: 0.5rem 0;
}
}
}
textarea.wounds {
resize: none;
height: 100px;
+4 -2
View File
@@ -1,7 +1,7 @@
import HumanSkillsActorData from "./base/human-skills.js";
import CharacterData from "./base/character.js";
const { SchemaField, NumberField, StringField, BooleanField } =
const { SchemaField, NumberField, StringField, BooleanField, HTMLField } =
foundry.data.fields;
export default class AgentData extends CharacterData {
@@ -29,8 +29,10 @@ export default class AgentData extends CharacterData {
}),
}),
physical: new SchemaField({
description: new StringField({
description: new HTMLField({
initial: "",
blank: true,
textSearch: true,
}),
wounds: new StringField({ initial: "" }),
firstAidAttempted: new BooleanField({ initial: false }),
+2 -2
View File
@@ -1,7 +1,7 @@
import HumanSkillsActorData from "./base/human-skills.js";
import CharacterData from "./base/character.js";
const { SchemaField, NumberField, StringField, BooleanField } =
const { SchemaField, NumberField, StringField, BooleanField, HTMLField } =
foundry.data.fields;
export default class NPCData extends CharacterData {
@@ -19,7 +19,7 @@ export default class NPCData extends CharacterData {
biography: new SchemaField({
profession: new StringField({ initial: "" }),
}),
notes: new StringField({ initial: "" }),
notes: new HTMLField({ initial: "", blank: true, textSearch: true }),
shortDescription: new StringField({ initial: "" }),
showUntrainedSkills: new BooleanField({ initial: true }),
};
+7 -2
View File
@@ -1,7 +1,7 @@
import UnnaturalSkillsActorData from "./base/unnatural-skills.js";
import CharacterData from "./base/character.js";
const { SchemaField, NumberField, StringField, BooleanField } =
const { SchemaField, NumberField, StringField, BooleanField, HTMLField } =
foundry.data.fields;
export default class UnnaturalData extends CharacterData {
@@ -17,7 +17,12 @@ export default class UnnaturalData extends CharacterData {
successLoss: new StringField({ initial: "1" }),
}),
schemaVersion: new NumberField({ initial: 1.0 }),
notes: new StringField({ initial: "" }),
notes: new HTMLField({
initial: "",
blank: true,
textSearch: true,
allowColor: true,
}),
shortDescription: new StringField({ initial: "" }),
showUntrainedSkills: new BooleanField({ initial: true }),
};
+6 -2
View File
@@ -1,6 +1,6 @@
import SheetSettingsActorData from "./base/sheet-settings.js";
const { SchemaField, NumberField, StringField, ArrayField } =
const { SchemaField, NumberField, StringField, ArrayField, HTMLField } =
foundry.data.fields;
export default class VehicleData extends foundry.abstract.TypeDataModel {
@@ -8,7 +8,11 @@ export default class VehicleData extends foundry.abstract.TypeDataModel {
return {
...SheetSettingsActorData.defineSchema(),
name: new StringField({ initial: "" }),
description: new StringField({ initial: "" }),
description: new HTMLField({
initial: "",
blank: true,
textSearch: true,
}),
shortDescription: new StringField({ initial: "" }),
health: new SchemaField({
value: new NumberField({ initial: 10 }),
+14
View File
@@ -0,0 +1,14 @@
import defineBaseItemSystemFields from "./base-fields.js";
const { NumberField, StringField, BooleanField } = foundry.data.fields;
export default class ArmorItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
...defineBaseItemSystemFields(),
protection: new NumberField({ initial: 3, integer: true }),
equipped: new BooleanField({ initial: true }),
expense: new StringField({ initial: "Standard" }),
};
}
}
+11
View File
@@ -0,0 +1,11 @@
const { HTMLField } = foundry.data.fields;
/**
* Shared system fields for all Delta Green item types (from legacy template base).
* Item display name lives on the document (`Item#name`), not in system.
*/
export default function defineBaseItemSystemFields() {
return {
description: new HTMLField({ initial: "", blank: true, textSearch: true }),
};
}
+14
View File
@@ -0,0 +1,14 @@
import defineBaseItemSystemFields from "./base-fields.js";
const { NumberField, StringField, BooleanField } = foundry.data.fields;
export default class BondItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
...defineBaseItemSystemFields(),
score: new NumberField({ initial: 10, integer: true }),
relationship: new StringField({ initial: "" }),
hasBeenDamagedSinceLastHomeScene: new BooleanField({ initial: false }),
};
}
}
+13
View File
@@ -0,0 +1,13 @@
import defineBaseItemSystemFields from "./base-fields.js";
const { StringField, BooleanField } = foundry.data.fields;
export default class GearItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
...defineBaseItemSystemFields(),
equipped: new BooleanField({ initial: true }),
expense: new StringField({ initial: "Standard" }),
};
}
}
+14
View File
@@ -0,0 +1,14 @@
import defineBaseItemSystemFields from "./base-fields.js";
const { StringField, BooleanField } = foundry.data.fields;
export default class MotivationItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
...defineBaseItemSystemFields(),
disorder: new StringField({ initial: "" }),
crossedOut: new BooleanField({ initial: false }),
disorderCured: new BooleanField({ initial: false }),
};
}
}
+33
View File
@@ -0,0 +1,33 @@
import defineBaseItemSystemFields from "./base-fields.js";
const { NumberField, StringField, BooleanField, SchemaField, HTMLField } =
foundry.data.fields;
export default class RitualItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
...defineBaseItemSystemFields(),
studyTime: new StringField({ initial: "" }),
sanity: new SchemaField({
notes: new StringField({ initial: "" }),
failedLoss: new StringField({ initial: "1D10" }),
successLoss: new StringField({ initial: "0" }),
}),
learnedSanity: new SchemaField({
notes: new StringField({ initial: "" }),
failedLoss: new StringField({ initial: "1D10" }),
successLoss: new StringField({ initial: "0" }),
}),
unnaturalSkillIncrease: new NumberField({ initial: 1, integer: true }),
activationCosts: new StringField({ initial: "" }),
activationTime: new StringField({ initial: "" }),
complexity: new StringField({ initial: "Simple" }),
handlerNotes: new HTMLField({
initial: "",
blank: true,
textSearch: true,
}),
revealed: new BooleanField({ initial: false }),
};
}
}
+27
View File
@@ -0,0 +1,27 @@
import defineBaseItemSystemFields from "./base-fields.js";
const { NumberField, StringField, BooleanField, SchemaField, HTMLField } =
foundry.data.fields;
export default class TomeItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
...defineBaseItemSystemFields(),
language: new StringField({ initial: "" }),
studyTime: new StringField({ initial: "" }),
unnaturalSkillIncrease: new NumberField({ initial: 5, integer: true }),
occultSkillIncrease: new NumberField({ initial: 3, integer: true }),
sanity: new SchemaField({
notes: new StringField({ initial: "" }),
failedLoss: new StringField({ initial: "1D6" }),
successLoss: new StringField({ initial: "1D4" }),
}),
handlerNotes: new HTMLField({
initial: "",
blank: true,
textSearch: true,
}),
revealed: new BooleanField({ initial: false }),
};
}
}
+23
View File
@@ -0,0 +1,23 @@
import defineBaseItemSystemFields from "./base-fields.js";
const { NumberField, StringField, BooleanField } = foundry.data.fields;
export default class WeaponItemData extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
...defineBaseItemSystemFields(),
skill: new StringField({ initial: "" }),
skillModifier: new NumberField({ initial: 0, integer: true }),
customSkillTarget: new NumberField({ initial: 50, integer: true }),
range: new StringField({ initial: "10M" }),
damage: new StringField({ initial: "1D8" }),
armorPiercing: new NumberField({ initial: 0, integer: true }),
lethality: new NumberField({ initial: 0, integer: true }),
isLethal: new BooleanField({ initial: false }),
killRadius: new StringField({ initial: "N/A" }),
ammo: new StringField({ initial: "" }),
expense: new StringField({ initial: "Standard" }),
equipped: new BooleanField({ initial: true }),
};
}
}
+18 -1
View File
@@ -25,18 +25,35 @@ import AgentData from "./data/actor/agent.js";
import UnnaturalData from "./data/actor/unnatural.js";
import NPCData from "./data/actor/npc.js";
import VehicleData from "./data/actor/vehicle.js";
import WeaponItemData from "./data/item/weapon.js";
import ArmorItemData from "./data/item/armor.js";
import MotivationItemData from "./data/item/motivation.js";
import BondItemData from "./data/item/bond.js";
import GearItemData from "./data/item/gear.js";
import TomeItemData from "./data/item/tome.js";
import RitualItemData from "./data/item/ritual.js";
const { Actors, Items } = foundry.documents.collections;
Hooks.once("init", async () => {
Object.assign(CONFIG.Actor.dataModels, {
// The keys are the types defined in our template.json
// The keys are the types defined in system.json documentTypes.Actor
agent: AgentData,
unnatural: UnnaturalData,
npc: NPCData,
vehicle: VehicleData,
});
Object.assign(CONFIG.Item.dataModels, {
weapon: WeaponItemData,
armor: ArmorItemData,
motivation: MotivationItemData,
bond: BondItemData,
gear: GearItemData,
tome: TomeItemData,
ritual: RitualItemData,
});
game.deltagreen = {
DeltaGreenActor,
DeltaGreenItem,
+8 -2
View File
@@ -594,10 +594,11 @@ export class DGLethalityRoll extends DGPercentileRoll {
}
let html = "";
html += `<div class="dice-roll">`;
html += `<div class="dice-roll" data-action="expandRoll">`;
html += ` <div class="dice-result">`;
html += ` <div style="${styleOverride}" class="dice-formula">${resultString}</div>`;
html += ` <div class="dice-tooltip">`;
html += ` <div class="wrapper">`;
html += ` <section class="tooltip-part">`;
html += ` <div class="dice">`;
html += ` <header class="part-header flexrow">`;
@@ -626,10 +627,12 @@ export class DGLethalityRoll extends DGPercentileRoll {
html += ` </ol>`;
html += ` </div>`;
html += ` </section>`;
html += ` </div>`;
html += ` </div>`;
html += ` <h4 class="dice-total">${this.total} (${
nonLethalDamage.total
} ${game.i18n.localize("DG.Roll.Damage")})</h4>`;
html += ` </div>`;
html += `</div>`;
return this.toMessage({ content: html, flavor: label });
@@ -788,10 +791,11 @@ export class DGSanityDamageRoll extends DGRoll {
)}</b> For <b>${lowDie.formula} / ${highDie.formula}</b>`;
let html = "";
html += `<div class="dice-roll">`;
html += `<div class="dice-roll" data-action="expandRoll">`;
html += ` <div class="dice-result">`;
html += ` <div class="dice-formula">${lowDie.formula} / ${highDie.formula}</div>`;
html += ` <div class="dice-tooltip">`;
html += ` <div class="wrapper">`;
html += ` <section class="tooltip-part">`;
html += ` <div class="dice">`;
html += ` <header class="part-header flexrow">`;
@@ -819,8 +823,10 @@ export class DGSanityDamageRoll extends DGRoll {
html += ` </ol>`;
html += ` </div>`;
html += ` </section>`;
html += ` </div>`;
html += ` </div>`;
html += ` <h4 class="dice-total">${lowResult} / ${highResult}</h4>`;
html += ` </div>`;
html += `</div>`;
return this.toMessage({ content: html, flavor });
}
+37 -6
View File
@@ -18,8 +18,8 @@
"version": "dev",
"compatibility": {
"minimum": "13",
"verified": "13",
"maximum": "13"
"verified": "14",
"maximum": "14"
},
"flags": {
"hotReload": {
@@ -203,10 +203,41 @@
"secondaryTokenAttribute": "wp",
"documentTypes": {
"Actor": {
"agent": {},
"unnatural": {},
"npc": {},
"vehicle": {}
"agent": {
"htmlFields": ["physical.description"]
},
"unnatural": {
"htmlFields": ["notes"]
},
"npc": {
"htmlFields": ["notes"]
},
"vehicle": {
"htmlFields": ["description"]
}
},
"Item": {
"weapon": {
"htmlFields": ["description"]
},
"armor": {
"htmlFields": ["description"]
},
"motivation": {
"htmlFields": ["description"]
},
"bond": {
"htmlFields": ["description"]
},
"gear": {
"htmlFields": ["description"]
},
"tome": {
"htmlFields": ["description", "handlerNotes"]
},
"ritual": {
"htmlFields": ["description", "handlerNotes"]
}
}
}
}
-91
View File
@@ -1,91 +0,0 @@
{
"Item": {
"types": [
"weapon",
"armor",
"motivation",
"bond",
"gear",
"tome",
"ritual"
],
"templates": {
"base": {
"name": "",
"description": ""
}
},
"weapon": {
"templates": ["base"],
"skill": "",
"skillModifier": 0,
"customSkillTarget": 50,
"range": "10M",
"damage": "1D8",
"armorPiercing": 0,
"lethality": 0,
"isLethal": false,
"killRadius": "N/A",
"ammo": "",
"expense": "Standard",
"equipped": true
},
"armor": {
"templates": ["base"],
"protection": 3,
"equipped": true,
"expense": "Standard"
},
"motivation": {
"templates": ["base"],
"disorder": "",
"crossedOut": false,
"disorderCured": false
},
"bond": {
"templates": ["base"],
"score": 10,
"relationship": "?",
"hasBeenDamagedSinceLastHomeScene": false
},
"gear": {
"templates": ["base"],
"equipped": true,
"expense": "Standard"
},
"tome": {
"templates": ["base"],
"language": "",
"studyTime": "",
"unnaturalSkillIncrease": 5,
"occultSkillIncrease": 3,
"sanity": {
"notes": "",
"failedLoss": "1D6",
"successLoss": "1D4"
},
"handlerNotes": "",
"revealed": false
},
"ritual": {
"templates": ["base"],
"studyTime": "",
"sanity": {
"notes": "",
"failedLoss": "1D10",
"successLoss": "0"
},
"learnedSanity": {
"notes": "",
"failedLoss": "1D10",
"successLoss": "0"
},
"unnaturalSkillIncrease": 1,
"activationCosts": "",
"activationTime": "",
"complexity": "Simple",
"handlerNotes": "",
"revealed": false
}
}
}
+27 -26
View File
@@ -3,31 +3,32 @@
data-tab="about">
<div class="about-section-header"></div>
<div class="flex horizontal-flex-column">
<div>
<a class="fas fa-question-circle"
title="{{localize 'DG.About.OnlineHelpTooltip'}}"
href="https://github.com/deltagreen-foundryvtt/delta-green-foundry-vtt-system/blob/master/documentation/home.md">
{{localize 'DG.About.OnlineHelp'}}
</a>
</div>
<div>
<a class="fas fa-bug"
title="{{localize 'DG.About.OnlineBugTrackerTooltip'}}"
href="https://github.com/deltagreen-foundryvtt/delta-green-foundry-vtt-system/issues">
{{localize 'DG.About.OnlineBugTracker'}}
</a>
</div>
<div>
<a class="fas fa-plus-circle"
title="{{localize 'DG.About.Changelogtip'}}"
href="https://github.com/deltagreen-foundryvtt/delta-green-foundry-vtt-system/blob/master/CHANGELOG.md">
{{localize 'DG.About.Changelog'}}
</a>
</div>
<div>
<p>{{localize 'DG.About.Copyright'}}</p>
<p>{{{localize 'DG.About.License'}}}</p>
</div>
<div class="dg-about-links flex horizontal-flex-column">
<a href="https://github.com/deltagreen-foundryvtt/delta-green-foundry-vtt-system/blob/master/documentation/home.md"
target="_blank"
rel="noopener"
data-tooltip="{{localize 'DG.About.OnlineHelpTooltip'}}">
<i class="fas fa-question-circle" inert></i>
<span>{{localize 'DG.About.OnlineHelp'}}</span>
</a>
<a href="https://github.com/deltagreen-foundryvtt/delta-green-foundry-vtt-system/issues"
target="_blank"
rel="noopener"
data-tooltip="{{localize 'DG.About.OnlineBugTrackerTooltip'}}">
<i class="fas fa-bug" inert></i>
<span>{{localize 'DG.About.OnlineBugTracker'}}</span>
</a>
<a href="https://github.com/deltagreen-foundryvtt/delta-green-foundry-vtt-system/blob/master/CHANGELOG.md"
target="_blank"
rel="noopener"
data-tooltip="{{localize 'DG.About.Changelogtip'}}">
<i class="fas fa-plus-circle" inert></i>
<span>{{localize 'DG.About.Changelog'}}</span>
</a>
</div>
<div class="dg-about-legal">
<p>{{localize 'DG.About.Copyright'}}</p>
<p>{{{localize 'DG.About.License'}}}</p>
</div>
</div>
+15 -13
View File
@@ -1,18 +1,20 @@
<div class="dice-roll">
<div class="dice-roll" data-action="expandRoll">
<div class="dice-result">
<div style="{{styleOverride}}" class="dice-formula">{{resultString}}</div>
<div class="dice-tooltip">
<section class="tooltip-part">
<div class="dice">
<header class="part-header flexrow">
<span class="part-formula">{{formula}}</span>
<span class="part-total">{{total}}</span>
</header>
<ol class="dice-rolls">
<li class="roll die {{formula}}">{{total}}</li>
</ol>
</div>
</section>
<div class="wrapper">
<section class="tooltip-part">
<div class="dice">
<header class="part-header flexrow">
<span class="part-formula">{{formula}}</span>
<span class="part-total">{{total}}</span>
</header>
<ol class="dice-rolls">
<li class="roll die {{formula}}">{{total}}</li>
</ol>
</div>
</section>
</div>
</div>
<h4 class="dice-total">{{total}}</h4>
</div>
@@ -27,4 +29,4 @@
</div>
{{/if}}
</div>
</div>