-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathwfrp3e.js
386 lines (352 loc) · 16.3 KB
/
wfrp3e.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
import {WFRP3e} from "./modules/config.js";
import CharacterGenerator from "./modules/applications/CharacterGenerator.js";
import CheckBuilder from "./modules/applications/CheckBuilder.js";
import WFRP3eCharacterSheet from "./modules/applications/actors/WFRP3eCharacterSheet.js";
import WFRP3eCreatureSheet from "./modules/applications/actors/WFRP3eCreatureSheet.js";
import WFRP3eGroupSheet from "./modules/applications/actors/WFRP3eGroupSheet.js";
import WFRP3ePartySheet from "./modules/applications/actors/WFRP3ePartySheet.js";
import WFRP3eAbilitySheet from "./modules/applications/items/WFRP3eAbilitySheet.js";
import WFRP3eActionSheet from "./modules/applications/items/WFRP3eActionSheet.js";
import WFRP3eActionSheetV2 from "./modules/applications/items/WFRP3eActionSheetV2.js";
import WFRP3eArmourSheet from "./modules/applications/items/WFRP3eArmourSheet.js";
import WFRP3eCareerSheet from "./modules/applications/items/WFRP3eCareerSheet.js";
import WFRP3eConditionSheet from "./modules/applications/items/WFRP3eConditionSheet.js";
import WFRP3eCriticalWoundSheet from "./modules/applications/items/WFRP3eCriticalWoundSheet.js";
import WFRP3eDiseaseSheet from "./modules/applications/items/WFRP3eDiseaseSheet.js";
import WFRP3eInsanitySheet from "./modules/applications/items/WFRP3eInsanitySheet.js";
import WFRP3eMiscastSheet from "./modules/applications/items/WFRP3eMiscastSheet.js";
import WFRP3eMoneySheet from "./modules/applications/items/WFRP3eMoneySheet.js";
import WFRP3eMutationSheet from "./modules/applications/items/WFRP3eMutationSheet.js";
import WFRP3eSkillSheet from "./modules/applications/items/WFRP3eSkillSheet.js";
import WFRP3eTalentSheet from "./modules/applications/items/WFRP3eTalentSheet.js";
import WFRP3eTrappingSheet from "./modules/applications/items/WFRP3eTrappingSheet.js";
import WFRP3eWeaponSheet from "./modules/applications/items/WFRP3eWeaponSheet.js";
import WFRP3eCombatTracker from "./modules/applications/sidebar/WFRP3eCombatTracker.js";
import WFRP3eCombat from "./modules/combat/WFRP3eCombat.js";
import WFRP3eCombatant from "./modules/combat/WFRP3eCombatant.js";
import WFRP3eCharacterDataModel from "./modules/data/actors/WFRP3eCharacterDataModel.js";
import WFRP3eCreatureDataModel from "./modules/data/actors/WFRP3eCreatureDataModel.js";
import WFRP3eGroupDataModel from "./modules/data/actors/WFRP3eGroupDataModel.js";
import WFRP3ePartyDataModel from "./modules/data/actors/WFRP3ePartyDataModel.js";
import WFRP3eAbilityDataModel from "./modules/data/items/WFRP3eAbilityDataModel.js";
import WFRP3eActionDataModel from "./modules/data/items/WFRP3eActionDataModel.js";
import WFRP3eArmourDataModel from "./modules/data/items/WFRP3eArmourDataModel.js";
import WFRP3eCareerDataModel from "./modules/data/items/WFRP3eCareerDataModel.js";
import WFRP3eConditionDataModel from "./modules/data/items/WFRP3eConditionDataModel.js";
import WFRP3eCriticalWoundDataModel from "./modules/data/items/WFRP3eCriticalWoundDataModel.js";
import WFRP3eDiseaseDataModel from "./modules/data/items/WFRP3eDiseaseDataModel.js";
import WFRP3eInsanityDataModel from "./modules/data/items/WFRP3eInsanityDataModel.js";
import WFRP3eMiscastDataModel from "./modules/data/items/WFRP3eMiscastDataModel.js";
import WFRP3eMutationDataModel from "./modules/data/items/WFRP3eMutationDataModel.js";
import WFRP3eMoneyDataModel from "./modules/data/items/WFRP3eMoneyDataModel.js";
import WFRP3eSkillDataModel from "./modules/data/items/WFRP3eSkillDataModel.js";
import WFRP3eTalentDataModel from "./modules/data/items/WFRP3eTalentDataModel.js";
import WFRP3eTrappingDataModel from "./modules/data/items/WFRP3eTrappingDataModel.js";
import WFRP3eWeaponDataModel from "./modules/data/items/WFRP3eWeaponDataModel.js";
import ChallengeDie from "./modules/dice/ChallengeDie.js";
import CharacteristicDie from "./modules/dice/CharacteristicDie.js";
import ConservativeDie from "./modules/dice/ConservativeDie.js";
import ExpertiseDie from "./modules/dice/ExpertiseDie.js";
import FortuneDie from "./modules/dice/FortuneDie.js";
import MisfortuneDie from "./modules/dice/MisfortuneDie.js";
import RecklessDie from "./modules/dice/RecklessDie.js";
import WFRP3eActor from "./modules/documents/WFRP3eActor.js"
import WFRP3eItem from "./modules/documents/WFRP3eItem.js"
import CheckHelper from "./modules/CheckHelper.js";
import DicePool from "./modules/DicePool.js";
import WFRP3eRoll from "./modules/WFRP3eRoll.js";
import * as handlebarsHelpers from "./modules/handlebars.js";
async function preloadHandlebarsTemplates()
{
const templatePaths = [
"systems/wfrp3e/templates/partials/ability-tab.hbs",
"systems/wfrp3e/templates/partials/action-tab.hbs",
"systems/wfrp3e/templates/partials/ability-track-editor-segment.hbs",
"systems/wfrp3e/templates/partials/action-effects.hbs",
"systems/wfrp3e/templates/partials/attribute-partial.hbs",
"systems/wfrp3e/templates/partials/item-career-sheet.hbs",
"systems/wfrp3e/templates/partials/character-generator-origin-description.hbs",
"systems/wfrp3e/templates/partials/character-generator-talent-card.hbs",
"systems/wfrp3e/templates/partials/characteristic-partial.hbs",
"systems/wfrp3e/templates/partials/impairment-partial.hbs",
"systems/wfrp3e/templates/partials/item-ability-card.hbs",
"systems/wfrp3e/templates/partials/item-action-card.hbs",
"systems/wfrp3e/templates/partials/item-armour-row.hbs",
"systems/wfrp3e/templates/partials/item-career-partial.hbs",
"systems/wfrp3e/templates/partials/item-condition-card.hbs",
"systems/wfrp3e/templates/partials/item-disease-card.hbs",
"systems/wfrp3e/templates/partials/item-insanity-card.hbs",
"systems/wfrp3e/templates/partials/item-money-row.hbs",
"systems/wfrp3e/templates/partials/item-mutation-card.hbs",
"systems/wfrp3e/templates/partials/item-miscast-card.hbs",
"systems/wfrp3e/templates/partials/item-skill-row.hbs",
"systems/wfrp3e/templates/partials/item-talent-card.hbs",
"systems/wfrp3e/templates/partials/item-trapping-row.hbs",
"systems/wfrp3e/templates/partials/item-weapon-row.hbs",
"systems/wfrp3e/templates/partials/item-wound-card.hbs",
"systems/wfrp3e/templates/partials/trapping-cost-informations.hbs",
"systems/wfrp3e/templates/partials/trapping-tab.hbs"
];
return loadTemplates(templatePaths);
}
Hooks.once("init", async () => {
console.log("WFRP3e | Initialising Warhammer Fantasy Roleplay - 3rd Edition System");
CONFIG.WFRP3e = WFRP3e;
Object.assign(CONFIG.Actor.dataModels, {
"character": WFRP3eCharacterDataModel,
"creature": WFRP3eCreatureDataModel,
"group": WFRP3eGroupDataModel,
"party": WFRP3ePartyDataModel
});
CONFIG.Actor.documentClass = WFRP3eActor;
Object.assign(CONFIG.Item.dataModels, {
"ability": WFRP3eAbilityDataModel,
"action": WFRP3eActionDataModel,
"armour": WFRP3eArmourDataModel,
"career": WFRP3eCareerDataModel,
"condition": WFRP3eConditionDataModel,
"criticalWound": WFRP3eCriticalWoundDataModel,
"disease": WFRP3eDiseaseDataModel,
"insanity": WFRP3eInsanityDataModel,
"miscast": WFRP3eMiscastDataModel,
"money": WFRP3eMoneyDataModel,
"mutation": WFRP3eMutationDataModel,
"skill": WFRP3eSkillDataModel,
"talent": WFRP3eTalentDataModel,
"trapping": WFRP3eTrappingDataModel,
"weapon": WFRP3eWeaponDataModel
});
CONFIG.Item.documentClass = WFRP3eItem;
CONFIG.Combat.documentClass = WFRP3eCombat;
CONFIG.Combatant.documentClass = WFRP3eCombatant;
CONFIG.Dice.rolls.push(CONFIG.Dice.rolls[0]);
CONFIG.Dice.rolls[0] = WFRP3eRoll;
CONFIG.Dice.terms["h"] = ChallengeDie;
CONFIG.Dice.terms["a"] = CharacteristicDie;
CONFIG.Dice.terms["o"] = ConservativeDie;
CONFIG.Dice.terms["e"] = ExpertiseDie;
CONFIG.Dice.terms["f"] = FortuneDie;
CONFIG.Dice.terms["m"] = MisfortuneDie;
CONFIG.Dice.terms["r"] = RecklessDie;
CONFIG.fontDefinitions["ArnoPro"] = {
editor: true,
fonts: [
{urls: ["systems/wfrp3e/assets/fonts/ArnoPro-Regular.otf"]},
{urls: ["systems/wfrp3e/assets/fonts/ArnoPro-Bold.otf"], weight: 700},
{urls: ["systems/wfrp3e/assets/fonts/ArnoPro-Italic.otf"], style: "italic"},
{urls: ["systems/wfrp3e/assets/fonts/ArnoPro-BoldItalic.otf"], style: "italic", weight: 700}
]
};
CONFIG.fontDefinitions["Caslon Antique"] = {editor: true, fonts: []};
CONFIG.ui.combat = WFRP3eCombatTracker;
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("wfrp3e", WFRP3eCharacterSheet, {label: "Character Sheet", types: ["character"], makeDefault: true});
Actors.registerSheet("wfrp3e", WFRP3ePartySheet, {label: "Party Sheet", types: ["party"], makeDefault: true});
Actors.registerSheet("wfrp3e", WFRP3eCreatureSheet, {label: "Creature Sheet", types: ["creature"], makeDefault: true});
Actors.registerSheet("wfrp3e", WFRP3eGroupSheet, {label: "Group Sheet", types: ["group"], makeDefault: true});
Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("wfrp3e", WFRP3eAbilitySheet, {label: "Ability Sheet", types: ["ability"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eActionSheet, {label: "Action Sheet", types: ["action"]});
Items.registerSheet("wfrp3e", WFRP3eActionSheetV2, {label: "Action Sheet V2", types: ["action"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eArmourSheet, {label: "Armour Sheet", types: ["armour"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eCareerSheet, {label: "Career Sheet", types: ["career"], makeDefault: true})
Items.registerSheet("wfrp3e", WFRP3eConditionSheet, {label: "Condition Sheet", types: ["condition"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eCriticalWoundSheet, {label: "Critical Wound Sheet", types: ["criticalWound"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eDiseaseSheet, {label: "Disease Sheet", types: ["disease"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eInsanitySheet, {label: "Insanity Sheet", types: ["insanity"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eMiscastSheet, {label: "Miscast Sheet", types: ["miscast"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eMoneySheet, {label: "Money Sheet", types: ["money"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eMutationSheet, {label: "Mutation Sheet", types: ["mutation"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eSkillSheet, {label: "Skill Sheet", types: ["skill"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eTalentSheet, {label: "Talent Sheet", types: ["talent"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eWeaponSheet, {label: "Weapon Sheet", types: ["weapon"], makeDefault: true});
Items.registerSheet("wfrp3e", WFRP3eTrappingSheet, {label: "Trapping Sheet", types: ["trapping"], makeDefault: true});
await preloadHandlebarsTemplates();
});
Hooks.on("getChatLogEntryContext", (html, options) => {
options.push({
name: "ROLL.ACTIONS.applyToggledEffects",
icon: '<span class="fa-solid fa-check"></span>',
condition: li => {
const message = game.messages.get(li.attr("data-message-id"));
return message.rolls.length > 0
&& message.rolls[0].effects
&& Object.values(message.rolls[0].effects).find(symbol => symbol.length > 0).length > 0
&& (!Object.hasOwn(message.rolls[0].options.checkData, "outcome") || game.user.isGM);
},
callback: li => CheckHelper.triggerEffects(li.attr("data-message-id"))
});
});
Hooks.on('renderSidebarTab', (app, html, data) => {
const chatControls = html.find("#chat-controls > .control-buttons");
if(chatControls.length > 0) {
chatControls.prepend(
'<a class="wfrp3e-dice-roller" role="button" data-tooltip="' + game.i18n.localize("ROLL.NAMES.freeCheck") +' ">' +
' <img src="systems/wfrp3e/assets/icons/dice/characteristic_onesuccess.webp" alt="' + game.i18n.localize("ROLL.NAMES.freeCheck") + '"/>' +
'</a>'
);
html.find("#chat-controls > .control-buttons > .wfrp3e-dice-roller").click(async () => {
await new CheckBuilder().render(true);
});
}
});
// Update chat messages with dice images
Hooks.on("renderChatMessage", (app, html, messageData) => {
const content = html.find(".message-content");
html.on("click", ".special-pool-to-player", () => {
const poolData = messageData.message.flags.wfrp3e;
const dicePool = new DicePool(poolData.dicePool);
DiceHelpers.displayRollDialog(poolData.roll.data, dicePool, poolData.description, poolData.roll.skillName, poolData.roll.item, poolData.roll.flavor, poolData.roll.sound);
});
html.find(".roll-effects:not(.disabled) .effect-toggle").click((event) => {
event.stopPropagation();
CheckHelper.toggleEffect(
$(event.currentTarget).parents(".chat-message").data("messageId"),
event.currentTarget.dataset.symbol,
event.currentTarget.dataset.index
);
});
});
Hooks.on("renderActorDirectory", (app, html, data) => {
// Add a button to start the Character Generator.
html.find(".directory-header .header-actions").append(
'<button class="character-generator">' +
' <span class="fas fa-user"></span> ' + game.i18n.localize("ACTOR.GenerateACharacter") +
'</button>'
);
html.find(".character-generator").click(async(event) => {
event.preventDefault();
new CharacterGenerator().render(true);
});
});
// Register all WFRP3e special dice for Dice So Nice! support.
Hooks.once('diceSoNiceReady', (dice3d) => {
dice3d.addSystem({id: "wfrp3e", name: "Warhammer Fantasy Roleplay - 3rd Edition"}, "preferred");
// Characteristic Dice.
dice3d.addDicePreset({
type: "da",
labels: ["", "", "s", "s", "s", "s", "B", "B"],
system: "wfrp3e",
colorset: "characteristic"
}, "d10");
dice3d.addColorset({
name: "characteristic",
description: "WFRP3e/Characteristic Dice",
category: "Warhammer Fantasy Roleplay - 3rd Edition",
foreground: "#FFFFFF",
background: "#4040FF",
outline: "#000000",
material: "plastic",
font: "WFRP3eSymbols",
visibility: 'hidden'
}, "preferred");
// Fortune Dice.
dice3d.addDicePreset({
type: "df",
labels: ["", "", "", "s", "s", "B"],
system: "wfrp3e",
colorset: "fortune"
}, "d6");
dice3d.addColorset({
name: "fortune",
description: "WFRP3e/Fortune Dice",
category: "Warhammer Fantasy Roleplay - 3rd Edition",
foreground: "#000000",
background: "#FFFFFF",
outline: "#FFFFFF",
material: "plastic",
font: "WFRP3eSymbols",
visibility: 'hidden'
}, "preferred");
// Expertise Dice.
dice3d.addDicePreset({
type: "de",
labels: ["", "s", "r", "B", "B", "S"],
system: "wfrp3e",
colorset: "expertise",
}, "d6");
dice3d.addColorset({
name: "expertise",
description: "WFRP3e/Expertise Dice",
category: "Warhammer Fantasy Roleplay - 3rd Edition",
foreground: "#000000",
background: "#FFFF00",
outline: "#FFFFFF",
material: "plastic",
font: "WFRP3eSymbols",
visibility: 'hidden'
}, "preferred");
// Conservative Dice.
dice3d.addDicePreset({
type: "do",
labels: ["", "s", "s", "s", "s", "B", "B", "s\nB", "s\nd", "s\nd"],
system: "wfrp3e",
colorset: "conservative"
}, "d10");
dice3d.addColorset({
name: "conservative",
description: "WFRP3e/Conservative Dice",
category: "Warhammer Fantasy Roleplay - 3rd Edition",
foreground: "#FFFFFF",
background: "#008000",
outline: "#000000",
material: "plastic",
font: "WFRP3eSymbols",
visibility: 'hidden'
}, "preferred");
// Reckless Dice.
dice3d.addDicePreset({
type: "dr",
labels: ["", "", "s\ns", "s\ns", "s\nB", "B\nB", "b", "b", "s\ne", "s\ne"],
system: "wfrp3e",
colorset: "reckless"
}, "d10");
dice3d.addColorset({
name: "reckless",
description: "WFRP3e/Reckless Dice",
category: "Warhammer Fantasy Roleplay - 3rd Edition",
foreground: "#FFFFFF",
background: "#C00000",
outline: "#000000",
material: "plastic",
font: "WFRP3eSymbols",
visibility: 'hidden'
}, "preferred");
// Challenge Dice.
dice3d.addDicePreset({
type: "dh",
labels: ["", "c", "c", "c\nc", "c\nc", "b", "b\nb", "C"],
system: "wfrp3e",
colorset: "challenge"
}, "d10");
dice3d.addColorset({
name: "challenge",
description: "WFRP3e/Challenge Dice",
category: "Warhammer Fantasy Roleplay - 3rd Edition",
foreground: "#FFFFFF",
background: "#800080",
outline: "#000000",
material: "plastic",
font: "WFRP3eSymbols",
visibility: 'hidden'
}, "preferred");
// Misfortune Dice.
dice3d.addDicePreset({
type: "dm",
labels: ["", "", "", "c", "c", "b"],
system: "wfrp3e",
colorset: "misfortune",
}, "d6");
dice3d.addColorset({
name: "misfortune",
description: "WFRP3e/Misfortune Dice",
category: "Warhammer Fantasy Roleplay - 3rd Edition",
foreground: "#FFFFFF",
background: "#000000",
outline: "#000000",
material: "plastic",
font: "WFRP3eSymbols",
visibility: 'hidden'
}, "preferred");
});
handlebarsHelpers.default();