feat: wip work on making classes configurable
This commit is contained in:
parent
e33927b277
commit
bdc454d7c0
11 changed files with 292 additions and 16 deletions
|
@ -61,12 +61,14 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
|||
});
|
||||
const enrichedEffects = await Promise.all(enrichedEffectPromises);
|
||||
|
||||
const settings = getDS4Settings();
|
||||
|
||||
const data = {
|
||||
...this.addTooltipsToData(await super.getData()),
|
||||
config: DS4,
|
||||
itemsByType,
|
||||
enrichedEffects,
|
||||
settings: getDS4Settings(),
|
||||
settings,
|
||||
};
|
||||
return data;
|
||||
}
|
||||
|
@ -409,7 +411,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
|||
}
|
||||
}
|
||||
|
||||
interface DS4ActorSheetData extends ActorSheet.Data {
|
||||
export interface DS4ActorSheetData extends ActorSheet.Data {
|
||||
config: typeof DS4;
|
||||
itemsByType: Record<string, foundry.data.ItemData[]>;
|
||||
enrichedEffects: EnrichedActiveEffectDataSource[];
|
||||
|
|
|
@ -2,16 +2,51 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { DS4ActorSheet } from "../actor-sheet";
|
||||
import { DS4ActorSheet, DS4ActorSheetData } from "../actor-sheet";
|
||||
|
||||
import type { DS4Actor } from "../actor";
|
||||
import type { Classes, HeroClasses } from "../../apps/class-config";
|
||||
|
||||
/**
|
||||
* The Sheet class for DS4 Character Actors
|
||||
*/
|
||||
export class DS4CharacterActorSheet extends DS4ActorSheet {
|
||||
export class DS4CharacterSheet extends DS4ActorSheet {
|
||||
/** @override */
|
||||
static get defaultOptions(): ActorSheet.Options {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["sheet", "ds4-actor-sheet", "ds4-character-sheet"],
|
||||
});
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async getData(): Promise<DS4CharacterSheetData> {
|
||||
const data = await super.getData();
|
||||
const settings = data.settings;
|
||||
|
||||
const classes: Classes = {
|
||||
none: { name: "DS4.ClassNone", hasSpellCasterConfiguration: false },
|
||||
...settings.classes,
|
||||
};
|
||||
const heroClasses: HeroClasses = Object.fromEntries([
|
||||
["none", { name: "DS4.HeroClassNone", baseClass: "none", hasSpellCasterConfiguration: false }],
|
||||
...Object.entries(settings.heroClasses).filter(
|
||||
([, value]) => this.actor.data.data.baseInfo.class === value.baseClass,
|
||||
),
|
||||
]);
|
||||
|
||||
return {
|
||||
...data,
|
||||
classes,
|
||||
heroClasses,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface DS4CharacterSheet {
|
||||
object: DS4Actor & { data: { type: "character"; _source: { type: "character" } } };
|
||||
}
|
||||
|
||||
interface DS4CharacterSheetData extends DS4ActorSheetData {
|
||||
classes: Classes;
|
||||
heroClasses: HeroClasses;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { DS4ActorSheet } from "../actor-sheet";
|
|||
/**
|
||||
* The Sheet class for DS4 Creature Actors
|
||||
*/
|
||||
export class DS4CreatureActorSheet extends DS4ActorSheet {
|
||||
export class DS4CreatureSheet extends DS4ActorSheet {
|
||||
/** @override */
|
||||
static get defaultOptions(): ActorSheet.Options {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
|
|
67
src/apps/class-config.ts
Normal file
67
src/apps/class-config.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
// SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { DS4 } from "../config";
|
||||
import { getGame } from "../helpers";
|
||||
|
||||
export class ClassConfig extends FormApplication<FormApplicationOptions, ClassConfigData, undefined> {
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
template: "systems/ds4/templates/apps/class-config.hbs",
|
||||
});
|
||||
}
|
||||
|
||||
static get defaultClasses(): Classes {
|
||||
return Object.fromEntries(
|
||||
Object.entries(DS4.defaultClasses).map(([key, { i18nKey: name, hasSpellCasterConfiguration }]) => [
|
||||
key,
|
||||
{ name, hasSpellCasterConfiguration },
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
static get defaultHeroClasses(): HeroClasses {
|
||||
return Object.fromEntries(
|
||||
Object.entries(DS4.defaultHeroClasses).map(
|
||||
([key, { i18nKey: name, baseClass, hasSpellCasterConfiguration }]) => [
|
||||
key,
|
||||
{ name, baseClass, hasSpellCasterConfiguration },
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/** @override */
|
||||
getData(): ClassConfigData {
|
||||
const game = getGame();
|
||||
return {
|
||||
classes: game.settings.get("ds4", "classes"),
|
||||
heroClasses: game.settings.get("ds4", "heroClasses"),
|
||||
};
|
||||
}
|
||||
|
||||
protected _updateObject(event: Event, formData?: object): Promise<unknown> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
interface Class {
|
||||
name: string;
|
||||
hasSpellCasterConfiguration: boolean;
|
||||
}
|
||||
|
||||
export type Classes = Record<string, Class>;
|
||||
|
||||
interface HeroClass {
|
||||
name: string;
|
||||
baseClass: string;
|
||||
hasSpellCasterConfiguration: boolean;
|
||||
}
|
||||
|
||||
export type HeroClasses = Record<string, HeroClass>;
|
||||
|
||||
interface ClassConfigData {
|
||||
classes: Classes;
|
||||
heroClasses: HeroClasses;
|
||||
}
|
101
src/config.ts
101
src/config.ts
|
@ -426,4 +426,105 @@ export const DS4 = {
|
|||
eyeColor: "String",
|
||||
specialCharacteristics: "String",
|
||||
},
|
||||
|
||||
defaultClasses: {
|
||||
fighter: {
|
||||
i18nKey: "DS4.ClassFighter",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
scout: {
|
||||
i18nKey: "DS4.ClassScout",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
healer: {
|
||||
i18nKey: "DS4.ClassHealer",
|
||||
hasSpellCasterConfiguration: true,
|
||||
},
|
||||
wizard: {
|
||||
i18nKey: "DS4.ClassWizard",
|
||||
hasSpellCasterConfiguration: true,
|
||||
},
|
||||
sorcerer: {
|
||||
i18nKey: "DS4.ClassSorcerer",
|
||||
hasSpellCasterConfiguration: true,
|
||||
},
|
||||
},
|
||||
|
||||
defaultHeroClasses: {
|
||||
berserker: {
|
||||
i18nKey: "DS4.HeroClassBerserker",
|
||||
baseClass: "fighter",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
weaponMaster: {
|
||||
i18nKey: "DS4.HeroClassWeaponMaster",
|
||||
baseClass: "fighter",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
paladin: {
|
||||
i18nKey: "DS4.HeroClassPaladin",
|
||||
baseClass: "fighter",
|
||||
hasSpellCasterConfiguration: true,
|
||||
},
|
||||
assassin: {
|
||||
i18nKey: "DS4.HeroClassAssassin",
|
||||
baseClass: "scout",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
ranger: {
|
||||
i18nKey: "DS4.HeroClassRanger",
|
||||
baseClass: "scout",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
rogue: {
|
||||
i18nKey: "DS4.HeroClassRogue",
|
||||
baseClass: "scout",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
cleric: {
|
||||
i18nKey: "DS4.HeroClassCleric",
|
||||
baseClass: "healer",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
druid: {
|
||||
i18nKey: "DS4.HeroClassDruid",
|
||||
baseClass: "healer",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
monk: {
|
||||
i18nKey: "DS4.HeroClassMonk",
|
||||
baseClass: "healer",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
archmage: {
|
||||
i18nKey: "DS4.HeroClassArchmage",
|
||||
baseClass: "wizard",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
elementalist: {
|
||||
i18nKey: "DS4.HeroClassElementalist",
|
||||
baseClass: "wizard",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
battleMage: {
|
||||
i18nKey: "DS4.HeroClassBattleMage",
|
||||
baseClass: "wizard",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
bloodMage: {
|
||||
i18nKey: "DS4.HeroClassBloodMage",
|
||||
baseClass: "sorcerer",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
demonologist: {
|
||||
i18nKey: "DS4.HeroClassDemonologist",
|
||||
baseClass: "sorcerer",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
necromancer: {
|
||||
i18nKey: "DS4.HeroClassNecromancer",
|
||||
baseClass: "sorcerer",
|
||||
hasSpellCasterConfiguration: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
4
src/global.d.ts
vendored
4
src/global.d.ts
vendored
|
@ -2,12 +2,16 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import type { Classes, HeroClasses } from "./apps/class-config";
|
||||
|
||||
declare global {
|
||||
namespace ClientSettings {
|
||||
interface Values {
|
||||
"ds4.systemMigrationVersion": number;
|
||||
"ds4.useSlayingDiceForAutomatedChecks": boolean;
|
||||
"ds4.showSlayerPoints": boolean;
|
||||
"ds4.classes": Classes;
|
||||
"ds4.heroClasses": HeroClasses;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { DS4ActiveEffect } from "../active-effect";
|
||||
import { DS4CharacterActorSheet } from "../actor/character/character-sheet";
|
||||
import { DS4CreatureActorSheet } from "../actor/creature/creature-sheet";
|
||||
import { DS4CharacterSheet } from "../actor/character/character-sheet";
|
||||
import { DS4CreatureSheet } from "../actor/creature/creature-sheet";
|
||||
import { DS4ActorProxy } from "../actor/proxy";
|
||||
import { DS4ChatMessage } from "../chat-message";
|
||||
import { DS4 } from "../config";
|
||||
|
@ -66,8 +66,8 @@ async function init() {
|
|||
registerSystemSettings();
|
||||
|
||||
Actors.unregisterSheet("core", ActorSheet);
|
||||
Actors.registerSheet("ds4", DS4CharacterActorSheet, { types: ["character"], makeDefault: true });
|
||||
Actors.registerSheet("ds4", DS4CreatureActorSheet, { types: ["creature"], makeDefault: true });
|
||||
Actors.registerSheet("ds4", DS4CharacterSheet, { types: ["character"], makeDefault: true });
|
||||
Actors.registerSheet("ds4", DS4CreatureSheet, { types: ["creature"], makeDefault: true });
|
||||
Items.unregisterSheet("core", ItemSheet);
|
||||
Items.registerSheet("ds4", DS4ItemSheet, { makeDefault: true });
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { ClassConfig, Classes, HeroClasses } from "./apps/class-config";
|
||||
import { getGame } from "./helpers";
|
||||
|
||||
export function registerSystemSettings(): void {
|
||||
|
@ -11,7 +12,6 @@ export function registerSystemSettings(): void {
|
|||
* Track the migrations version of the latest migration that has been applied
|
||||
*/
|
||||
game.settings.register("ds4", "systemMigrationVersion", {
|
||||
name: "System Migration Version",
|
||||
scope: "world",
|
||||
config: false,
|
||||
type: Number,
|
||||
|
@ -35,12 +35,37 @@ export function registerSystemSettings(): void {
|
|||
type: Boolean,
|
||||
default: false,
|
||||
});
|
||||
|
||||
game.settings.register("ds4", "classes", {
|
||||
scope: "world",
|
||||
config: false,
|
||||
default: ClassConfig.defaultClasses,
|
||||
onChange: renderActorAndSpellSheets,
|
||||
});
|
||||
|
||||
game.settings.register("ds4", "heroClasses", {
|
||||
scope: "world",
|
||||
config: false,
|
||||
default: ClassConfig.defaultHeroClasses,
|
||||
onChange: renderActorAndSpellSheets,
|
||||
});
|
||||
|
||||
game.settings.registerMenu("ds4", "classes", {
|
||||
name: "DS4.MenuClassesName",
|
||||
hint: "DS4.MenuClassesHint",
|
||||
label: "DS4.MenuClassesLabel",
|
||||
icon: "fas fa-chess",
|
||||
restricted: true,
|
||||
type: ClassConfig,
|
||||
});
|
||||
}
|
||||
|
||||
export interface DS4Settings {
|
||||
systemMigrationVersion: number;
|
||||
useSlayingDiceForAutomatedChecks: boolean;
|
||||
showSlayerPoints: boolean;
|
||||
classes: Classes;
|
||||
heroClasses: HeroClasses;
|
||||
}
|
||||
|
||||
export function getDS4Settings(): DS4Settings {
|
||||
|
@ -49,5 +74,18 @@ export function getDS4Settings(): DS4Settings {
|
|||
systemMigrationVersion: game.settings.get("ds4", "systemMigrationVersion"),
|
||||
useSlayingDiceForAutomatedChecks: game.settings.get("ds4", "useSlayingDiceForAutomatedChecks"),
|
||||
showSlayerPoints: game.settings.get("ds4", "showSlayerPoints"),
|
||||
classes: game.settings.get("ds4", "classes"),
|
||||
heroClasses: game.settings.get("ds4", "heroClasses"),
|
||||
};
|
||||
}
|
||||
|
||||
function renderActorAndSpellSheets() {
|
||||
for (const application of Object.values(ui.windows)) {
|
||||
if (
|
||||
application instanceof ActorSheet ||
|
||||
(application instanceof ItemSheet && application.item.type === "spell")
|
||||
) {
|
||||
application.render(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,8 +87,8 @@
|
|||
"templates": ["base"],
|
||||
"baseInfo": {
|
||||
"race": "",
|
||||
"class": "",
|
||||
"heroClass": "",
|
||||
"class": "none",
|
||||
"heroClass": "none",
|
||||
"culture": ""
|
||||
},
|
||||
"progression": {
|
||||
|
|
19
templates/apps/class-config.hbs
Normal file
19
templates/apps/class-config.hbs
Normal file
|
@ -0,0 +1,19 @@
|
|||
{{!--
|
||||
SPDX-FileCopyrightText: 2022 Johannes Loher
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
--}}
|
||||
|
||||
<form>
|
||||
<ul>
|
||||
{{#each classes as | value key |}}
|
||||
<li>{{localize value.name}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
<hr />
|
||||
<ul>
|
||||
{{#each heroClasses as | value key |}}
|
||||
<li>{{localize value.name}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</form>
|
|
@ -51,13 +51,23 @@ SPDX-License-Identifier: MIT
|
|||
<div class="ds4-actor-properties__property">
|
||||
<label class="ds4-actor-properties__property-label"
|
||||
for="data.baseInfo.class-{{data._id}}">{{config.i18n.characterBaseInfo.class}}</label>
|
||||
<input type="text" id="data.baseInfo.class-{{data._id}}" name="data.baseInfo.class"
|
||||
value="{{data.data.baseInfo.class}}" data-dtype="String" />
|
||||
<select id="data.baseInfo.class-{{data._id}}" name="data.baseInfo.class" data-dtype="String">
|
||||
{{#select data.data.baseInfo.class}}
|
||||
{{#each classes as |value key|}}
|
||||
<option value="{{key}}">{{localize value.name}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="ds4-actor-properties__property">
|
||||
<label class="ds4-actor-properties__property-label"
|
||||
for="data.baseInfo.heroClass-{{data._id}}">{{config.i18n.characterBaseInfo.heroClass}}</label>
|
||||
<input type="text" id="data.baseInfo.heroClass-{{data._id}}" name="data.baseInfo.heroClass"
|
||||
value="{{data.data.baseInfo.heroClass}}" data-dtype="String" />
|
||||
<select id="data.baseInfo.heroClass-{{data._id}}" name="data.baseInfo.heroClass" data-dtype="String">
|
||||
{{#select data.data.baseInfo.heroClass}}
|
||||
{{#each heroClasses as |value key|}}
|
||||
<option value="{{key}}">{{localize value.name}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue