intelligent-system-design-language 0.3.21 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/langium-language-designer.md +38 -38
- package/.claude/agents/typescript-vscode-expert.md +29 -29
- package/.claude/agents/ui-ux-designer.md +36 -36
- package/.claude/settings.local.json +33 -33
- package/.idea/inspectionProfiles/Project_Default.xml +6 -6
- package/.idea/isdl.iml +13 -13
- package/.idea/modules.xml +8 -8
- package/.idea/vcs.xml +6 -6
- package/.idea/watcherTasks.xml +3 -3
- package/.vscodeignore +18 -18
- package/LICENSE +673 -673
- package/README.md +86 -86
- package/bin/cli.js +4 -4
- package/bin/lsp.js +8 -8
- package/out/_backgrounds.scss +91 -91
- package/out/_handlebars.scss +497 -497
- package/out/_isdlStyles.scss +1444 -1381
- package/out/_vuetifyOverrides.scss +425 -425
- package/out/_vuetifyStyles.scss +31957 -31957
- package/out/cli/components/_backgrounds.scss +91 -91
- package/out/cli/components/_handlebars.scss +497 -497
- package/out/cli/components/_isdlStyles.scss +1444 -1381
- package/out/cli/components/_vuetifyOverrides.scss +425 -425
- package/out/cli/components/_vuetifyStyles.scss +31957 -31957
- package/out/cli/components/active-effect-sheet-generator.js +453 -453
- package/out/cli/components/chat-card-generator.js +654 -651
- package/out/cli/components/chat-card-generator.js.map +1 -1
- package/out/cli/components/css-generator.js +4 -4
- package/out/cli/components/damage-roll-generator.js +160 -160
- package/out/cli/components/datamodel-generator.js +264 -257
- package/out/cli/components/datamodel-generator.js.map +1 -1
- package/out/cli/components/derived-data-generator.js +923 -923
- package/out/cli/components/hotbar-drop-hook-generator.js +82 -82
- package/out/cli/components/init-hook-generator.js +495 -495
- package/out/cli/components/language-generator.js +1 -1
- package/out/cli/components/language-generator.js.map +1 -1
- package/out/cli/components/measured-template-preview.js +221 -221
- package/out/cli/components/method-generator.js +979 -887
- package/out/cli/components/method-generator.js.map +1 -1
- package/out/cli/components/ready-hook-generator.js +404 -404
- package/out/cli/components/token-generator.js +116 -116
- package/out/cli/components/vue/base-components/vue-attribute.js +138 -138
- package/out/cli/components/vue/base-components/vue-boolean.js +64 -64
- package/out/cli/components/vue/base-components/vue-calculator.js +93 -93
- package/out/cli/components/vue/base-components/vue-damage-application.js +356 -356
- package/out/cli/components/vue/base-components/vue-damage-bonuses.js +165 -165
- package/out/cli/components/vue/base-components/vue-damage-resistances.js +196 -196
- package/out/cli/components/vue/base-components/vue-damage-track.js +121 -121
- package/out/cli/components/vue/base-components/vue-date-time.js +42 -42
- package/out/cli/components/vue/base-components/vue-dice.js +98 -98
- package/out/cli/components/vue/base-components/vue-die.js +73 -73
- package/out/cli/components/vue/base-components/vue-document-choice.js +149 -149
- package/out/cli/components/vue/base-components/vue-document-choices.js +179 -179
- package/out/cli/components/vue/base-components/vue-document-link.js +60 -60
- package/out/cli/components/vue/base-components/vue-extended-choice.js +88 -88
- package/out/cli/components/vue/base-components/vue-inventory.js +519 -519
- package/out/cli/components/vue/base-components/vue-macro-choice.js +138 -138
- package/out/cli/components/vue/base-components/vue-measured-template.js +530 -530
- package/out/cli/components/vue/base-components/vue-money.js +483 -483
- package/out/cli/components/vue/base-components/vue-number.js +174 -174
- package/out/cli/components/vue/base-components/vue-paperdoll.js +43 -43
- package/out/cli/components/vue/base-components/vue-parent-property-reference.js +76 -76
- package/out/cli/components/vue/base-components/vue-prosemirror.js +18 -18
- package/out/cli/components/vue/base-components/vue-resource.js +136 -136
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js +286 -109
- package/out/cli/components/vue/base-components/vue-roll-visualizer.js.map +1 -1
- package/out/cli/components/vue/base-components/vue-self-property-reference.js +62 -62
- package/out/cli/components/vue/base-components/vue-string-choice.js +98 -98
- package/out/cli/components/vue/base-components/vue-string-choices.js +203 -203
- package/out/cli/components/vue/base-components/vue-string.js +60 -60
- package/out/cli/components/vue/base-components/vue-text-field.js +53 -53
- package/out/cli/components/vue/base-components/vue-tracker.js +431 -431
- package/out/cli/components/vue/vue-action-component-generator.js +64 -64
- package/out/cli/components/vue/vue-active-effect-sheet-generator.js +856 -856
- package/out/cli/components/vue/vue-datatable-sheet-class-generator.js +292 -292
- package/out/cli/components/vue/vue-datatable2-component-generator.js +824 -824
- package/out/cli/components/vue/vue-document-creation-app.js +121 -121
- package/out/cli/components/vue/vue-document-creation-sheet.js +94 -94
- package/out/cli/components/vue/vue-generator.js +40 -40
- package/out/cli/components/vue/vue-mixin.js +296 -296
- package/out/cli/components/vue/vue-pinned-datatable-component-generator.js +260 -260
- package/out/cli/components/vue/vue-prompt-generator.js +91 -76
- package/out/cli/components/vue/vue-prompt-generator.js.map +1 -1
- package/out/cli/components/vue/vue-prompt-sheet-class-generator.js +317 -317
- package/out/cli/components/vue/vue-sheet-application-generator.js +1177 -1167
- package/out/cli/components/vue/vue-sheet-application-generator.js.map +1 -1
- package/out/cli/components/vue/vue-sheet-class-generator.js +510 -510
- package/out/cli/generator.js +438 -433
- package/out/cli/generator.js.map +1 -1
- package/out/extension/github/githubAuthProvider.js +71 -29
- package/out/extension/github/githubAuthProvider.js.map +1 -1
- package/out/extension/github/githubGistManager.js +4 -3
- package/out/extension/github/githubGistManager.js.map +1 -1
- package/out/extension/github/githubManager.js +40 -38
- package/out/extension/github/githubManager.js.map +1 -1
- package/out/extension/github/githubQuickActions.js +120 -120
- package/out/extension/github/system-workflow.yml +47 -47
- package/out/extension/main.cjs +909 -532
- package/out/extension/main.cjs.map +3 -3
- package/out/extension/package.json +419 -419
- package/out/language/generated/ast.js +51 -2
- package/out/language/generated/ast.js.map +1 -1
- package/out/language/generated/grammar.js +14240 -13991
- package/out/language/generated/grammar.js.map +1 -1
- package/out/language/intelligent-system-design-language-validator.js +32 -2
- package/out/language/intelligent-system-design-language-validator.js.map +1 -1
- package/out/language/isdl-scope-provider.js +14 -1
- package/out/language/isdl-scope-provider.js.map +1 -1
- package/out/language/main.cjs +913 -569
- package/out/language/main.cjs.map +3 -3
- package/out/package.json +419 -419
- package/out/progressbar.min.js +6 -6
- package/out/styles.scss +762 -747
- package/out/test/validating/diagnostics.test.js +40 -0
- package/out/test/validating/diagnostics.test.js.map +1 -1
- package/package.json +419 -419
|
@@ -13,20 +13,20 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
13
13
|
function generateExtendedDocumentClass(type, entry) {
|
|
14
14
|
function translateMethodOrValueOrStored(property, param) {
|
|
15
15
|
if (param == undefined) {
|
|
16
|
-
return expandToNode `
|
|
17
|
-
return system.${property.name.toLowerCase()} ?? 0
|
|
16
|
+
return expandToNode `
|
|
17
|
+
return system.${property.name.toLowerCase()} ?? 0
|
|
18
18
|
`;
|
|
19
19
|
}
|
|
20
20
|
if (isMethodBlock(param.value)) {
|
|
21
21
|
if (isNumberParamValue(param)) {
|
|
22
22
|
toBeReapplied.add("system." + property.name.toLowerCase());
|
|
23
23
|
}
|
|
24
|
-
return expandToNode `
|
|
25
|
-
${translateExpression(entry, id, param.value, true, property)}
|
|
24
|
+
return expandToNode `
|
|
25
|
+
${translateExpression(entry, id, param.value, true, property)}
|
|
26
26
|
`;
|
|
27
27
|
}
|
|
28
|
-
return expandToNode `
|
|
29
|
-
return ${param.value}
|
|
28
|
+
return expandToNode `
|
|
29
|
+
return ${param.value}
|
|
30
30
|
`;
|
|
31
31
|
}
|
|
32
32
|
const generatedFilePath = path.join(generatedFileDir, `${type.toLowerCase()}.mjs`);
|
|
@@ -42,21 +42,21 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
42
42
|
if (stringValue.value == "")
|
|
43
43
|
return;
|
|
44
44
|
if (typeof stringValue.value == "string") {
|
|
45
|
-
return expandToNode `
|
|
46
|
-
// ${property.name} String Derived Data
|
|
47
|
-
this.system.${property.name.toLowerCase()} = "${stringValue.value}";
|
|
45
|
+
return expandToNode `
|
|
46
|
+
// ${property.name} String Derived Data
|
|
47
|
+
this.system.${property.name.toLowerCase()} = "${stringValue.value}";
|
|
48
48
|
`.appendNewLineIfNotEmpty();
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
|
-
return expandToNode `
|
|
52
|
-
// ${property.name} String Derived Data
|
|
53
|
-
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
54
|
-
const context = {
|
|
55
|
-
object: this
|
|
56
|
-
};
|
|
57
|
-
${translateExpression(entry, id, stringValue.value, true, property)}
|
|
58
|
-
};
|
|
59
|
-
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
51
|
+
return expandToNode `
|
|
52
|
+
// ${property.name} String Derived Data
|
|
53
|
+
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
54
|
+
const context = {
|
|
55
|
+
object: this
|
|
56
|
+
};
|
|
57
|
+
${translateExpression(entry, id, stringValue.value, true, property)}
|
|
58
|
+
};
|
|
59
|
+
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
60
60
|
`.appendNewLineIfNotEmpty();
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -66,102 +66,102 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
66
66
|
const minParam = property.params.find(p => isNumberParamMin(p));
|
|
67
67
|
const maxParam = property.params.find(p => isNumberParamMax(p));
|
|
68
68
|
if (valueParam) {
|
|
69
|
-
return expandToNode `
|
|
70
|
-
// ${property.name} Number Calculated Data
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
${minParam != undefined ? expandToNode `
|
|
74
|
-
const ${property.name.toLowerCase()}MinFunc = (system) => {
|
|
75
|
-
const context = {
|
|
76
|
-
object: this
|
|
77
|
-
};
|
|
78
|
-
${translateMethodOrValueOrStored(property, minParam)}
|
|
79
|
-
};
|
|
80
|
-
let ${property.name.toLowerCase()}Min = ${property.name.toLowerCase()}MinFunc(this.system);
|
|
81
|
-
if (isNaN(${property.name.toLowerCase()}Min) || ${property.name.toLowerCase()}Min === undefined || ${property.name.toLowerCase()}Min === null) {
|
|
82
|
-
${property.name.toLowerCase()}Min = 0;
|
|
83
|
-
}
|
|
84
|
-
`.appendNewLine() : ""}
|
|
85
|
-
|
|
86
|
-
${maxParam != undefined ? expandToNode `
|
|
87
|
-
const ${property.name.toLowerCase()}MaxFunc = (system) => {
|
|
88
|
-
const context = {
|
|
89
|
-
object: this
|
|
90
|
-
};
|
|
91
|
-
${translateMethodOrValueOrStored(property, maxParam)}
|
|
92
|
-
};
|
|
93
|
-
let ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}MaxFunc(this.system);
|
|
94
|
-
if (isNaN(${property.name.toLowerCase()}Max) || ${property.name.toLowerCase()}Max === undefined || ${property.name.toLowerCase()}Max === null) {
|
|
95
|
-
${property.name.toLowerCase()}Max = 0;
|
|
96
|
-
}
|
|
97
|
-
`.appendNewLine() : ""}
|
|
98
|
-
|
|
99
|
-
// ${property.name} Number Derived Data
|
|
100
|
-
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
101
|
-
const context = {
|
|
102
|
-
object: this
|
|
103
|
-
};
|
|
104
|
-
${translateMethodOrValueOrStored(property, valueParam)}
|
|
105
|
-
};
|
|
106
|
-
Object.defineProperty(this.system, "${property.name.toLowerCase()}", {
|
|
107
|
-
get: () => {
|
|
108
|
-
let current = ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
109
|
-
// Protect against NaN from invalid operations (e.g., "A" + 2)
|
|
110
|
-
if (isNaN(current) || current === undefined || current === null) {
|
|
111
|
-
current = 0;
|
|
112
|
-
}
|
|
113
|
-
${minParam != undefined ? expandToNode `
|
|
114
|
-
if ( current < ${property.name.toLowerCase()}Min ) {
|
|
115
|
-
current = ${property.name.toLowerCase()}Min;
|
|
116
|
-
}
|
|
117
|
-
`.appendNewLine() : ""}
|
|
118
|
-
${maxParam != undefined ? expandToNode `
|
|
119
|
-
if ( current > ${property.name.toLowerCase()}Max ) {
|
|
120
|
-
current = ${property.name.toLowerCase()}Max;
|
|
121
|
-
}
|
|
122
|
-
`.appendNewLine() : ""}
|
|
123
|
-
return current;
|
|
124
|
-
},
|
|
125
|
-
configurable: true
|
|
126
|
-
});
|
|
127
|
-
|
|
69
|
+
return expandToNode `
|
|
70
|
+
// ${property.name} Number Calculated Data
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
${minParam != undefined ? expandToNode `
|
|
74
|
+
const ${property.name.toLowerCase()}MinFunc = (system) => {
|
|
75
|
+
const context = {
|
|
76
|
+
object: this
|
|
77
|
+
};
|
|
78
|
+
${translateMethodOrValueOrStored(property, minParam)}
|
|
79
|
+
};
|
|
80
|
+
let ${property.name.toLowerCase()}Min = ${property.name.toLowerCase()}MinFunc(this.system);
|
|
81
|
+
if (isNaN(${property.name.toLowerCase()}Min) || ${property.name.toLowerCase()}Min === undefined || ${property.name.toLowerCase()}Min === null) {
|
|
82
|
+
${property.name.toLowerCase()}Min = 0;
|
|
83
|
+
}
|
|
84
|
+
`.appendNewLine() : ""}
|
|
85
|
+
|
|
86
|
+
${maxParam != undefined ? expandToNode `
|
|
87
|
+
const ${property.name.toLowerCase()}MaxFunc = (system) => {
|
|
88
|
+
const context = {
|
|
89
|
+
object: this
|
|
90
|
+
};
|
|
91
|
+
${translateMethodOrValueOrStored(property, maxParam)}
|
|
92
|
+
};
|
|
93
|
+
let ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}MaxFunc(this.system);
|
|
94
|
+
if (isNaN(${property.name.toLowerCase()}Max) || ${property.name.toLowerCase()}Max === undefined || ${property.name.toLowerCase()}Max === null) {
|
|
95
|
+
${property.name.toLowerCase()}Max = 0;
|
|
96
|
+
}
|
|
97
|
+
`.appendNewLine() : ""}
|
|
98
|
+
|
|
99
|
+
// ${property.name} Number Derived Data
|
|
100
|
+
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
101
|
+
const context = {
|
|
102
|
+
object: this
|
|
103
|
+
};
|
|
104
|
+
${translateMethodOrValueOrStored(property, valueParam)}
|
|
105
|
+
};
|
|
106
|
+
Object.defineProperty(this.system, "${property.name.toLowerCase()}", {
|
|
107
|
+
get: () => {
|
|
108
|
+
let current = ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
109
|
+
// Protect against NaN from invalid operations (e.g., "A" + 2)
|
|
110
|
+
if (isNaN(current) || current === undefined || current === null) {
|
|
111
|
+
current = 0;
|
|
112
|
+
}
|
|
113
|
+
${minParam != undefined ? expandToNode `
|
|
114
|
+
if ( current < ${property.name.toLowerCase()}Min ) {
|
|
115
|
+
current = ${property.name.toLowerCase()}Min;
|
|
116
|
+
}
|
|
117
|
+
`.appendNewLine() : ""}
|
|
118
|
+
${maxParam != undefined ? expandToNode `
|
|
119
|
+
if ( current > ${property.name.toLowerCase()}Max ) {
|
|
120
|
+
current = ${property.name.toLowerCase()}Max;
|
|
121
|
+
}
|
|
122
|
+
`.appendNewLine() : ""}
|
|
123
|
+
return current;
|
|
124
|
+
},
|
|
125
|
+
configurable: true
|
|
126
|
+
});
|
|
127
|
+
|
|
128
128
|
`.appendNewLineIfNotEmpty();
|
|
129
129
|
}
|
|
130
|
-
return expandToNode `
|
|
131
|
-
// ${property.name} Number Derived Data
|
|
132
|
-
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
133
|
-
const context = {
|
|
134
|
-
object: this
|
|
135
|
-
};
|
|
136
|
-
${translateMethodOrValueOrStored(property, valueParam)}
|
|
137
|
-
};
|
|
138
|
-
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
139
|
-
|
|
140
|
-
${minParam != undefined ? expandToNode `
|
|
141
|
-
const ${property.name.toLowerCase()}MinFunc = (system) => {
|
|
142
|
-
const context = {
|
|
143
|
-
object: this
|
|
144
|
-
};
|
|
145
|
-
${translateMethodOrValueOrStored(property, minParam)}
|
|
146
|
-
};
|
|
147
|
-
const ${property.name.toLowerCase()}Min = ${property.name.toLowerCase()}MinFunc(this.system);
|
|
148
|
-
if ( this.system.${property.name.toLowerCase()} < ${property.name.toLowerCase()}Min ) {
|
|
149
|
-
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}Min;
|
|
150
|
-
}
|
|
151
|
-
`.appendNewLine() : ""}
|
|
152
|
-
|
|
153
|
-
${maxParam != undefined ? expandToNode `
|
|
154
|
-
const ${property.name.toLowerCase()}MaxFunc = (system) => {
|
|
155
|
-
const context = {
|
|
156
|
-
object: this
|
|
157
|
-
};
|
|
158
|
-
${translateMethodOrValueOrStored(property, maxParam)}
|
|
159
|
-
};
|
|
160
|
-
const ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}MaxFunc(this.system);
|
|
161
|
-
if ( this.system.${property.name.toLowerCase()} > ${property.name.toLowerCase()}Max ) {
|
|
162
|
-
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}Max;
|
|
163
|
-
}
|
|
164
|
-
`.appendNewLine() : ""}
|
|
130
|
+
return expandToNode `
|
|
131
|
+
// ${property.name} Number Derived Data
|
|
132
|
+
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
133
|
+
const context = {
|
|
134
|
+
object: this
|
|
135
|
+
};
|
|
136
|
+
${translateMethodOrValueOrStored(property, valueParam)}
|
|
137
|
+
};
|
|
138
|
+
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
139
|
+
|
|
140
|
+
${minParam != undefined ? expandToNode `
|
|
141
|
+
const ${property.name.toLowerCase()}MinFunc = (system) => {
|
|
142
|
+
const context = {
|
|
143
|
+
object: this
|
|
144
|
+
};
|
|
145
|
+
${translateMethodOrValueOrStored(property, minParam)}
|
|
146
|
+
};
|
|
147
|
+
const ${property.name.toLowerCase()}Min = ${property.name.toLowerCase()}MinFunc(this.system);
|
|
148
|
+
if ( this.system.${property.name.toLowerCase()} < ${property.name.toLowerCase()}Min ) {
|
|
149
|
+
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}Min;
|
|
150
|
+
}
|
|
151
|
+
`.appendNewLine() : ""}
|
|
152
|
+
|
|
153
|
+
${maxParam != undefined ? expandToNode `
|
|
154
|
+
const ${property.name.toLowerCase()}MaxFunc = (system) => {
|
|
155
|
+
const context = {
|
|
156
|
+
object: this
|
|
157
|
+
};
|
|
158
|
+
${translateMethodOrValueOrStored(property, maxParam)}
|
|
159
|
+
};
|
|
160
|
+
const ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}MaxFunc(this.system);
|
|
161
|
+
if ( this.system.${property.name.toLowerCase()} > ${property.name.toLowerCase()}Max ) {
|
|
162
|
+
this.system.${property.name.toLowerCase()} = ${property.name.toLowerCase()}Max;
|
|
163
|
+
}
|
|
164
|
+
`.appendNewLine() : ""}
|
|
165
165
|
`.appendNewLineIfNotEmpty();
|
|
166
166
|
}
|
|
167
167
|
if (isMoneyField(property)) {
|
|
@@ -173,65 +173,65 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
173
173
|
console.warn(`Money field ${property.name} has both denominations and value parameter. Value parameter will be ignored for multi-denomination money.`);
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
|
-
return expandToNode `
|
|
177
|
-
// ${property.name} Money Calculated Data
|
|
178
|
-
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
179
|
-
const context = {
|
|
180
|
-
object: this
|
|
181
|
-
};
|
|
182
|
-
${translateMethodOrValueOrStored(property, valueParam)}
|
|
183
|
-
};
|
|
184
|
-
Object.defineProperty(this.system, "${property.name.toLowerCase()}", {
|
|
185
|
-
get: () => {
|
|
186
|
-
return ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
187
|
-
},
|
|
188
|
-
configurable: true
|
|
189
|
-
});
|
|
190
|
-
|
|
176
|
+
return expandToNode `
|
|
177
|
+
// ${property.name} Money Calculated Data
|
|
178
|
+
const ${property.name.toLowerCase()}CurrentValueFunc = (system) => {
|
|
179
|
+
const context = {
|
|
180
|
+
object: this
|
|
181
|
+
};
|
|
182
|
+
${translateMethodOrValueOrStored(property, valueParam)}
|
|
183
|
+
};
|
|
184
|
+
Object.defineProperty(this.system, "${property.name.toLowerCase()}", {
|
|
185
|
+
get: () => {
|
|
186
|
+
return ${property.name.toLowerCase()}CurrentValueFunc(this.system);
|
|
187
|
+
},
|
|
188
|
+
configurable: true
|
|
189
|
+
});
|
|
190
|
+
|
|
191
191
|
`.appendNewLineIfNotEmpty();
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
if (isAttributeExp(property)) {
|
|
195
195
|
console.log("Processing Derived Attribute: " + property.name);
|
|
196
196
|
const modParam = property.params.find(p => isAttributeParamMod(p));
|
|
197
|
-
return expandToNode `
|
|
198
|
-
|
|
199
|
-
// ${property.name} Attribute Derived Data
|
|
200
|
-
const ${property.name.toLowerCase()}CurrentValue = this.system.${property.name.toLowerCase()}?.value ?? 0;
|
|
201
|
-
const ${property.name.toLowerCase()}CurrentMax = this.system.${property.name.toLowerCase()}?.max ?? 0;
|
|
202
|
-
const ${property.name.toLowerCase()}ModFunc = (system) => {
|
|
203
|
-
const context = {
|
|
204
|
-
object: this
|
|
205
|
-
};
|
|
206
|
-
${modParam ? translateExpression(entry, id, modParam.method, true, property) : `return ${property.name.toLowerCase()}CurrentValue`}
|
|
207
|
-
};
|
|
208
|
-
let ${property.name.toLowerCase()}Mod = ${property.name.toLowerCase()}ModFunc(this.system);
|
|
209
|
-
// Protect against NaN from invalid operations
|
|
210
|
-
if (isNaN(${property.name.toLowerCase()}Mod) || ${property.name.toLowerCase()}Mod === undefined || ${property.name.toLowerCase()}Mod === null) {
|
|
211
|
-
${property.name.toLowerCase()}Mod = 0;
|
|
212
|
-
}
|
|
213
|
-
this.system.${property.name.toLowerCase()} = {
|
|
214
|
-
value: ${property.name.toLowerCase()}CurrentValue,
|
|
215
|
-
max: ${property.name.toLowerCase()}CurrentMax,
|
|
216
|
-
mod: ${property.name.toLowerCase()}Mod
|
|
217
|
-
};
|
|
218
|
-
if ( this.system.${property.name.toLowerCase()}.value > this.system.${property.name.toLowerCase()}.max ) {
|
|
219
|
-
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.max;
|
|
220
|
-
}
|
|
197
|
+
return expandToNode `
|
|
198
|
+
|
|
199
|
+
// ${property.name} Attribute Derived Data
|
|
200
|
+
const ${property.name.toLowerCase()}CurrentValue = this.system.${property.name.toLowerCase()}?.value ?? 0;
|
|
201
|
+
const ${property.name.toLowerCase()}CurrentMax = this.system.${property.name.toLowerCase()}?.max ?? 0;
|
|
202
|
+
const ${property.name.toLowerCase()}ModFunc = (system) => {
|
|
203
|
+
const context = {
|
|
204
|
+
object: this
|
|
205
|
+
};
|
|
206
|
+
${modParam ? translateExpression(entry, id, modParam.method, true, property) : `return ${property.name.toLowerCase()}CurrentValue`}
|
|
207
|
+
};
|
|
208
|
+
let ${property.name.toLowerCase()}Mod = ${property.name.toLowerCase()}ModFunc(this.system);
|
|
209
|
+
// Protect against NaN from invalid operations
|
|
210
|
+
if (isNaN(${property.name.toLowerCase()}Mod) || ${property.name.toLowerCase()}Mod === undefined || ${property.name.toLowerCase()}Mod === null) {
|
|
211
|
+
${property.name.toLowerCase()}Mod = 0;
|
|
212
|
+
}
|
|
213
|
+
this.system.${property.name.toLowerCase()} = {
|
|
214
|
+
value: ${property.name.toLowerCase()}CurrentValue,
|
|
215
|
+
max: ${property.name.toLowerCase()}CurrentMax,
|
|
216
|
+
mod: ${property.name.toLowerCase()}Mod
|
|
217
|
+
};
|
|
218
|
+
if ( this.system.${property.name.toLowerCase()}.value > this.system.${property.name.toLowerCase()}.max ) {
|
|
219
|
+
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.max;
|
|
220
|
+
}
|
|
221
221
|
`.appendNewLineIfNotEmpty();
|
|
222
222
|
}
|
|
223
223
|
;
|
|
224
224
|
function generateValueOrMethod(value) {
|
|
225
225
|
if (isMethodBlock(value)) {
|
|
226
|
-
return expandToNode `
|
|
227
|
-
const context = {
|
|
228
|
-
object: this
|
|
229
|
-
};
|
|
230
|
-
${translateExpression(entry, id, value, true, undefined)}
|
|
226
|
+
return expandToNode `
|
|
227
|
+
const context = {
|
|
228
|
+
object: this
|
|
229
|
+
};
|
|
230
|
+
${translateExpression(entry, id, value, true, undefined)}
|
|
231
231
|
`;
|
|
232
232
|
}
|
|
233
|
-
return expandToNode `
|
|
234
|
-
return ${value};
|
|
233
|
+
return expandToNode `
|
|
234
|
+
return ${value};
|
|
235
235
|
`;
|
|
236
236
|
}
|
|
237
237
|
if (isTrackerExp(property)) {
|
|
@@ -241,43 +241,43 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
241
241
|
const valueParam = property.params.find(x => isNumberParamValue(x));
|
|
242
242
|
if (maxParam == undefined && minParam == undefined && valueParam == undefined)
|
|
243
243
|
return;
|
|
244
|
-
return expandToNode `
|
|
245
|
-
// ${property.name} Tracker Derived Data
|
|
246
|
-
const ${property.name.toLowerCase()}TempValue = this.system.${property.name.toLowerCase()}.temp ?? 0;
|
|
247
|
-
const ${property.name.toLowerCase()}CurrentMin = (system) => {
|
|
248
|
-
${minParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.min ?? 0;` : generateValueOrMethod(minParam.value)};
|
|
249
|
-
}
|
|
250
|
-
const ${property.name.toLowerCase()}CurrentValue = (system) => {
|
|
251
|
-
${valueParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.value ?? 0;` : generateValueOrMethod(valueParam.value)};
|
|
252
|
-
}
|
|
253
|
-
const ${property.name.toLowerCase()}CurrentMax = (system) => {
|
|
254
|
-
${maxParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.max ?? 0;` : generateValueOrMethod(maxParam.value)};
|
|
255
|
-
}
|
|
256
|
-
let ${property.name.toLowerCase()}Min = ${property.name.toLowerCase()}CurrentMin(this.system);
|
|
257
|
-
let ${property.name.toLowerCase()}Value = ${property.name.toLowerCase()}CurrentValue(this.system);
|
|
258
|
-
let ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}CurrentMax(this.system);
|
|
259
|
-
// Protect against NaN from invalid operations
|
|
260
|
-
if (isNaN(${property.name.toLowerCase()}Min) || ${property.name.toLowerCase()}Min === undefined || ${property.name.toLowerCase()}Min === null) {
|
|
261
|
-
${property.name.toLowerCase()}Min = 0;
|
|
262
|
-
}
|
|
263
|
-
if (isNaN(${property.name.toLowerCase()}Value) || ${property.name.toLowerCase()}Value === undefined || ${property.name.toLowerCase()}Value === null) {
|
|
264
|
-
${property.name.toLowerCase()}Value = 0;
|
|
265
|
-
}
|
|
266
|
-
if (isNaN(${property.name.toLowerCase()}Max) || ${property.name.toLowerCase()}Max === undefined || ${property.name.toLowerCase()}Max === null) {
|
|
267
|
-
${property.name.toLowerCase()}Max = 0;
|
|
268
|
-
}
|
|
269
|
-
this.system.${property.name.toLowerCase()} = {
|
|
270
|
-
min: ${property.name.toLowerCase()}Min,
|
|
271
|
-
value: ${property.name.toLowerCase()}Value,
|
|
272
|
-
temp: ${property.name.toLowerCase()}TempValue,
|
|
273
|
-
max: ${property.name.toLowerCase()}Max,
|
|
274
|
-
};
|
|
275
|
-
if ( !editMode && this.system.${property.name.toLowerCase()}.value < this.system.${property.name.toLowerCase()}.min ) {
|
|
276
|
-
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.min;
|
|
277
|
-
}
|
|
278
|
-
else if ( !editMode && this.system.${property.name.toLowerCase()}.value > this.system.${property.name.toLowerCase()}.max ) {
|
|
279
|
-
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.max;
|
|
280
|
-
}
|
|
244
|
+
return expandToNode `
|
|
245
|
+
// ${property.name} Tracker Derived Data
|
|
246
|
+
const ${property.name.toLowerCase()}TempValue = this.system.${property.name.toLowerCase()}.temp ?? 0;
|
|
247
|
+
const ${property.name.toLowerCase()}CurrentMin = (system) => {
|
|
248
|
+
${minParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.min ?? 0;` : generateValueOrMethod(minParam.value)};
|
|
249
|
+
}
|
|
250
|
+
const ${property.name.toLowerCase()}CurrentValue = (system) => {
|
|
251
|
+
${valueParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.value ?? 0;` : generateValueOrMethod(valueParam.value)};
|
|
252
|
+
}
|
|
253
|
+
const ${property.name.toLowerCase()}CurrentMax = (system) => {
|
|
254
|
+
${maxParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.max ?? 0;` : generateValueOrMethod(maxParam.value)};
|
|
255
|
+
}
|
|
256
|
+
let ${property.name.toLowerCase()}Min = ${property.name.toLowerCase()}CurrentMin(this.system);
|
|
257
|
+
let ${property.name.toLowerCase()}Value = ${property.name.toLowerCase()}CurrentValue(this.system);
|
|
258
|
+
let ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}CurrentMax(this.system);
|
|
259
|
+
// Protect against NaN from invalid operations
|
|
260
|
+
if (isNaN(${property.name.toLowerCase()}Min) || ${property.name.toLowerCase()}Min === undefined || ${property.name.toLowerCase()}Min === null) {
|
|
261
|
+
${property.name.toLowerCase()}Min = 0;
|
|
262
|
+
}
|
|
263
|
+
if (isNaN(${property.name.toLowerCase()}Value) || ${property.name.toLowerCase()}Value === undefined || ${property.name.toLowerCase()}Value === null) {
|
|
264
|
+
${property.name.toLowerCase()}Value = 0;
|
|
265
|
+
}
|
|
266
|
+
if (isNaN(${property.name.toLowerCase()}Max) || ${property.name.toLowerCase()}Max === undefined || ${property.name.toLowerCase()}Max === null) {
|
|
267
|
+
${property.name.toLowerCase()}Max = 0;
|
|
268
|
+
}
|
|
269
|
+
this.system.${property.name.toLowerCase()} = {
|
|
270
|
+
min: ${property.name.toLowerCase()}Min,
|
|
271
|
+
value: ${property.name.toLowerCase()}Value,
|
|
272
|
+
temp: ${property.name.toLowerCase()}TempValue,
|
|
273
|
+
max: ${property.name.toLowerCase()}Max,
|
|
274
|
+
};
|
|
275
|
+
if ( !editMode && this.system.${property.name.toLowerCase()}.value < this.system.${property.name.toLowerCase()}.min ) {
|
|
276
|
+
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.min;
|
|
277
|
+
}
|
|
278
|
+
else if ( !editMode && this.system.${property.name.toLowerCase()}.value > this.system.${property.name.toLowerCase()}.max ) {
|
|
279
|
+
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.max;
|
|
280
|
+
}
|
|
281
281
|
`.appendNewLineIfNotEmpty();
|
|
282
282
|
}
|
|
283
283
|
;
|
|
@@ -289,80 +289,80 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
289
289
|
if (maxParam == undefined && minParam == undefined && valueParam == undefined)
|
|
290
290
|
return;
|
|
291
291
|
//toBeReapplied.add("system." + property.name.toLowerCase() + ".max");
|
|
292
|
-
return expandToNode `
|
|
293
|
-
// ${property.name} Resource Derived Data
|
|
294
|
-
const ${property.name.toLowerCase()}TempValue = this.system.${property.name.toLowerCase()}.temp ?? 0;
|
|
295
|
-
const ${property.name.toLowerCase()}CurrentMin = (system) => {
|
|
296
|
-
${minParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.min ?? 0;` : generateValueOrMethod(minParam.value)};
|
|
297
|
-
}
|
|
298
|
-
const ${property.name.toLowerCase()}CurrentValue = (system) => {
|
|
299
|
-
${valueParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.value ?? 0;` : generateValueOrMethod(valueParam.value)};
|
|
300
|
-
}
|
|
301
|
-
const ${property.name.toLowerCase()}CurrentMax = (system) => {
|
|
302
|
-
${maxParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.max ?? 0;` : generateValueOrMethod(maxParam.value)};
|
|
303
|
-
}
|
|
304
|
-
let ${property.name.toLowerCase()}Value = ${property.name.toLowerCase()}CurrentValue(this.system);
|
|
305
|
-
let ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}CurrentMax(this.system);
|
|
306
|
-
// Protect against NaN from invalid operations
|
|
307
|
-
if (isNaN(${property.name.toLowerCase()}Value) || ${property.name.toLowerCase()}Value === undefined || ${property.name.toLowerCase()}Value === null) {
|
|
308
|
-
${property.name.toLowerCase()}Value = 0;
|
|
309
|
-
}
|
|
310
|
-
if (isNaN(${property.name.toLowerCase()}Max) || ${property.name.toLowerCase()}Max === undefined || ${property.name.toLowerCase()}Max === null) {
|
|
311
|
-
${property.name.toLowerCase()}Max = 0;
|
|
312
|
-
}
|
|
313
|
-
this.system.${property.name.toLowerCase()} = {
|
|
314
|
-
value: ${property.name.toLowerCase()}Value,
|
|
315
|
-
temp: ${property.name.toLowerCase()}TempValue,
|
|
316
|
-
max: ${property.name.toLowerCase()}Max
|
|
317
|
-
};
|
|
318
|
-
this.reapplyActiveEffectsForName("system.${property.name.toLowerCase()}.max");
|
|
319
|
-
if ( !editMode && this.system.${property.name.toLowerCase()}.value < ${property.name.toLowerCase()}CurrentMin(this.system) ) {
|
|
320
|
-
this.system.${property.name.toLowerCase()}.value = ${property.name.toLowerCase()}CurrentMin(this.system);
|
|
321
|
-
}
|
|
322
|
-
else if ( !editMode && this.system.${property.name.toLowerCase()}.value > this.system.${property.name.toLowerCase()}.max ) {
|
|
323
|
-
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.max;
|
|
324
|
-
}
|
|
292
|
+
return expandToNode `
|
|
293
|
+
// ${property.name} Resource Derived Data
|
|
294
|
+
const ${property.name.toLowerCase()}TempValue = this.system.${property.name.toLowerCase()}.temp ?? 0;
|
|
295
|
+
const ${property.name.toLowerCase()}CurrentMin = (system) => {
|
|
296
|
+
${minParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.min ?? 0;` : generateValueOrMethod(minParam.value)};
|
|
297
|
+
}
|
|
298
|
+
const ${property.name.toLowerCase()}CurrentValue = (system) => {
|
|
299
|
+
${valueParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.value ?? 0;` : generateValueOrMethod(valueParam.value)};
|
|
300
|
+
}
|
|
301
|
+
const ${property.name.toLowerCase()}CurrentMax = (system) => {
|
|
302
|
+
${maxParam == undefined ? expandToNode `return this.system.${property.name.toLowerCase()}?.max ?? 0;` : generateValueOrMethod(maxParam.value)};
|
|
303
|
+
}
|
|
304
|
+
let ${property.name.toLowerCase()}Value = ${property.name.toLowerCase()}CurrentValue(this.system);
|
|
305
|
+
let ${property.name.toLowerCase()}Max = ${property.name.toLowerCase()}CurrentMax(this.system);
|
|
306
|
+
// Protect against NaN from invalid operations
|
|
307
|
+
if (isNaN(${property.name.toLowerCase()}Value) || ${property.name.toLowerCase()}Value === undefined || ${property.name.toLowerCase()}Value === null) {
|
|
308
|
+
${property.name.toLowerCase()}Value = 0;
|
|
309
|
+
}
|
|
310
|
+
if (isNaN(${property.name.toLowerCase()}Max) || ${property.name.toLowerCase()}Max === undefined || ${property.name.toLowerCase()}Max === null) {
|
|
311
|
+
${property.name.toLowerCase()}Max = 0;
|
|
312
|
+
}
|
|
313
|
+
this.system.${property.name.toLowerCase()} = {
|
|
314
|
+
value: ${property.name.toLowerCase()}Value,
|
|
315
|
+
temp: ${property.name.toLowerCase()}TempValue,
|
|
316
|
+
max: ${property.name.toLowerCase()}Max
|
|
317
|
+
};
|
|
318
|
+
this.reapplyActiveEffectsForName("system.${property.name.toLowerCase()}.max");
|
|
319
|
+
if ( !editMode && this.system.${property.name.toLowerCase()}.value < ${property.name.toLowerCase()}CurrentMin(this.system) ) {
|
|
320
|
+
this.system.${property.name.toLowerCase()}.value = ${property.name.toLowerCase()}CurrentMin(this.system);
|
|
321
|
+
}
|
|
322
|
+
else if ( !editMode && this.system.${property.name.toLowerCase()}.value > this.system.${property.name.toLowerCase()}.max ) {
|
|
323
|
+
this.system.${property.name.toLowerCase()}.value = this.system.${property.name.toLowerCase()}.max;
|
|
324
|
+
}
|
|
325
325
|
`.appendNewLineIfNotEmpty();
|
|
326
326
|
}
|
|
327
327
|
if (isTableField(property)) {
|
|
328
328
|
console.log("Processing Derived Document Array: " + property.name);
|
|
329
329
|
const whereParam = property.params.find(p => isWhereParam(p));
|
|
330
330
|
if (whereParam) {
|
|
331
|
-
return expandToNode `
|
|
332
|
-
// ${property.name} Document Array Derived Data
|
|
333
|
-
this.system.${property.name.toLowerCase()} = this.items.filter((item) => {
|
|
334
|
-
if ( item.type !== "${(_a = property.document.ref) === null || _a === void 0 ? void 0 : _a.name.toLowerCase()}") return false;
|
|
335
|
-
return ${translateExpression(entry, id, whereParam.value, true, property)};
|
|
336
|
-
});
|
|
331
|
+
return expandToNode `
|
|
332
|
+
// ${property.name} Document Array Derived Data
|
|
333
|
+
this.system.${property.name.toLowerCase()} = this.items.filter((item) => {
|
|
334
|
+
if ( item.type !== "${(_a = property.document.ref) === null || _a === void 0 ? void 0 : _a.name.toLowerCase()}") return false;
|
|
335
|
+
return ${translateExpression(entry, id, whereParam.value, true, property)};
|
|
336
|
+
});
|
|
337
337
|
`.appendNewLineIfNotEmpty();
|
|
338
338
|
}
|
|
339
|
-
return expandToNode `
|
|
340
|
-
// ${property.name} Document Array Derived Data
|
|
341
|
-
this.system.${property.name.toLowerCase()} = this.items.filter((item) => item.type == "${(_b = property.document.ref) === null || _b === void 0 ? void 0 : _b.name.toLowerCase()}");
|
|
339
|
+
return expandToNode `
|
|
340
|
+
// ${property.name} Document Array Derived Data
|
|
341
|
+
this.system.${property.name.toLowerCase()} = this.items.filter((item) => item.type == "${(_b = property.document.ref) === null || _b === void 0 ? void 0 : _b.name.toLowerCase()}");
|
|
342
342
|
`.appendNewLineIfNotEmpty();
|
|
343
343
|
}
|
|
344
344
|
if (isMeasuredTemplateField(property)) {
|
|
345
|
-
return expandToNode `
|
|
346
|
-
// ${property.name} Measured Template Field Derived Data
|
|
347
|
-
|
|
348
|
-
const ${property.name.toLowerCase()}Summary = () => {
|
|
349
|
-
let sum = \`\${this.system.${property.name.toLowerCase()}.direction}° \${this.system.${property.name.toLowerCase()}.type} (\${this.system.${property.name.toLowerCase()}.distance} squares)\`;
|
|
350
|
-
if (this.system.${property.name.toLowerCase()}.type === 'cone') sum += \` \${this.system.${property.name.toLowerCase()}.angle}° angle\`;
|
|
351
|
-
if (this.system.${property.name.toLowerCase()}.type === 'ray') sum += \` \${this.system.${property.name.toLowerCase()}.width} squares wide\`;
|
|
352
|
-
return sum;
|
|
353
|
-
}
|
|
354
|
-
this.system.${property.name.toLowerCase()}.summary = ${property.name.toLowerCase()}Summary();
|
|
345
|
+
return expandToNode `
|
|
346
|
+
// ${property.name} Measured Template Field Derived Data
|
|
347
|
+
|
|
348
|
+
const ${property.name.toLowerCase()}Summary = () => {
|
|
349
|
+
let sum = \`\${this.system.${property.name.toLowerCase()}.direction}° \${this.system.${property.name.toLowerCase()}.type} (\${this.system.${property.name.toLowerCase()}.distance} squares)\`;
|
|
350
|
+
if (this.system.${property.name.toLowerCase()}.type === 'cone') sum += \` \${this.system.${property.name.toLowerCase()}.angle}° angle\`;
|
|
351
|
+
if (this.system.${property.name.toLowerCase()}.type === 'ray') sum += \` \${this.system.${property.name.toLowerCase()}.width} squares wide\`;
|
|
352
|
+
return sum;
|
|
353
|
+
}
|
|
354
|
+
this.system.${property.name.toLowerCase()}.summary = ${property.name.toLowerCase()}Summary();
|
|
355
355
|
`.appendNewLineIfNotEmpty();
|
|
356
356
|
}
|
|
357
357
|
if (isDiceField(property)) {
|
|
358
|
-
return expandToNode `
|
|
359
|
-
// ${property.name} Dice Field Derived Data
|
|
360
|
-
|
|
361
|
-
const ${property.name.toLowerCase()}Value = () => {
|
|
362
|
-
// Output a string of num + die
|
|
363
|
-
return this.system.${property.name.toLowerCase()}.number + this.system.${property.name.toLowerCase()}.die;
|
|
364
|
-
}
|
|
365
|
-
this.system.${property.name.toLowerCase()}.value = ${property.name.toLowerCase()}Value();
|
|
358
|
+
return expandToNode `
|
|
359
|
+
// ${property.name} Dice Field Derived Data
|
|
360
|
+
|
|
361
|
+
const ${property.name.toLowerCase()}Value = () => {
|
|
362
|
+
// Output a string of num + die
|
|
363
|
+
return this.system.${property.name.toLowerCase()}.number + this.system.${property.name.toLowerCase()}.die;
|
|
364
|
+
}
|
|
365
|
+
this.system.${property.name.toLowerCase()}.value = ${property.name.toLowerCase()}Value();
|
|
366
366
|
`.appendNewLineIfNotEmpty();
|
|
367
367
|
}
|
|
368
368
|
// if (isParentPropertyRefExp(property)) {
|
|
@@ -644,78 +644,78 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
644
644
|
.filter(f => functionIsDerivedSafe(f));
|
|
645
645
|
function generateDerivedFunction(functionDef) {
|
|
646
646
|
const params = functionDef.params.map(p => p.param.name);
|
|
647
|
-
return expandToNode `
|
|
648
|
-
const function_${functionDef.name} = (system${params.length ? ", " + params.join(", ") : ""}) => {
|
|
649
|
-
const context = { object: this };
|
|
650
|
-
${translateBodyExpressionToJavascript(entry, id, functionDef.method.body, true, functionDef)}
|
|
651
|
-
};
|
|
647
|
+
return expandToNode `
|
|
648
|
+
const function_${functionDef.name} = (system${params.length ? ", " + params.join(", ") : ""}) => {
|
|
649
|
+
const context = { object: this };
|
|
650
|
+
${translateBodyExpressionToJavascript(entry, id, functionDef.method.body, true, functionDef)}
|
|
651
|
+
};
|
|
652
652
|
`;
|
|
653
653
|
}
|
|
654
|
-
return expandToNode `
|
|
655
|
-
async _prepare${document.name}DerivedData() {
|
|
656
|
-
const editMode = this.flags["${id}"]?.["edit-mode"] ?? true;
|
|
657
|
-
|
|
658
|
-
${joinToNode(derivedFunctions, generateDerivedFunction, { appendNewLineIfNotEmpty: true })}
|
|
659
|
-
|
|
660
|
-
${cycles.length > 0 ? expandToNode `
|
|
661
|
-
// WARNING: Dependency cycles detected: ${cycles.map(cycle => cycle.join(' -> ')).join(', ')}
|
|
662
|
-
// Properties will be processed in original order to prevent infinite loops.
|
|
663
|
-
`.appendNewLine() : ""}
|
|
664
|
-
|
|
665
|
-
${joinToNode(sorted.map(dep => dep.property), property => generateDerivedAttribute(property), { appendNewLineIfNotEmpty: true })}
|
|
666
|
-
|
|
667
|
-
${isActor(document) ? expandToNode `
|
|
668
|
-
// Reapply Active Effects for calculated values
|
|
669
|
-
${joinToNode(toBeReapplied, name => expandToNode `this.reapplyActiveEffectsForName("${name}");`, { appendNewLineIfNotEmpty: true })}
|
|
670
|
-
|
|
671
|
-
// Bridge fighter.system.* active effect overrides into system.* for flat (non-nested) fields.
|
|
672
|
-
// allApplicableEffects cannot strip the type prefix in V14 (changes is getter-only),
|
|
673
|
-
// so Foundry applies flat fields (e.g. bonusdamage, resistanceflat) to actor.fighter.system.*
|
|
674
|
-
// Nested fields (e.g. fight.value) are handled by reapplyActiveEffectsForName above.
|
|
675
|
-
const _typeOverrides = this.overrides?.${document.name.toLowerCase()}?.system ?? {};
|
|
676
|
-
for (const [_k, _v] of Object.entries(_typeOverrides)) {
|
|
677
|
-
if (typeof _v !== 'object' && _k in this.system) {
|
|
678
|
-
this.system[_k] = _v;
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
` : ""}
|
|
682
|
-
}
|
|
654
|
+
return expandToNode `
|
|
655
|
+
async _prepare${document.name}DerivedData() {
|
|
656
|
+
const editMode = this.flags["${id}"]?.["edit-mode"] ?? true;
|
|
657
|
+
|
|
658
|
+
${joinToNode(derivedFunctions, generateDerivedFunction, { appendNewLineIfNotEmpty: true })}
|
|
659
|
+
|
|
660
|
+
${cycles.length > 0 ? expandToNode `
|
|
661
|
+
// WARNING: Dependency cycles detected: ${cycles.map(cycle => cycle.join(' -> ')).join(', ')}
|
|
662
|
+
// Properties will be processed in original order to prevent infinite loops.
|
|
663
|
+
`.appendNewLine() : ""}
|
|
664
|
+
|
|
665
|
+
${joinToNode(sorted.map(dep => dep.property), property => generateDerivedAttribute(property), { appendNewLineIfNotEmpty: true })}
|
|
666
|
+
|
|
667
|
+
${isActor(document) ? expandToNode `
|
|
668
|
+
// Reapply Active Effects for calculated values
|
|
669
|
+
${joinToNode(toBeReapplied, name => expandToNode `this.reapplyActiveEffectsForName("${name}");`, { appendNewLineIfNotEmpty: true })}
|
|
670
|
+
|
|
671
|
+
// Bridge fighter.system.* active effect overrides into system.* for flat (non-nested) fields.
|
|
672
|
+
// allApplicableEffects cannot strip the type prefix in V14 (changes is getter-only),
|
|
673
|
+
// so Foundry applies flat fields (e.g. bonusdamage, resistanceflat) to actor.fighter.system.*
|
|
674
|
+
// Nested fields (e.g. fight.value) are handled by reapplyActiveEffectsForName above.
|
|
675
|
+
const _typeOverrides = this.overrides?.${document.name.toLowerCase()}?.system ?? {};
|
|
676
|
+
for (const [_k, _v] of Object.entries(_typeOverrides)) {
|
|
677
|
+
if (typeof _v !== 'object' && _k in this.system) {
|
|
678
|
+
this.system[_k] = _v;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
` : ""}
|
|
682
|
+
}
|
|
683
683
|
`.appendNewLineIfNotEmpty().appendNewLine();
|
|
684
684
|
}
|
|
685
685
|
function generateActorPreUpdate(document) {
|
|
686
686
|
const allResources = getAllOfType(document.body, isResourceExp);
|
|
687
687
|
const healthResource = allResources.find(x => x.tag == "health");
|
|
688
688
|
if (healthResource == undefined)
|
|
689
|
-
return expandToNode `
|
|
690
|
-
_handlePreUpdate${document.name}Delta(changes, deltas) {
|
|
691
|
-
// No health resource defined
|
|
692
|
-
}
|
|
689
|
+
return expandToNode `
|
|
690
|
+
_handlePreUpdate${document.name}Delta(changes, deltas) {
|
|
691
|
+
// No health resource defined
|
|
692
|
+
}
|
|
693
693
|
`.appendNewLine();
|
|
694
|
-
return expandToNode `
|
|
695
|
-
_handlePreUpdate${document.name}Delta(changes, deltas) {
|
|
696
|
-
// Health resource updates
|
|
697
|
-
if (changes.system.${healthResource.name.toLowerCase()} === undefined) return;
|
|
698
|
-
|
|
699
|
-
// Store value and temp changes
|
|
700
|
-
const valueChange = changes.system.${healthResource.name.toLowerCase()}.value;
|
|
701
|
-
const tempChange = changes.system.${healthResource.name.toLowerCase()}.temp;
|
|
702
|
-
|
|
703
|
-
// Calculate delta
|
|
704
|
-
if (valueChange !== undefined) {
|
|
705
|
-
const delta = valueChange - this.system.${healthResource.name.toLowerCase()}.value;
|
|
706
|
-
if (delta !== 0) {
|
|
707
|
-
deltas.${healthResource.name.toLowerCase()} = delta;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// Calculate temp delta
|
|
712
|
-
if (tempChange !== undefined) {
|
|
713
|
-
const tempDelta = tempChange - this.system.${healthResource.name.toLowerCase()}.temp;
|
|
714
|
-
if (tempDelta !== 0) {
|
|
715
|
-
deltas.${healthResource.name.toLowerCase()}Temp = tempDelta;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
694
|
+
return expandToNode `
|
|
695
|
+
_handlePreUpdate${document.name}Delta(changes, deltas) {
|
|
696
|
+
// Health resource updates
|
|
697
|
+
if (changes.system.${healthResource.name.toLowerCase()} === undefined) return;
|
|
698
|
+
|
|
699
|
+
// Store value and temp changes
|
|
700
|
+
const valueChange = changes.system.${healthResource.name.toLowerCase()}.value;
|
|
701
|
+
const tempChange = changes.system.${healthResource.name.toLowerCase()}.temp;
|
|
702
|
+
|
|
703
|
+
// Calculate delta
|
|
704
|
+
if (valueChange !== undefined) {
|
|
705
|
+
const delta = valueChange - this.system.${healthResource.name.toLowerCase()}.value;
|
|
706
|
+
if (delta !== 0) {
|
|
707
|
+
deltas.${healthResource.name.toLowerCase()} = delta;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Calculate temp delta
|
|
712
|
+
if (tempChange !== undefined) {
|
|
713
|
+
const tempDelta = tempChange - this.system.${healthResource.name.toLowerCase()}.temp;
|
|
714
|
+
if (tempDelta !== 0) {
|
|
715
|
+
deltas.${healthResource.name.toLowerCase()}Temp = tempDelta;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
719
|
`.appendNewLine();
|
|
720
720
|
}
|
|
721
721
|
function generateDeltas(documents) {
|
|
@@ -726,179 +726,179 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
726
726
|
const healthResource = getAllOfType(document.body, isResourceExp).find(x => x.tag == "health");
|
|
727
727
|
if (healthResource == undefined)
|
|
728
728
|
return;
|
|
729
|
-
return expandToNode `
|
|
730
|
-
case "${document.name.toLowerCase()}": {
|
|
731
|
-
// ${healthResource.name} health resource
|
|
732
|
-
|
|
733
|
-
if ( !data.prototypeToken.bar1.attribute ) data.prototypeToken.bar1.attribute = "${healthResource.name.toLowerCase()}";
|
|
734
|
-
if ( !data.prototypeToken.displayBars ) data.prototypeToken.displayBars = CONST.TOKEN_DISPLAY_MODES.ALWAYS;
|
|
735
|
-
}
|
|
729
|
+
return expandToNode `
|
|
730
|
+
case "${document.name.toLowerCase()}": {
|
|
731
|
+
// ${healthResource.name} health resource
|
|
732
|
+
|
|
733
|
+
if ( !data.prototypeToken.bar1.attribute ) data.prototypeToken.bar1.attribute = "${healthResource.name.toLowerCase()}";
|
|
734
|
+
if ( !data.prototypeToken.displayBars ) data.prototypeToken.displayBars = CONST.TOKEN_DISPLAY_MODES.ALWAYS;
|
|
735
|
+
}
|
|
736
736
|
`.appendNewLineIfNotEmpty();
|
|
737
737
|
}
|
|
738
|
-
return expandToNode `
|
|
739
|
-
switch ( data.type ) {
|
|
740
|
-
${joinToNode(documents.filter(x => isActor(x)), document => documentHealthResource(document), { appendNewLineIfNotEmpty: true })}
|
|
741
|
-
}
|
|
738
|
+
return expandToNode `
|
|
739
|
+
switch ( data.type ) {
|
|
740
|
+
${joinToNode(documents.filter(x => isActor(x)), document => documentHealthResource(document), { appendNewLineIfNotEmpty: true })}
|
|
741
|
+
}
|
|
742
742
|
`.appendNewLineIfNotEmpty();
|
|
743
743
|
}
|
|
744
|
-
return expandToNode `
|
|
745
|
-
async _preUpdate(data, options, userId) {
|
|
746
|
-
await super._preUpdate(data, options, userId);
|
|
747
|
-
if (!options.diff || data === undefined) return;
|
|
748
|
-
let changes = {};
|
|
749
|
-
|
|
750
|
-
// Foundry v12 no longer has diffed data during _preUpdate, so we need to compute it ourselves.
|
|
751
|
-
if (game.release.version >= 12) {
|
|
752
|
-
// Retrieve a copy of the existing actor data.
|
|
753
|
-
let newData = game.system.utils.flattenObject(data);
|
|
754
|
-
let oldData = game.system.utils.flattenObject(this);
|
|
755
|
-
|
|
756
|
-
// Limit data to just the new data.
|
|
757
|
-
const diffData = foundry.utils.diffObject(oldData, newData);
|
|
758
|
-
changes = foundry.utils.expandObject(diffData);
|
|
759
|
-
}
|
|
760
|
-
else {
|
|
761
|
-
changes = foundry.utils.duplicate(data);
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
// Handle name changes
|
|
765
|
-
if (changes.name) {
|
|
766
|
-
let tokenData = {};
|
|
767
|
-
|
|
768
|
-
// Propagate name update to prototype token if same as actor
|
|
769
|
-
if (changes.name && this.name == this.prototypeToken.name) {
|
|
770
|
-
data.prototypeToken = {name: data.name};
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
// Update tokens.
|
|
774
|
-
let tokens = this.getActiveTokens();
|
|
775
|
-
tokens.forEach(token => {
|
|
776
|
-
let updateData = foundry.utils.duplicate(tokenData);
|
|
777
|
-
|
|
778
|
-
// Propagate name update to token if same as actor
|
|
779
|
-
if (data.name && this.name == token.name) {
|
|
780
|
-
updateData.name = data.name;
|
|
781
|
-
}
|
|
782
|
-
token.document.update(updateData);
|
|
783
|
-
});
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
if (changes.system === undefined) return; // Nothing more to do
|
|
787
|
-
|
|
788
|
-
const deltas = {};
|
|
789
|
-
|
|
790
|
-
${joinToNode(documents.filter(x => isActor(x)), document => expandToNode `
|
|
791
|
-
if (this.type == "${document.name.toLowerCase()}") this._handlePreUpdate${document.name}Delta(changes, deltas);
|
|
792
|
-
`, { appendNewLineIfNotEmpty: true })}
|
|
793
|
-
|
|
794
|
-
options.fromPreUpdate = deltas;
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
/* -------------------------------------------- */
|
|
798
|
-
|
|
799
|
-
${joinToNode(documents.filter(x => isActor(x)), document => generateActorPreUpdate(document), { appendNewLineIfNotEmpty: true })}
|
|
800
|
-
|
|
801
|
-
/* -------------------------------------------- */
|
|
802
|
-
|
|
803
|
-
async _onUpdate(data, options, userId) {
|
|
804
|
-
await super._onUpdate(data, options, userId);
|
|
805
|
-
|
|
806
|
-
// Iterate over all objects in fromPreUpdate, showing scrolling text for each.
|
|
807
|
-
if (options.fromPreUpdate) {
|
|
808
|
-
for (const [key, delta] of Object.entries(options.fromPreUpdate)) {
|
|
809
|
-
this._showScrollingText(delta, key);
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
// Add / remove status effects
|
|
814
|
-
const calculatedStatusEffects = CONFIG.statusEffects.filter(effect => effect.calculated);
|
|
815
|
-
for (const effect of calculatedStatusEffects) {
|
|
816
|
-
const key = effect.id;
|
|
817
|
-
const active = this.system[key] ?? false;
|
|
818
|
-
const existing = this.effects.find(e => e.statuses.has(key));
|
|
819
|
-
|
|
820
|
-
if ((active && existing) || (!active && !existing)) continue;
|
|
821
|
-
|
|
822
|
-
// If the effect is active the AE doesn't exist, add it
|
|
823
|
-
if (active && !existing) {
|
|
824
|
-
const cls = getDocumentClass("ActiveEffect");
|
|
825
|
-
const createData = foundry.utils.deepClone(effect);
|
|
826
|
-
createData.statuses = [key];
|
|
827
|
-
delete createData.id;
|
|
828
|
-
createData.name = game.i18n.localize(createData.name);
|
|
829
|
-
await cls.create(createData, {parent: this});
|
|
830
|
-
if (key == "dead") Hooks.callAll("death", this);
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
// If the effect is active the AE doesn't exist, add it
|
|
834
|
-
if (!active && existing) {
|
|
835
|
-
this.deleteEmbeddedDocuments("ActiveEffect", [existing.id]);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
/* -------------------------------------------- */
|
|
841
|
-
|
|
842
|
-
async _onCreate(data, options, userId) {
|
|
843
|
-
await super._onCreate(data, options, userId);
|
|
844
|
-
|
|
845
|
-
console.log("onCreate", data, options, userId);
|
|
846
|
-
|
|
847
|
-
${generateHealthResourceAssignments(documents)}
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
/* -------------------------------------------- */
|
|
851
|
-
|
|
852
|
-
_showScrollingText(delta, suffix="", overrideOptions={}) {
|
|
853
|
-
// Show scrolling text of hp update
|
|
854
|
-
const tokens = this.isToken ? [this.token?.object] : this.getActiveTokens(true);
|
|
855
|
-
if (delta != 0 && tokens.length > 0) {
|
|
856
|
-
let color = delta < 0 ? 0xcc0000 : 0x00cc00;
|
|
857
|
-
for ( let token of tokens ) {
|
|
858
|
-
let textOptions = {
|
|
859
|
-
anchor: CONST.TEXT_ANCHOR_POINTS.CENTER,
|
|
860
|
-
direction: CONST.TEXT_ANCHOR_POINTS.TOP,
|
|
861
|
-
fontSize: 32,
|
|
862
|
-
fill: color,
|
|
863
|
-
stroke: 0x000000,
|
|
864
|
-
strokeThickness: 4,
|
|
865
|
-
duration: 3000
|
|
866
|
-
};
|
|
867
|
-
canvas.interface.createScrollingText(
|
|
868
|
-
token.center,
|
|
869
|
-
delta.signedString()+" "+suffix,
|
|
870
|
-
foundry.utils.mergeObject(textOptions, overrideOptions)
|
|
871
|
-
);
|
|
872
|
-
// Flash dynamic token rings.
|
|
873
|
-
if (token?.ring) {
|
|
874
|
-
const flashColor = delta < 0 ? Color.fromString('#ff0000') : Color.fromString('#00ff00');
|
|
875
|
-
token.ring.flashColor(flashColor, {
|
|
876
|
-
duration: 600,
|
|
877
|
-
easing: foundry.canvas.tokens.TokenRing.easeTwoPeaks,
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
}
|
|
744
|
+
return expandToNode `
|
|
745
|
+
async _preUpdate(data, options, userId) {
|
|
746
|
+
await super._preUpdate(data, options, userId);
|
|
747
|
+
if (!options.diff || data === undefined) return;
|
|
748
|
+
let changes = {};
|
|
749
|
+
|
|
750
|
+
// Foundry v12 no longer has diffed data during _preUpdate, so we need to compute it ourselves.
|
|
751
|
+
if (game.release.version >= 12) {
|
|
752
|
+
// Retrieve a copy of the existing actor data.
|
|
753
|
+
let newData = game.system.utils.flattenObject(data);
|
|
754
|
+
let oldData = game.system.utils.flattenObject(this);
|
|
755
|
+
|
|
756
|
+
// Limit data to just the new data.
|
|
757
|
+
const diffData = foundry.utils.diffObject(oldData, newData);
|
|
758
|
+
changes = foundry.utils.expandObject(diffData);
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
changes = foundry.utils.duplicate(data);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// Handle name changes
|
|
765
|
+
if (changes.name) {
|
|
766
|
+
let tokenData = {};
|
|
767
|
+
|
|
768
|
+
// Propagate name update to prototype token if same as actor
|
|
769
|
+
if (changes.name && this.name == this.prototypeToken.name) {
|
|
770
|
+
data.prototypeToken = {name: data.name};
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Update tokens.
|
|
774
|
+
let tokens = this.getActiveTokens();
|
|
775
|
+
tokens.forEach(token => {
|
|
776
|
+
let updateData = foundry.utils.duplicate(tokenData);
|
|
777
|
+
|
|
778
|
+
// Propagate name update to token if same as actor
|
|
779
|
+
if (data.name && this.name == token.name) {
|
|
780
|
+
updateData.name = data.name;
|
|
781
|
+
}
|
|
782
|
+
token.document.update(updateData);
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
if (changes.system === undefined) return; // Nothing more to do
|
|
787
|
+
|
|
788
|
+
const deltas = {};
|
|
789
|
+
|
|
790
|
+
${joinToNode(documents.filter(x => isActor(x)), document => expandToNode `
|
|
791
|
+
if (this.type == "${document.name.toLowerCase()}") this._handlePreUpdate${document.name}Delta(changes, deltas);
|
|
792
|
+
`, { appendNewLineIfNotEmpty: true })}
|
|
793
|
+
|
|
794
|
+
options.fromPreUpdate = deltas;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/* -------------------------------------------- */
|
|
798
|
+
|
|
799
|
+
${joinToNode(documents.filter(x => isActor(x)), document => generateActorPreUpdate(document), { appendNewLineIfNotEmpty: true })}
|
|
800
|
+
|
|
801
|
+
/* -------------------------------------------- */
|
|
802
|
+
|
|
803
|
+
async _onUpdate(data, options, userId) {
|
|
804
|
+
await super._onUpdate(data, options, userId);
|
|
805
|
+
|
|
806
|
+
// Iterate over all objects in fromPreUpdate, showing scrolling text for each.
|
|
807
|
+
if (options.fromPreUpdate) {
|
|
808
|
+
for (const [key, delta] of Object.entries(options.fromPreUpdate)) {
|
|
809
|
+
this._showScrollingText(delta, key);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Add / remove status effects
|
|
814
|
+
const calculatedStatusEffects = CONFIG.statusEffects.filter(effect => effect.calculated);
|
|
815
|
+
for (const effect of calculatedStatusEffects) {
|
|
816
|
+
const key = effect.id;
|
|
817
|
+
const active = this.system[key] ?? false;
|
|
818
|
+
const existing = this.effects.find(e => e.statuses.has(key));
|
|
819
|
+
|
|
820
|
+
if ((active && existing) || (!active && !existing)) continue;
|
|
821
|
+
|
|
822
|
+
// If the effect is active the AE doesn't exist, add it
|
|
823
|
+
if (active && !existing) {
|
|
824
|
+
const cls = getDocumentClass("ActiveEffect");
|
|
825
|
+
const createData = foundry.utils.deepClone(effect);
|
|
826
|
+
createData.statuses = [key];
|
|
827
|
+
delete createData.id;
|
|
828
|
+
createData.name = game.i18n.localize(createData.name);
|
|
829
|
+
await cls.create(createData, {parent: this});
|
|
830
|
+
if (key == "dead") Hooks.callAll("death", this);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// If the effect is active the AE doesn't exist, add it
|
|
834
|
+
if (!active && existing) {
|
|
835
|
+
this.deleteEmbeddedDocuments("ActiveEffect", [existing.id]);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/* -------------------------------------------- */
|
|
841
|
+
|
|
842
|
+
async _onCreate(data, options, userId) {
|
|
843
|
+
await super._onCreate(data, options, userId);
|
|
844
|
+
|
|
845
|
+
console.log("onCreate", data, options, userId);
|
|
846
|
+
|
|
847
|
+
${generateHealthResourceAssignments(documents)}
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
/* -------------------------------------------- */
|
|
851
|
+
|
|
852
|
+
_showScrollingText(delta, suffix="", overrideOptions={}) {
|
|
853
|
+
// Show scrolling text of hp update
|
|
854
|
+
const tokens = this.isToken ? [this.token?.object] : this.getActiveTokens(true);
|
|
855
|
+
if (delta != 0 && tokens.length > 0) {
|
|
856
|
+
let color = delta < 0 ? 0xcc0000 : 0x00cc00;
|
|
857
|
+
for ( let token of tokens ) {
|
|
858
|
+
let textOptions = {
|
|
859
|
+
anchor: CONST.TEXT_ANCHOR_POINTS.CENTER,
|
|
860
|
+
direction: CONST.TEXT_ANCHOR_POINTS.TOP,
|
|
861
|
+
fontSize: 32,
|
|
862
|
+
fill: color,
|
|
863
|
+
stroke: 0x000000,
|
|
864
|
+
strokeThickness: 4,
|
|
865
|
+
duration: 3000
|
|
866
|
+
};
|
|
867
|
+
canvas.interface.createScrollingText(
|
|
868
|
+
token.center,
|
|
869
|
+
delta.signedString()+" "+suffix,
|
|
870
|
+
foundry.utils.mergeObject(textOptions, overrideOptions)
|
|
871
|
+
);
|
|
872
|
+
// Flash dynamic token rings.
|
|
873
|
+
if (token?.ring) {
|
|
874
|
+
const flashColor = delta < 0 ? Color.fromString('#ff0000') : Color.fromString('#00ff00');
|
|
875
|
+
token.ring.flashColor(flashColor, {
|
|
876
|
+
duration: 600,
|
|
877
|
+
easing: foundry.canvas.tokens.TokenRing.easeTwoPeaks,
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
883
|
`.appendNewLineIfNotEmpty();
|
|
884
884
|
}
|
|
885
885
|
function generateInitiativeFormula(document) {
|
|
886
886
|
var _a;
|
|
887
887
|
const initiativeAttribute = getAllOfType(document.body, isInitiativeProperty);
|
|
888
888
|
if (initiativeAttribute.length == 0) {
|
|
889
|
-
return expandToNode `
|
|
890
|
-
case "${document.name.toLowerCase()}": return "0";
|
|
889
|
+
return expandToNode `
|
|
890
|
+
case "${document.name.toLowerCase()}": return "0";
|
|
891
891
|
`.appendNewLineIfNotEmpty();
|
|
892
892
|
}
|
|
893
893
|
let initiative = (_a = initiativeAttribute[0]) === null || _a === void 0 ? void 0 : _a.value;
|
|
894
894
|
if (initiative == undefined) {
|
|
895
|
-
return expandToNode `
|
|
896
|
-
case "${document.name.toLowerCase()}": return "0";
|
|
895
|
+
return expandToNode `
|
|
896
|
+
case "${document.name.toLowerCase()}": return "0";
|
|
897
897
|
`.appendNewLineIfNotEmpty();
|
|
898
898
|
}
|
|
899
899
|
console.log("Initiative Formula");
|
|
900
|
-
return expandToNode `
|
|
901
|
-
case "${document.name.toLowerCase()}": return "${translateExpression(entry, id, initiative, true, initiativeAttribute[0])}";
|
|
900
|
+
return expandToNode `
|
|
901
|
+
case "${document.name.toLowerCase()}": return "${translateExpression(entry, id, initiative, true, initiativeAttribute[0])}";
|
|
902
902
|
`.appendNewLineIfNotEmpty();
|
|
903
903
|
}
|
|
904
904
|
function generateDocumentHooks(document) {
|
|
@@ -907,177 +907,177 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
907
907
|
var _a;
|
|
908
908
|
let name = hook.name;
|
|
909
909
|
function generateBody() {
|
|
910
|
-
return expandToNode `
|
|
911
|
-
const ${entry.config.name}Roll = game.system.rollClass;
|
|
912
|
-
const ${entry.config.name}DamageRoll = game.system.damageRollClass;
|
|
913
|
-
const context = {
|
|
914
|
-
object: document,
|
|
915
|
-
target: game.user.getTargetOrNothing()
|
|
916
|
-
};
|
|
917
|
-
const system = document.system;
|
|
918
|
-
let update = {};
|
|
919
|
-
let embeddedUpdate = {};
|
|
920
|
-
let parentUpdate = {};
|
|
921
|
-
let parentEmbeddedUpdate = {};
|
|
922
|
-
let targetUpdate = {};
|
|
923
|
-
let targetEmbeddedUpdate = {};
|
|
924
|
-
let selfDeleted = false;
|
|
925
|
-
|
|
926
|
-
${translateBodyExpressionToJavascript(entry, id, hook.body, false, hook)}
|
|
927
|
-
|
|
928
|
-
if (!selfDeleted && Object.keys(update).length > 0) {
|
|
929
|
-
await document.update(update);
|
|
930
|
-
}
|
|
931
|
-
if (!selfDeleted && Object.keys(embeddedUpdate).length > 0) {
|
|
932
|
-
for (let key of Object.keys(embeddedUpdate)) {
|
|
933
|
-
await document.updateEmbeddedDocuments("Item", embeddedUpdate[key]);
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
if (Object.keys(parentUpdate).length > 0) {
|
|
937
|
-
await document.parent.update(parentUpdate);
|
|
938
|
-
}
|
|
939
|
-
if (Object.keys(parentEmbeddedUpdate).length > 0) {
|
|
940
|
-
for (let key of Object.keys(parentEmbeddedUpdate)) {
|
|
941
|
-
await document.parent.updateEmbeddedDocuments("Item", parentEmbeddedUpdate[key]);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
if (Object.keys(targetUpdate).length > 0) {
|
|
945
|
-
await context.target.update(targetUpdate);
|
|
946
|
-
}
|
|
947
|
-
if (Object.keys(targetEmbeddedUpdate).length > 0) {
|
|
948
|
-
for (let key of Object.keys(targetEmbeddedUpdate)) {
|
|
949
|
-
await context.target.updateEmbeddedDocuments("Item", targetEmbeddedUpdate[key]);
|
|
950
|
-
}
|
|
951
|
-
}
|
|
910
|
+
return expandToNode `
|
|
911
|
+
const ${entry.config.name}Roll = game.system.rollClass;
|
|
912
|
+
const ${entry.config.name}DamageRoll = game.system.damageRollClass;
|
|
913
|
+
const context = {
|
|
914
|
+
object: document,
|
|
915
|
+
target: game.user.getTargetOrNothing()
|
|
916
|
+
};
|
|
917
|
+
const system = document.system;
|
|
918
|
+
let update = {};
|
|
919
|
+
let embeddedUpdate = {};
|
|
920
|
+
let parentUpdate = {};
|
|
921
|
+
let parentEmbeddedUpdate = {};
|
|
922
|
+
let targetUpdate = {};
|
|
923
|
+
let targetEmbeddedUpdate = {};
|
|
924
|
+
let selfDeleted = false;
|
|
925
|
+
|
|
926
|
+
${translateBodyExpressionToJavascript(entry, id, hook.body, false, hook)}
|
|
927
|
+
|
|
928
|
+
if (!selfDeleted && Object.keys(update).length > 0) {
|
|
929
|
+
await document.update(update);
|
|
930
|
+
}
|
|
931
|
+
if (!selfDeleted && Object.keys(embeddedUpdate).length > 0) {
|
|
932
|
+
for (let key of Object.keys(embeddedUpdate)) {
|
|
933
|
+
await document.updateEmbeddedDocuments("Item", embeddedUpdate[key]);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
if (Object.keys(parentUpdate).length > 0) {
|
|
937
|
+
await document.parent.update(parentUpdate);
|
|
938
|
+
}
|
|
939
|
+
if (Object.keys(parentEmbeddedUpdate).length > 0) {
|
|
940
|
+
for (let key of Object.keys(parentEmbeddedUpdate)) {
|
|
941
|
+
await document.parent.updateEmbeddedDocuments("Item", parentEmbeddedUpdate[key]);
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
if (Object.keys(targetUpdate).length > 0) {
|
|
945
|
+
await context.target.update(targetUpdate);
|
|
946
|
+
}
|
|
947
|
+
if (Object.keys(targetEmbeddedUpdate).length > 0) {
|
|
948
|
+
for (let key of Object.keys(targetEmbeddedUpdate)) {
|
|
949
|
+
await context.target.updateEmbeddedDocuments("Item", targetEmbeddedUpdate[key]);
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
952
|
`;
|
|
953
953
|
}
|
|
954
954
|
switch (name) {
|
|
955
955
|
case "combatStart":
|
|
956
|
-
return expandToNode `
|
|
957
|
-
Hooks.on("combatStart", async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
958
|
-
${generateBody()}
|
|
959
|
-
});
|
|
956
|
+
return expandToNode `
|
|
957
|
+
Hooks.on("combatStart", async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
958
|
+
${generateBody()}
|
|
959
|
+
});
|
|
960
960
|
`.appendNewLineIfNotEmpty();
|
|
961
961
|
case "combatEnd":
|
|
962
|
-
return expandToNode `
|
|
963
|
-
Hooks.on("deleteCombat", async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
964
|
-
${generateBody()}
|
|
965
|
-
});
|
|
962
|
+
return expandToNode `
|
|
963
|
+
Hooks.on("deleteCombat", async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
964
|
+
${generateBody()}
|
|
965
|
+
});
|
|
966
966
|
`.appendNewLineIfNotEmpty();
|
|
967
967
|
case "roundStart":
|
|
968
|
-
return expandToNode `
|
|
969
|
-
Hooks.on("combatRound", async (combat, updateData, updateOptions) => {
|
|
970
|
-
const roundStart = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
971
|
-
${generateBody()}
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
if (updateData.turn == 0) {
|
|
975
|
-
await roundStart(updateData.round);
|
|
976
|
-
}
|
|
977
|
-
});
|
|
968
|
+
return expandToNode `
|
|
969
|
+
Hooks.on("combatRound", async (combat, updateData, updateOptions) => {
|
|
970
|
+
const roundStart = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
971
|
+
${generateBody()}
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
if (updateData.turn == 0) {
|
|
975
|
+
await roundStart(updateData.round);
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
978
|
`.appendNewLineIfNotEmpty();
|
|
979
979
|
case "roundEnd":
|
|
980
|
-
return expandToNode `
|
|
981
|
-
Hooks.on("combatRound", async (combat, updateData, updateOptions) => {
|
|
982
|
-
const roundEnd = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
983
|
-
${generateBody()}
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
if (updateData.round > 0) {
|
|
987
|
-
roundEnd(updateData.round - 1);
|
|
988
|
-
}
|
|
989
|
-
});
|
|
980
|
+
return expandToNode `
|
|
981
|
+
Hooks.on("combatRound", async (combat, updateData, updateOptions) => {
|
|
982
|
+
const roundEnd = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
983
|
+
${generateBody()}
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
if (updateData.round > 0) {
|
|
987
|
+
roundEnd(updateData.round - 1);
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
990
|
`.appendNewLineIfNotEmpty();
|
|
991
991
|
case "turnStart":
|
|
992
|
-
return expandToNode `
|
|
993
|
-
Hooks.on("combatTurnChange", async (combat, updateData, updateOptions) => {
|
|
994
|
-
const turnStart = async () => {
|
|
995
|
-
${generateBody()}
|
|
996
|
-
}
|
|
997
|
-
if (combat.combatant.actor.uuid == document.uuid) {
|
|
998
|
-
await turnStart();
|
|
999
|
-
}
|
|
1000
|
-
});
|
|
992
|
+
return expandToNode `
|
|
993
|
+
Hooks.on("combatTurnChange", async (combat, updateData, updateOptions) => {
|
|
994
|
+
const turnStart = async () => {
|
|
995
|
+
${generateBody()}
|
|
996
|
+
}
|
|
997
|
+
if (combat.combatant.actor.uuid == document.uuid) {
|
|
998
|
+
await turnStart();
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
1001
|
`.appendNewLineIfNotEmpty();
|
|
1002
1002
|
case "turnEnd":
|
|
1003
|
-
return expandToNode `
|
|
1004
|
-
Hooks.on("combatTurnChange", async (combat, updateData, updateOptions) => {
|
|
1005
|
-
const turnEnd = async () => {
|
|
1006
|
-
${generateBody()}
|
|
1007
|
-
}
|
|
1008
|
-
const previousCombatant = combat.combatants.get(combat.previous?.combatantId);
|
|
1009
|
-
if (previousCombatant?.actor?.uuid == document.uuid) {
|
|
1010
|
-
await turnEnd();
|
|
1011
|
-
}
|
|
1012
|
-
});
|
|
1003
|
+
return expandToNode `
|
|
1004
|
+
Hooks.on("combatTurnChange", async (combat, updateData, updateOptions) => {
|
|
1005
|
+
const turnEnd = async () => {
|
|
1006
|
+
${generateBody()}
|
|
1007
|
+
}
|
|
1008
|
+
const previousCombatant = combat.combatants.get(combat.previous?.combatantId);
|
|
1009
|
+
if (previousCombatant?.actor?.uuid == document.uuid) {
|
|
1010
|
+
await turnEnd();
|
|
1011
|
+
}
|
|
1012
|
+
});
|
|
1013
1013
|
`.appendNewLineIfNotEmpty();
|
|
1014
1014
|
case "turnIsNext":
|
|
1015
|
-
return expandToNode `
|
|
1016
|
-
Hooks.on("combatTurnChange", async (combat, updateData, updateOptions) => {
|
|
1017
|
-
const turnIsNext = async () => {
|
|
1018
|
-
${generateBody()}
|
|
1019
|
-
};
|
|
1020
|
-
if (combat.nextCombatant.actor.uuid == document.uuid) {
|
|
1021
|
-
await turnIsNext();
|
|
1022
|
-
}
|
|
1023
|
-
});
|
|
1015
|
+
return expandToNode `
|
|
1016
|
+
Hooks.on("combatTurnChange", async (combat, updateData, updateOptions) => {
|
|
1017
|
+
const turnIsNext = async () => {
|
|
1018
|
+
${generateBody()}
|
|
1019
|
+
};
|
|
1020
|
+
if (combat.nextCombatant.actor.uuid == document.uuid) {
|
|
1021
|
+
await turnIsNext();
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
1024
|
`.appendNewLineIfNotEmpty();
|
|
1025
1025
|
case "death":
|
|
1026
|
-
return expandToNode `
|
|
1027
|
-
Hooks.on("death", async (deadDocument) => {
|
|
1028
|
-
const onDeath = async () => {
|
|
1029
|
-
${generateBody()}
|
|
1030
|
-
};
|
|
1031
|
-
if ( deadDocument.uuid == document.uuid ) {
|
|
1032
|
-
await onDeath();
|
|
1033
|
-
}
|
|
1034
|
-
});
|
|
1026
|
+
return expandToNode `
|
|
1027
|
+
Hooks.on("death", async (deadDocument) => {
|
|
1028
|
+
const onDeath = async () => {
|
|
1029
|
+
${generateBody()}
|
|
1030
|
+
};
|
|
1031
|
+
if ( deadDocument.uuid == document.uuid ) {
|
|
1032
|
+
await onDeath();
|
|
1033
|
+
}
|
|
1034
|
+
});
|
|
1035
1035
|
`.appendNewLineIfNotEmpty();
|
|
1036
1036
|
case "preApplyDamage":
|
|
1037
1037
|
case "preApplyHealing":
|
|
1038
1038
|
case "preApplyTemp":
|
|
1039
|
-
return expandToNode `
|
|
1040
|
-
if (game.system.documentHooks.has("${name}-" + this.uuid)) return;
|
|
1041
|
-
const on${name} = async (document, context) => {
|
|
1042
|
-
const preApply = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
1043
|
-
${generateBody()}
|
|
1044
|
-
return ${(_a = hook.params.shift()) === null || _a === void 0 ? void 0 : _a.name};
|
|
1045
|
-
}
|
|
1046
|
-
if (document.uuid == this.uuid) {
|
|
1047
|
-
context.amount = await preApply(context.amount, context.damageType, context.damageMetadata);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
game.system.documentHooks.set("${name}-" + this.uuid, on${name});
|
|
1051
|
-
Hooks.on("${name}", on${name});
|
|
1039
|
+
return expandToNode `
|
|
1040
|
+
if (game.system.documentHooks.has("${name}-" + this.uuid)) return;
|
|
1041
|
+
const on${name} = async (document, context) => {
|
|
1042
|
+
const preApply = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
1043
|
+
${generateBody()}
|
|
1044
|
+
return ${(_a = hook.params.shift()) === null || _a === void 0 ? void 0 : _a.name};
|
|
1045
|
+
}
|
|
1046
|
+
if (document.uuid == this.uuid) {
|
|
1047
|
+
context.amount = await preApply(context.amount, context.damageType, context.damageMetadata);
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
game.system.documentHooks.set("${name}-" + this.uuid, on${name});
|
|
1051
|
+
Hooks.on("${name}", on${name});
|
|
1052
1052
|
`.appendNewLineIfNotEmpty();
|
|
1053
1053
|
case "appliedDamage":
|
|
1054
1054
|
case "appliedHealing":
|
|
1055
1055
|
case "appliedTemp":
|
|
1056
|
-
return expandToNode `
|
|
1057
|
-
if (game.system.documentHooks.has("${name}-" + this.uuid)) return;
|
|
1058
|
-
const on${name} = async (document, context) => {
|
|
1059
|
-
const applied = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
1060
|
-
${generateBody()}
|
|
1061
|
-
}
|
|
1062
|
-
if (document.uuid == this.uuid) {
|
|
1063
|
-
await applied(context.amount, context.damageType, context.damageMetadata);
|
|
1064
|
-
}
|
|
1065
|
-
};
|
|
1066
|
-
game.system.documentHooks.set("${name}-" + this.uuid, on${name});
|
|
1067
|
-
Hooks.on("${name}", on${name});
|
|
1056
|
+
return expandToNode `
|
|
1057
|
+
if (game.system.documentHooks.has("${name}-" + this.uuid)) return;
|
|
1058
|
+
const on${name} = async (document, context) => {
|
|
1059
|
+
const applied = async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
1060
|
+
${generateBody()}
|
|
1061
|
+
}
|
|
1062
|
+
if (document.uuid == this.uuid) {
|
|
1063
|
+
await applied(context.amount, context.damageType, context.damageMetadata);
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
game.system.documentHooks.set("${name}-" + this.uuid, on${name});
|
|
1067
|
+
Hooks.on("${name}", on${name});
|
|
1068
1068
|
`.appendNewLineIfNotEmpty();
|
|
1069
1069
|
default:
|
|
1070
|
-
return expandToNode `
|
|
1071
|
-
Hooks.on("${name}", async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
1072
|
-
${generateBody()}
|
|
1073
|
-
});
|
|
1070
|
+
return expandToNode `
|
|
1071
|
+
Hooks.on("${name}", async (${hook.params.map(p => p.name).join(", ")}) => {
|
|
1072
|
+
${generateBody()}
|
|
1073
|
+
});
|
|
1074
1074
|
`.appendNewLineIfNotEmpty();
|
|
1075
1075
|
}
|
|
1076
1076
|
}
|
|
1077
|
-
return expandToNode `
|
|
1078
|
-
_register${document.name}Hooks(document) {
|
|
1079
|
-
${joinToNode(hooks, generateHook, { appendNewLineIfNotEmpty: true })}
|
|
1080
|
-
}
|
|
1077
|
+
return expandToNode `
|
|
1078
|
+
_register${document.name}Hooks(document) {
|
|
1079
|
+
${joinToNode(hooks, generateHook, { appendNewLineIfNotEmpty: true })}
|
|
1080
|
+
}
|
|
1081
1081
|
`.appendNewLineIfNotEmpty().appendNewLine();
|
|
1082
1082
|
}
|
|
1083
1083
|
// Number fields whose `initial:` is an expression (method block) can't be a static schema
|
|
@@ -1094,27 +1094,27 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
1094
1094
|
});
|
|
1095
1095
|
if (exprInitialFields.length === 0)
|
|
1096
1096
|
return undefined;
|
|
1097
|
-
return expandToNode `
|
|
1098
|
-
case "${document.name.toLowerCase()}": {
|
|
1097
|
+
return expandToNode `
|
|
1098
|
+
case "${document.name.toLowerCase()}": {
|
|
1099
1099
|
${joinToNode(exprInitialFields, f => {
|
|
1100
1100
|
const initParam = f.params.find(p => isNumberParamInitial(p));
|
|
1101
1101
|
const field = f.name.toLowerCase();
|
|
1102
|
-
return expandToNode `
|
|
1103
|
-
// ${f.name} expression initial
|
|
1104
|
-
if (foundry.utils.getProperty(data, "system.${field}") === undefined) {
|
|
1105
|
-
const ${field}InitialFunc = (system) => {
|
|
1106
|
-
const context = { object: this };
|
|
1107
|
-
${translateExpression(entry, id, initParam.value, true, f)}
|
|
1108
|
-
};
|
|
1109
|
-
const ${field}Initial = ${field}InitialFunc(this.system);
|
|
1110
|
-
if (typeof ${field}Initial === "number" && !isNaN(${field}Initial)) {
|
|
1111
|
-
initialUpdates["system.${field}"] = ${field}Initial;
|
|
1112
|
-
}
|
|
1113
|
-
}
|
|
1102
|
+
return expandToNode `
|
|
1103
|
+
// ${f.name} expression initial
|
|
1104
|
+
if (foundry.utils.getProperty(data, "system.${field}") === undefined) {
|
|
1105
|
+
const ${field}InitialFunc = (system) => {
|
|
1106
|
+
const context = { object: this };
|
|
1107
|
+
${translateExpression(entry, id, initParam.value, true, f)}
|
|
1108
|
+
};
|
|
1109
|
+
const ${field}Initial = ${field}InitialFunc(this.system);
|
|
1110
|
+
if (typeof ${field}Initial === "number" && !isNaN(${field}Initial)) {
|
|
1111
|
+
initialUpdates["system.${field}"] = ${field}Initial;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
1114
|
`;
|
|
1115
|
-
}, { appendNewLineIfNotEmpty: true })}
|
|
1116
|
-
break;
|
|
1117
|
-
}
|
|
1115
|
+
}, { appendNewLineIfNotEmpty: true })}
|
|
1116
|
+
break;
|
|
1117
|
+
}
|
|
1118
1118
|
`.appendNewLineIfNotEmpty();
|
|
1119
1119
|
}
|
|
1120
1120
|
const cases = entry.documents
|
|
@@ -1123,300 +1123,300 @@ export function generateExtendedDocumentClasses(entry, id, destination) {
|
|
|
1123
1123
|
.filter((x) => x !== undefined);
|
|
1124
1124
|
if (cases.length === 0)
|
|
1125
1125
|
return expandToNode ``;
|
|
1126
|
-
return expandToNode `
|
|
1127
|
-
/** @override */
|
|
1128
|
-
async _preCreate(data, options, user) {
|
|
1129
|
-
await super._preCreate(data, options, user);
|
|
1130
|
-
const initialUpdates = {};
|
|
1131
|
-
switch ( this.type ) {
|
|
1132
|
-
${joinToNode(cases, c => c, { appendNewLineIfNotEmpty: true })}
|
|
1133
|
-
}
|
|
1134
|
-
if (Object.keys(initialUpdates).length > 0) this.updateSource(initialUpdates);
|
|
1135
|
-
}
|
|
1126
|
+
return expandToNode `
|
|
1127
|
+
/** @override */
|
|
1128
|
+
async _preCreate(data, options, user) {
|
|
1129
|
+
await super._preCreate(data, options, user);
|
|
1130
|
+
const initialUpdates = {};
|
|
1131
|
+
switch ( this.type ) {
|
|
1132
|
+
${joinToNode(cases, c => c, { appendNewLineIfNotEmpty: true })}
|
|
1133
|
+
}
|
|
1134
|
+
if (Object.keys(initialUpdates).length > 0) this.updateSource(initialUpdates);
|
|
1135
|
+
}
|
|
1136
1136
|
`.appendNewLineIfNotEmpty();
|
|
1137
1137
|
}
|
|
1138
|
-
const fileNode = expandToNode `
|
|
1139
|
-
export default class ${entry.config.name}${type} extends ${type} {
|
|
1140
|
-
/** @override */
|
|
1141
|
-
prepareDerivedData() {
|
|
1142
|
-
switch ( this.type ) {
|
|
1143
|
-
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), document => `case "${document.name.toLowerCase()}": return this._prepare${document.name}DerivedData();`, { appendNewLineIfNotEmpty: true })}
|
|
1144
|
-
}
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
/* -------------------------------------------- */
|
|
1148
|
-
|
|
1149
|
-
${generateExpressionInitials()}
|
|
1150
|
-
|
|
1151
|
-
/* -------------------------------------------- */
|
|
1152
|
-
|
|
1153
|
-
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), document => generateDerivedData(document), { appendNewLineIfNotEmpty: true })}
|
|
1154
|
-
|
|
1155
|
-
/* -------------------------------------------- */
|
|
1156
|
-
|
|
1157
|
-
${generateDeltas(entry.documents)}
|
|
1158
|
-
|
|
1159
|
-
/* -------------------------------------------- */
|
|
1160
|
-
|
|
1161
|
-
reapplyActiveEffectsForName(name) {
|
|
1162
|
-
if (this.documentName !== "Actor") return;
|
|
1163
|
-
for (const effect of this.appliedEffects) {
|
|
1164
|
-
for (const change of effect.changes) {
|
|
1165
|
-
if (change.key == name) {
|
|
1166
|
-
const changes = effect.apply(this, change);
|
|
1167
|
-
Object.assign(this.overrides, changes);
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
}
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
/* -------------------------------------------- */
|
|
1174
|
-
|
|
1175
|
-
/** @override */
|
|
1176
|
-
_initialize(options = {}) {
|
|
1177
|
-
super._initialize(options);
|
|
1178
|
-
|
|
1179
|
-
switch ( this.type ) {
|
|
1180
|
-
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), document => `case "${document.name.toLowerCase()}": return this._register${document.name}Hooks(this);`, { appendNewLineIfNotEmpty: true })}
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
/* -------------------------------------------- */
|
|
1185
|
-
|
|
1186
|
-
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), generateDocumentHooks, { appendNewLineIfNotEmpty: true })}
|
|
1187
|
-
|
|
1188
|
-
/* -------------------------------------------- */
|
|
1189
|
-
|
|
1190
|
-
// In order to support per-document type effects, we need to override the allApplicableEffects method to yield virtualized effects with only changes that match the document type
|
|
1191
|
-
/** @override */
|
|
1192
|
-
*allApplicableEffects() {
|
|
1193
|
-
const systemFlags = this.flags["${id}"] ?? {};
|
|
1194
|
-
const edit = systemFlags["edit-mode"] ?? true;
|
|
1195
|
-
|
|
1196
|
-
function getTypedEffect(type, edit, effect, source) {
|
|
1197
|
-
// Pre-build data to avoid mutating ActiveEffect getters (changes is getter-only in v14).
|
|
1198
|
-
const data = foundry.utils.duplicate(effect);
|
|
1199
|
-
data.changes = (data.changes ?? []).filter(c => c.key.startsWith(type));
|
|
1200
|
-
for ( const change of data.changes ) {
|
|
1201
|
-
if (change.mode == 0) continue;
|
|
1202
|
-
change.key = change.key.replace(type + ".", "");
|
|
1203
|
-
}
|
|
1204
|
-
if ( edit ) data.disabled = true;
|
|
1205
|
-
data.flags ??= {};
|
|
1206
|
-
data.flags["${id}"] ??= {};
|
|
1207
|
-
data.flags["${id}"].source = source;
|
|
1208
|
-
return new ActiveEffect(data, {parent: effect.parent});
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
for ( const effect of this.effects ) {
|
|
1212
|
-
yield getTypedEffect(this.type, edit, effect, game.i18n.localize("Self"));
|
|
1213
|
-
}
|
|
1214
|
-
${type == "Actor" ? expandToNode `
|
|
1215
|
-
for ( const item of this.items ) {
|
|
1216
|
-
for ( const effect of item.effects ) {
|
|
1217
|
-
if ( effect.transfer ) yield getTypedEffect(this.type, edit, effect, item.name);
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
`.appendNewLine() : ""}
|
|
1221
|
-
}
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
/* -------------------------------------------- */
|
|
1225
|
-
|
|
1226
|
-
_onCreateDescendantDocuments(parent, collection, documents, data, options, userId) {
|
|
1227
|
-
super._onCreateDescendantDocuments(parent, collection, documents, data, options, userId);
|
|
1228
|
-
|
|
1229
|
-
for (const document of documents) {
|
|
1230
|
-
if (document.documentName !== "ActiveEffect") continue;
|
|
1231
|
-
|
|
1232
|
-
for (const change of document.changes) {
|
|
1233
|
-
if (change.mode != 0) continue;
|
|
1234
|
-
const customMode = foundry.utils.getProperty(document.flags["${id}"], change.key + "-custommode");
|
|
1235
|
-
switch (customMode) {
|
|
1236
|
-
case 1: // Add Once
|
|
1237
|
-
this._effectAddOnce(parent, document, change);
|
|
1238
|
-
break;
|
|
1239
|
-
default:
|
|
1240
|
-
console.error("Unknown custom mode", customMode);
|
|
1241
|
-
break;
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
/* -------------------------------------------- */
|
|
1248
|
-
|
|
1249
|
-
_effectAddOnce(parent, ae, change) {
|
|
1250
|
-
console.dir("AddOnce", parent, ae, change);
|
|
1251
|
-
|
|
1252
|
-
const key = change.key.replace(parent.type + ".", "");
|
|
1253
|
-
const currentValue = foundry.utils.getProperty(parent, key);
|
|
1254
|
-
|
|
1255
|
-
// Create an update for the parent
|
|
1256
|
-
const update = {
|
|
1257
|
-
[key]: currentValue + parseInt(change.value)
|
|
1258
|
-
};
|
|
1259
|
-
parent.update(update);
|
|
1260
|
-
|
|
1261
|
-
// Create a chat card
|
|
1262
|
-
const chatData = {
|
|
1263
|
-
user: game.user._id,
|
|
1264
|
-
speaker: ChatMessage.getSpeaker({ actor: parent }),
|
|
1265
|
-
content: \`<p>Added "\${ae.name}" once</p>\`
|
|
1266
|
-
};
|
|
1267
|
-
ChatMessage.create(chatData);
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1270
|
-
/* -------------------------------------------- */
|
|
1271
|
-
|
|
1272
|
-
static async createDialog(data = {}, { parent = null, pack = null, types = null, ...options } = {}) {
|
|
1273
|
-
types ??= game.documentTypes[this.documentName].filter(t => (t !== CONST.BASE_DOCUMENT_TYPE) && (CONFIG[this.documentName].typeCreatables[t] !== false));
|
|
1274
|
-
if (!types.length) return null;
|
|
1275
|
-
|
|
1276
|
-
const collection = parent ? null : pack ? game.packs.get(pack) : game.collections.get(this.documentName);
|
|
1277
|
-
const folders = collection?._formatFolderSelectOptions() ?? [];
|
|
1278
|
-
|
|
1279
|
-
const label = game.i18n.localize(this.metadata.label);
|
|
1280
|
-
const title = game.i18n.format("DOCUMENT.Create", { type: label });
|
|
1281
|
-
const name = data.name || game.i18n.format("DOCUMENT.New", { type: label });
|
|
1282
|
-
|
|
1283
|
-
let type = data.type || CONFIG[this.documentName]?.defaultType;
|
|
1284
|
-
if (!types.includes(type)) type = types[0];
|
|
1285
|
-
|
|
1286
|
-
// If there's only one type, no need to prompt
|
|
1287
|
-
if (types.length === 1) {
|
|
1288
|
-
let createName = this.defaultName();
|
|
1289
|
-
const createData = {
|
|
1290
|
-
name: createName,
|
|
1291
|
-
type
|
|
1292
|
-
};
|
|
1293
|
-
return this.create(createData, { parent, pack, renderSheet: true });
|
|
1294
|
-
}
|
|
1295
|
-
|
|
1296
|
-
const createResponse = await game.system.documentCreateDialog.prompt({
|
|
1297
|
-
type,
|
|
1298
|
-
types: types.reduce((arr, typer) => {
|
|
1299
|
-
arr.push({
|
|
1300
|
-
type: typer,
|
|
1301
|
-
label: game.i18n.has(typer) ? game.i18n.localize(typer) : typer,
|
|
1302
|
-
icon: this.getDefaultArtwork({ type: typer })?.img ?? "icons/svg/item-bag.svg",
|
|
1303
|
-
description: CONFIG[this.documentName]?.typeDescriptions?.[typer] ?? "",
|
|
1304
|
-
selected: type === typer
|
|
1305
|
-
});
|
|
1306
|
-
return arr;
|
|
1307
|
-
}, []).sort((a, b) => a.label.localeCompare(b.label, game.i18n.lang)),
|
|
1308
|
-
name,
|
|
1309
|
-
title,
|
|
1310
|
-
label,
|
|
1311
|
-
folders,
|
|
1312
|
-
folder: data.folder
|
|
1313
|
-
});
|
|
1314
|
-
|
|
1315
|
-
const createData = foundry.utils.mergeObject(data, createResponse, { inplace: false });
|
|
1316
|
-
createData.type = createData.type || type;
|
|
1317
|
-
// The type field can come back as the autocomplete's display label (e.g. the
|
|
1318
|
-
// localized "Basic Hero") rather than the machine type ("basichero"). Lower-casing
|
|
1319
|
-
// alone doesn't recover a multi-word machine type, so map the response back against
|
|
1320
|
-
// the known types -- matching either the raw machine type or its displayed label --
|
|
1321
|
-
// and fall back to the resolved default type if nothing matches.
|
|
1322
|
-
if (!types.includes(createData.type)) {
|
|
1323
|
-
createData.type = types.find(t => t === createData.type || (game.i18n.has(t) ? game.i18n.localize(t) : t) === createData.type) ?? type;
|
|
1324
|
-
}
|
|
1325
|
-
if (!createData.folder) delete createData.folder;
|
|
1326
|
-
if (!createData.name?.trim()) createData.name = this.defaultName();
|
|
1327
|
-
return this.create(createData, { parent, pack, renderSheet: true });
|
|
1328
|
-
|
|
1329
|
-
const content = await renderTemplate("systems/${id}/system/templates/document-create.hbs", {
|
|
1330
|
-
folders, name, type,
|
|
1331
|
-
folder: data.folder,
|
|
1332
|
-
hasFolders: folders.length > 0,
|
|
1333
|
-
types: types.reduce((arr, typer) => {
|
|
1334
|
-
arr.push({
|
|
1335
|
-
type: typer,
|
|
1336
|
-
label: game.i18n.has(typer) ? game.i18n.localize(typer) : typer,
|
|
1337
|
-
icon: this.getDefaultArtwork({ type: typer })?.img ?? "icons/svg/item-bag.svg",
|
|
1338
|
-
description: CONFIG[this.documentName]?.typeDescriptions?.[typer] ?? "",
|
|
1339
|
-
selected: type === typer
|
|
1340
|
-
});
|
|
1341
|
-
return arr;
|
|
1342
|
-
}, []).sort((a, b) => a.label.localeCompare(b.label, game.i18n.lang))
|
|
1343
|
-
});
|
|
1344
|
-
return Dialog.prompt({
|
|
1345
|
-
title, content,
|
|
1346
|
-
label: title,
|
|
1347
|
-
render: html => {
|
|
1348
|
-
const app = html.closest(".app");
|
|
1349
|
-
const folder = app.querySelector("select");
|
|
1350
|
-
if (folder) app.querySelector(".dialog-buttons").insertAdjacentElement("afterbegin", folder);
|
|
1351
|
-
app.querySelectorAll(".window-header .header-button").forEach(btn => {
|
|
1352
|
-
const label = btn.innerText;
|
|
1353
|
-
const icon = btn.querySelector("i");
|
|
1354
|
-
btn.innerHTML = icon.outerHTML;
|
|
1355
|
-
btn.dataset.tooltip = label;
|
|
1356
|
-
btn.setAttribute("aria-label", label);
|
|
1357
|
-
});
|
|
1358
|
-
app.querySelector(".document-name").select();
|
|
1359
|
-
},
|
|
1360
|
-
callback: html => {
|
|
1361
|
-
const form = html.querySelector("form");
|
|
1362
|
-
const fd = new FormDataExtended(form);
|
|
1363
|
-
const createData = foundry.utils.mergeObject(data, fd.object, { inplace: false });
|
|
1364
|
-
|
|
1365
|
-
},
|
|
1366
|
-
rejectClose: false,
|
|
1367
|
-
options: { ...options, jQuery: false, width: 700, height: 'auto', classes: ["${id}", "create-document", "dialog"] }
|
|
1368
|
-
});
|
|
1369
|
-
}
|
|
1370
|
-
|
|
1371
|
-
/* -------------------------------------------- */
|
|
1372
|
-
|
|
1373
|
-
static getDefaultArtwork(itemData = {}) {
|
|
1374
|
-
const { type } = itemData;
|
|
1375
|
-
const { img, texture } = super.getDefaultArtwork(itemData);
|
|
1376
|
-
return { img: CONFIG[this.documentName]?.typeArtworks?.[type] ?? img, texture: texture };
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
/* -------------------------------------------- */
|
|
1380
|
-
|
|
1381
|
-
getRollData() {
|
|
1382
|
-
const data = super.getRollData();
|
|
1383
|
-
const rollData = foundry.utils.duplicate(data);
|
|
1384
|
-
rollData.system = this.system;
|
|
1385
|
-
return rollData;
|
|
1386
|
-
}
|
|
1387
|
-
|
|
1388
|
-
/* -------------------------------------------- */
|
|
1389
|
-
|
|
1390
|
-
/** @override */
|
|
1391
|
-
async modifyTokenAttribute(attribute, value, isDelta, isBar) {
|
|
1392
|
-
const resource = foundry.utils.getProperty(this.system, attribute);
|
|
1393
|
-
|
|
1394
|
-
if (isDelta && value < 0) {
|
|
1395
|
-
// Apply to temp first
|
|
1396
|
-
resource.temp += value;
|
|
1397
|
-
|
|
1398
|
-
// If temp is negative, apply to value
|
|
1399
|
-
if (resource.temp < 0) {
|
|
1400
|
-
resource.value += resource.temp;
|
|
1401
|
-
resource.temp = 0;
|
|
1402
|
-
}
|
|
1403
|
-
await this.update({ ["system." + attribute]: resource });
|
|
1404
|
-
return;
|
|
1405
|
-
}
|
|
1406
|
-
|
|
1407
|
-
return super.modifyTokenAttribute(attribute, value, isDelta, isBar);
|
|
1408
|
-
}
|
|
1409
|
-
|
|
1410
|
-
${type == "Actor" ? expandToNode `
|
|
1411
|
-
/* -------------------------------------------- */
|
|
1412
|
-
|
|
1413
|
-
getInitiativeFormula() {
|
|
1414
|
-
switch ( this.type ) {
|
|
1415
|
-
${joinToNode(entry.documents.filter(d => isActor(d)), document => generateInitiativeFormula(document), { appendNewLineIfNotEmpty: true })}
|
|
1416
|
-
}
|
|
1417
|
-
}
|
|
1418
|
-
`.appendNewLine() : ""}
|
|
1419
|
-
}
|
|
1138
|
+
const fileNode = expandToNode `
|
|
1139
|
+
export default class ${entry.config.name}${type} extends ${type} {
|
|
1140
|
+
/** @override */
|
|
1141
|
+
prepareDerivedData() {
|
|
1142
|
+
switch ( this.type ) {
|
|
1143
|
+
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), document => `case "${document.name.toLowerCase()}": return this._prepare${document.name}DerivedData();`, { appendNewLineIfNotEmpty: true })}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
/* -------------------------------------------- */
|
|
1148
|
+
|
|
1149
|
+
${generateExpressionInitials()}
|
|
1150
|
+
|
|
1151
|
+
/* -------------------------------------------- */
|
|
1152
|
+
|
|
1153
|
+
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), document => generateDerivedData(document), { appendNewLineIfNotEmpty: true })}
|
|
1154
|
+
|
|
1155
|
+
/* -------------------------------------------- */
|
|
1156
|
+
|
|
1157
|
+
${generateDeltas(entry.documents)}
|
|
1158
|
+
|
|
1159
|
+
/* -------------------------------------------- */
|
|
1160
|
+
|
|
1161
|
+
reapplyActiveEffectsForName(name) {
|
|
1162
|
+
if (this.documentName !== "Actor") return;
|
|
1163
|
+
for (const effect of this.appliedEffects) {
|
|
1164
|
+
for (const change of effect.changes) {
|
|
1165
|
+
if (change.key == name) {
|
|
1166
|
+
const changes = effect.apply(this, change);
|
|
1167
|
+
Object.assign(this.overrides, changes);
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
/* -------------------------------------------- */
|
|
1174
|
+
|
|
1175
|
+
/** @override */
|
|
1176
|
+
_initialize(options = {}) {
|
|
1177
|
+
super._initialize(options);
|
|
1178
|
+
|
|
1179
|
+
switch ( this.type ) {
|
|
1180
|
+
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), document => `case "${document.name.toLowerCase()}": return this._register${document.name}Hooks(this);`, { appendNewLineIfNotEmpty: true })}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
/* -------------------------------------------- */
|
|
1185
|
+
|
|
1186
|
+
${joinToNode(entry.documents.filter(d => type == "Actor" ? isActor(d) : isItem(d)), generateDocumentHooks, { appendNewLineIfNotEmpty: true })}
|
|
1187
|
+
|
|
1188
|
+
/* -------------------------------------------- */
|
|
1189
|
+
|
|
1190
|
+
// In order to support per-document type effects, we need to override the allApplicableEffects method to yield virtualized effects with only changes that match the document type
|
|
1191
|
+
/** @override */
|
|
1192
|
+
*allApplicableEffects() {
|
|
1193
|
+
const systemFlags = this.flags["${id}"] ?? {};
|
|
1194
|
+
const edit = systemFlags["edit-mode"] ?? true;
|
|
1195
|
+
|
|
1196
|
+
function getTypedEffect(type, edit, effect, source) {
|
|
1197
|
+
// Pre-build data to avoid mutating ActiveEffect getters (changes is getter-only in v14).
|
|
1198
|
+
const data = foundry.utils.duplicate(effect);
|
|
1199
|
+
data.changes = (data.changes ?? []).filter(c => c.key.startsWith(type));
|
|
1200
|
+
for ( const change of data.changes ) {
|
|
1201
|
+
if (change.mode == 0) continue;
|
|
1202
|
+
change.key = change.key.replace(type + ".", "");
|
|
1203
|
+
}
|
|
1204
|
+
if ( edit ) data.disabled = true;
|
|
1205
|
+
data.flags ??= {};
|
|
1206
|
+
data.flags["${id}"] ??= {};
|
|
1207
|
+
data.flags["${id}"].source = source;
|
|
1208
|
+
return new ActiveEffect(data, {parent: effect.parent});
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
for ( const effect of this.effects ) {
|
|
1212
|
+
yield getTypedEffect(this.type, edit, effect, game.i18n.localize("Self"));
|
|
1213
|
+
}
|
|
1214
|
+
${type == "Actor" ? expandToNode `
|
|
1215
|
+
for ( const item of this.items ) {
|
|
1216
|
+
for ( const effect of item.effects ) {
|
|
1217
|
+
if ( effect.transfer ) yield getTypedEffect(this.type, edit, effect, item.name);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
`.appendNewLine() : ""}
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
/* -------------------------------------------- */
|
|
1225
|
+
|
|
1226
|
+
_onCreateDescendantDocuments(parent, collection, documents, data, options, userId) {
|
|
1227
|
+
super._onCreateDescendantDocuments(parent, collection, documents, data, options, userId);
|
|
1228
|
+
|
|
1229
|
+
for (const document of documents) {
|
|
1230
|
+
if (document.documentName !== "ActiveEffect") continue;
|
|
1231
|
+
|
|
1232
|
+
for (const change of document.changes) {
|
|
1233
|
+
if (change.mode != 0) continue;
|
|
1234
|
+
const customMode = foundry.utils.getProperty(document.flags["${id}"], change.key + "-custommode");
|
|
1235
|
+
switch (customMode) {
|
|
1236
|
+
case 1: // Add Once
|
|
1237
|
+
this._effectAddOnce(parent, document, change);
|
|
1238
|
+
break;
|
|
1239
|
+
default:
|
|
1240
|
+
console.error("Unknown custom mode", customMode);
|
|
1241
|
+
break;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/* -------------------------------------------- */
|
|
1248
|
+
|
|
1249
|
+
_effectAddOnce(parent, ae, change) {
|
|
1250
|
+
console.dir("AddOnce", parent, ae, change);
|
|
1251
|
+
|
|
1252
|
+
const key = change.key.replace(parent.type + ".", "");
|
|
1253
|
+
const currentValue = foundry.utils.getProperty(parent, key);
|
|
1254
|
+
|
|
1255
|
+
// Create an update for the parent
|
|
1256
|
+
const update = {
|
|
1257
|
+
[key]: currentValue + parseInt(change.value)
|
|
1258
|
+
};
|
|
1259
|
+
parent.update(update);
|
|
1260
|
+
|
|
1261
|
+
// Create a chat card
|
|
1262
|
+
const chatData = {
|
|
1263
|
+
user: game.user._id,
|
|
1264
|
+
speaker: ChatMessage.getSpeaker({ actor: parent }),
|
|
1265
|
+
content: \`<p>Added "\${ae.name}" once</p>\`
|
|
1266
|
+
};
|
|
1267
|
+
ChatMessage.create(chatData);
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/* -------------------------------------------- */
|
|
1271
|
+
|
|
1272
|
+
static async createDialog(data = {}, { parent = null, pack = null, types = null, ...options } = {}) {
|
|
1273
|
+
types ??= game.documentTypes[this.documentName].filter(t => (t !== CONST.BASE_DOCUMENT_TYPE) && (CONFIG[this.documentName].typeCreatables[t] !== false));
|
|
1274
|
+
if (!types.length) return null;
|
|
1275
|
+
|
|
1276
|
+
const collection = parent ? null : pack ? game.packs.get(pack) : game.collections.get(this.documentName);
|
|
1277
|
+
const folders = collection?._formatFolderSelectOptions() ?? [];
|
|
1278
|
+
|
|
1279
|
+
const label = game.i18n.localize(this.metadata.label);
|
|
1280
|
+
const title = game.i18n.format("DOCUMENT.Create", { type: label });
|
|
1281
|
+
const name = data.name || game.i18n.format("DOCUMENT.New", { type: label });
|
|
1282
|
+
|
|
1283
|
+
let type = data.type || CONFIG[this.documentName]?.defaultType;
|
|
1284
|
+
if (!types.includes(type)) type = types[0];
|
|
1285
|
+
|
|
1286
|
+
// If there's only one type, no need to prompt
|
|
1287
|
+
if (types.length === 1) {
|
|
1288
|
+
let createName = this.defaultName();
|
|
1289
|
+
const createData = {
|
|
1290
|
+
name: createName,
|
|
1291
|
+
type
|
|
1292
|
+
};
|
|
1293
|
+
return this.create(createData, { parent, pack, renderSheet: true });
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
const createResponse = await game.system.documentCreateDialog.prompt({
|
|
1297
|
+
type,
|
|
1298
|
+
types: types.reduce((arr, typer) => {
|
|
1299
|
+
arr.push({
|
|
1300
|
+
type: typer,
|
|
1301
|
+
label: game.i18n.has(typer) ? game.i18n.localize(typer) : typer,
|
|
1302
|
+
icon: this.getDefaultArtwork({ type: typer })?.img ?? "icons/svg/item-bag.svg",
|
|
1303
|
+
description: CONFIG[this.documentName]?.typeDescriptions?.[typer] ?? "",
|
|
1304
|
+
selected: type === typer
|
|
1305
|
+
});
|
|
1306
|
+
return arr;
|
|
1307
|
+
}, []).sort((a, b) => a.label.localeCompare(b.label, game.i18n.lang)),
|
|
1308
|
+
name,
|
|
1309
|
+
title,
|
|
1310
|
+
label,
|
|
1311
|
+
folders,
|
|
1312
|
+
folder: data.folder
|
|
1313
|
+
});
|
|
1314
|
+
|
|
1315
|
+
const createData = foundry.utils.mergeObject(data, createResponse, { inplace: false });
|
|
1316
|
+
createData.type = createData.type || type;
|
|
1317
|
+
// The type field can come back as the autocomplete's display label (e.g. the
|
|
1318
|
+
// localized "Basic Hero") rather than the machine type ("basichero"). Lower-casing
|
|
1319
|
+
// alone doesn't recover a multi-word machine type, so map the response back against
|
|
1320
|
+
// the known types -- matching either the raw machine type or its displayed label --
|
|
1321
|
+
// and fall back to the resolved default type if nothing matches.
|
|
1322
|
+
if (!types.includes(createData.type)) {
|
|
1323
|
+
createData.type = types.find(t => t === createData.type || (game.i18n.has(t) ? game.i18n.localize(t) : t) === createData.type) ?? type;
|
|
1324
|
+
}
|
|
1325
|
+
if (!createData.folder) delete createData.folder;
|
|
1326
|
+
if (!createData.name?.trim()) createData.name = this.defaultName();
|
|
1327
|
+
return this.create(createData, { parent, pack, renderSheet: true });
|
|
1328
|
+
|
|
1329
|
+
const content = await renderTemplate("systems/${id}/system/templates/document-create.hbs", {
|
|
1330
|
+
folders, name, type,
|
|
1331
|
+
folder: data.folder,
|
|
1332
|
+
hasFolders: folders.length > 0,
|
|
1333
|
+
types: types.reduce((arr, typer) => {
|
|
1334
|
+
arr.push({
|
|
1335
|
+
type: typer,
|
|
1336
|
+
label: game.i18n.has(typer) ? game.i18n.localize(typer) : typer,
|
|
1337
|
+
icon: this.getDefaultArtwork({ type: typer })?.img ?? "icons/svg/item-bag.svg",
|
|
1338
|
+
description: CONFIG[this.documentName]?.typeDescriptions?.[typer] ?? "",
|
|
1339
|
+
selected: type === typer
|
|
1340
|
+
});
|
|
1341
|
+
return arr;
|
|
1342
|
+
}, []).sort((a, b) => a.label.localeCompare(b.label, game.i18n.lang))
|
|
1343
|
+
});
|
|
1344
|
+
return Dialog.prompt({
|
|
1345
|
+
title, content,
|
|
1346
|
+
label: title,
|
|
1347
|
+
render: html => {
|
|
1348
|
+
const app = html.closest(".app");
|
|
1349
|
+
const folder = app.querySelector("select");
|
|
1350
|
+
if (folder) app.querySelector(".dialog-buttons").insertAdjacentElement("afterbegin", folder);
|
|
1351
|
+
app.querySelectorAll(".window-header .header-button").forEach(btn => {
|
|
1352
|
+
const label = btn.innerText;
|
|
1353
|
+
const icon = btn.querySelector("i");
|
|
1354
|
+
btn.innerHTML = icon.outerHTML;
|
|
1355
|
+
btn.dataset.tooltip = label;
|
|
1356
|
+
btn.setAttribute("aria-label", label);
|
|
1357
|
+
});
|
|
1358
|
+
app.querySelector(".document-name").select();
|
|
1359
|
+
},
|
|
1360
|
+
callback: html => {
|
|
1361
|
+
const form = html.querySelector("form");
|
|
1362
|
+
const fd = new FormDataExtended(form);
|
|
1363
|
+
const createData = foundry.utils.mergeObject(data, fd.object, { inplace: false });
|
|
1364
|
+
|
|
1365
|
+
},
|
|
1366
|
+
rejectClose: false,
|
|
1367
|
+
options: { ...options, jQuery: false, width: 700, height: 'auto', classes: ["${id}", "create-document", "dialog"] }
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
/* -------------------------------------------- */
|
|
1372
|
+
|
|
1373
|
+
static getDefaultArtwork(itemData = {}) {
|
|
1374
|
+
const { type } = itemData;
|
|
1375
|
+
const { img, texture } = super.getDefaultArtwork(itemData);
|
|
1376
|
+
return { img: CONFIG[this.documentName]?.typeArtworks?.[type] ?? img, texture: texture };
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
/* -------------------------------------------- */
|
|
1380
|
+
|
|
1381
|
+
getRollData() {
|
|
1382
|
+
const data = super.getRollData();
|
|
1383
|
+
const rollData = foundry.utils.duplicate(data);
|
|
1384
|
+
rollData.system = this.system;
|
|
1385
|
+
return rollData;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
/* -------------------------------------------- */
|
|
1389
|
+
|
|
1390
|
+
/** @override */
|
|
1391
|
+
async modifyTokenAttribute(attribute, value, isDelta, isBar) {
|
|
1392
|
+
const resource = foundry.utils.getProperty(this.system, attribute);
|
|
1393
|
+
|
|
1394
|
+
if (isDelta && value < 0) {
|
|
1395
|
+
// Apply to temp first
|
|
1396
|
+
resource.temp += value;
|
|
1397
|
+
|
|
1398
|
+
// If temp is negative, apply to value
|
|
1399
|
+
if (resource.temp < 0) {
|
|
1400
|
+
resource.value += resource.temp;
|
|
1401
|
+
resource.temp = 0;
|
|
1402
|
+
}
|
|
1403
|
+
await this.update({ ["system." + attribute]: resource });
|
|
1404
|
+
return;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
return super.modifyTokenAttribute(attribute, value, isDelta, isBar);
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
${type == "Actor" ? expandToNode `
|
|
1411
|
+
/* -------------------------------------------- */
|
|
1412
|
+
|
|
1413
|
+
getInitiativeFormula() {
|
|
1414
|
+
switch ( this.type ) {
|
|
1415
|
+
${joinToNode(entry.documents.filter(d => isActor(d)), document => generateInitiativeFormula(document), { appendNewLineIfNotEmpty: true })}
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
`.appendNewLine() : ""}
|
|
1419
|
+
}
|
|
1420
1420
|
`.appendNewLineIfNotEmpty();
|
|
1421
1421
|
fs.writeFileSync(generatedFilePath, toString(fileNode));
|
|
1422
1422
|
}
|