mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Added ownership to countdowns
This commit is contained in:
parent
81cda222da
commit
08c136d740
13 changed files with 431 additions and 55 deletions
|
|
@ -4,7 +4,7 @@ import * as models from './module/data/_module.mjs';
|
|||
import * as documents from './module/documents/_module.mjs';
|
||||
import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs';
|
||||
import DhCombatTracker from './module/ui/combatTracker.mjs';
|
||||
import { GMUpdateEvent, handleSocketEvent, socketEvent } from './module/helpers/socket.mjs';
|
||||
import { handleSocketEvent, registerSocketHooks } from './module/helpers/socket.mjs';
|
||||
import { registerDHSettings } from './module/applications/settings.mjs';
|
||||
import DhpChatLog from './module/ui/chatLog.mjs';
|
||||
import DhpRuler from './module/ui/ruler.mjs';
|
||||
|
|
@ -13,12 +13,13 @@ import { DhDualityRollEnricher, DhTemplateEnricher } from './module/enrichers/_m
|
|||
import { getCommandTarget, rollCommandToJSON, setDiceSoNiceForDualityRoll } from './module/helpers/utils.mjs';
|
||||
import { abilities } from './module/config/actorConfig.mjs';
|
||||
import Resources from './module/applications/resources.mjs';
|
||||
import { NarrativeCountdowns, registerCountdownHooks } from './module/applications/countdowns.mjs';
|
||||
import { NarrativeCountdowns, registerCountdownApplicationHooks } from './module/applications/countdowns.mjs';
|
||||
import DHDualityRoll from './module/data/chat-message/dualityRoll.mjs';
|
||||
import { DualityRollColor } from './module/data/settings/Appearance.mjs';
|
||||
import { DhMeasuredTemplate } from './module/placeables/_module.mjs';
|
||||
import { renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs';
|
||||
import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs';
|
||||
import { registerCountdownHooks } from './module/data/countdowns.mjs';
|
||||
|
||||
globalThis.SYSTEM = SYSTEM;
|
||||
|
||||
|
|
@ -135,34 +136,12 @@ Hooks.on('ready', () => {
|
|||
);
|
||||
|
||||
registerCountdownHooks();
|
||||
registerSocketHooks();
|
||||
registerCountdownApplicationHooks();
|
||||
});
|
||||
|
||||
Hooks.once('dicesoniceready', () => {});
|
||||
|
||||
Hooks.on(socketEvent.GMUpdate, async (action, uuid, update) => {
|
||||
if (game.user.isGM) {
|
||||
const document = uuid ? await fromUuid(uuid) : null;
|
||||
switch (action) {
|
||||
case GMUpdateEvent.UpdateDocument:
|
||||
if (document && update) {
|
||||
await document.update(update);
|
||||
}
|
||||
break;
|
||||
case GMUpdateEvent.UpdateFear:
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(
|
||||
SYSTEM.id,
|
||||
SYSTEM.SETTINGS.gameSettings.Resources.Fear,
|
||||
Math.max(Math.min(update, 6), 0)
|
||||
);
|
||||
Hooks.callAll(socketEvent.DhpFearUpdate);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, { action: socketEvent.DhpFearUpdate });
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Hooks.on('renderChatMessageHTML', (_, element) => {
|
||||
element
|
||||
.querySelectorAll('.duality-roll-button')
|
||||
|
|
|
|||
|
|
@ -1056,12 +1056,20 @@
|
|||
"AddCountdown": "Add Countdown",
|
||||
"RemoveCountdownTitle": "Remove Countdown",
|
||||
"RemoveCountdownText": "Are you sure you want to remove the countdown: {name}?",
|
||||
"OpenOwnership": "Edit Player Ownership",
|
||||
"Title": "{type} Countdowns",
|
||||
"Types": {
|
||||
"narrative": "Narrative",
|
||||
"encounter": "Encounter"
|
||||
},
|
||||
"Notifications": {
|
||||
"LimitedOwnershipMaximise": "You don't have permission to enter edit view"
|
||||
}
|
||||
},
|
||||
"OwnershipSelection": {
|
||||
"Title": "Ownership Selection - {name}",
|
||||
"Default": "Default Ownership"
|
||||
},
|
||||
"Sheets": {
|
||||
"PC": {
|
||||
"Name": "Name",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { countdownTypes } from '../config/generalConfig.mjs';
|
||||
import { GMUpdateEvent, RefreshType, socketEvent } from '../helpers/socket.mjs';
|
||||
import OwnershipSelection from './ownershipSelection.mjs';
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
|
|
@ -28,7 +30,9 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
actions: {
|
||||
addCountdown: this.addCountdown,
|
||||
removeCountdown: this.removeCountdown,
|
||||
editImage: this.onEditImage
|
||||
editImage: this.onEditImage,
|
||||
openOwnership: this.openOwnership,
|
||||
openCountdownOwnership: this.openCountdownOwnership
|
||||
},
|
||||
form: { handler: this.updateData, submitOnChange: true }
|
||||
};
|
||||
|
|
@ -60,8 +64,23 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
const context = await super._prepareContext(_options);
|
||||
const countdownData = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath];
|
||||
|
||||
context.isGM = game.user.isGM;
|
||||
context.base = this.basePath;
|
||||
context.source = countdownData.toObject();
|
||||
|
||||
context.canCreate = countdownData.playerOwnership[game.user.id].value === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER;
|
||||
context.source = {
|
||||
...countdownData,
|
||||
countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => {
|
||||
const countdown = countdownData.countdowns[key];
|
||||
|
||||
const ownershipValue = countdown.playerOwnership[game.user.id].value;
|
||||
if (ownershipValue > CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
||||
acc[key] = { ...countdown, canEdit: ownershipValue === CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER };
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
};
|
||||
context.systemFields = countdownData.schema.fields;
|
||||
context.countdownFields = context.systemFields.countdowns.element.fields;
|
||||
context.minimized = this.minimized || _options.isFirstRender;
|
||||
|
|
@ -75,8 +94,20 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns).toObject(),
|
||||
data
|
||||
);
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, newSetting);
|
||||
this.render();
|
||||
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, newSetting);
|
||||
this.render();
|
||||
} else {
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: {
|
||||
action: GMUpdateEvent.UpdateSetting,
|
||||
uuid: SYSTEM.SETTINGS.gameSettings.Countdowns,
|
||||
update: newSetting
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async minimize() {
|
||||
|
|
@ -88,6 +119,12 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
|
||||
async maximize() {
|
||||
if (this.minimized) {
|
||||
const settings = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath];
|
||||
if (settings.playerOwnership[game.user.id].value <= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED) {
|
||||
ui.notifications.info(game.i18n.localize('DAGGERHEART.Countdown.Notifications.LimitedOwnership'));
|
||||
return;
|
||||
}
|
||||
|
||||
this.element.querySelector('.expanded-view').classList.toggle('hidden');
|
||||
this.element.querySelector('.minimized-view').classList.toggle('hidden');
|
||||
}
|
||||
|
|
@ -95,6 +132,31 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
await super.maximize();
|
||||
}
|
||||
|
||||
async updateSetting(update) {
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, update);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.Refresh,
|
||||
data: {
|
||||
refreshType: RefreshType.Countdown,
|
||||
application: `${this.basePath}-countdowns`
|
||||
}
|
||||
});
|
||||
|
||||
this.render();
|
||||
} else {
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.GMUpdate,
|
||||
data: {
|
||||
action: GMUpdateEvent.UpdateSetting,
|
||||
uuid: SYSTEM.SETTINGS.gameSettings.Countdowns,
|
||||
update: update,
|
||||
refresh: { refreshType: RefreshType.Countdown, application: `${this.basePath}-countdowns` }
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static onEditImage(_, target) {
|
||||
const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath];
|
||||
const current = setting.countdowns[target.dataset.countdown].img;
|
||||
|
|
@ -114,13 +176,51 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
[`${this.basePath}.countdowns.${countdown}.img`]: path
|
||||
});
|
||||
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, setting);
|
||||
this.render();
|
||||
await this.updateSetting(setting);
|
||||
}
|
||||
|
||||
static openOwnership(_, target) {
|
||||
new Promise((resolve, reject) => {
|
||||
const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath];
|
||||
const ownership = { default: setting.ownership.default, players: setting.playerOwnership };
|
||||
new OwnershipSelection(resolve, reject, this.title, ownership).render(true);
|
||||
}).then(async ownership => {
|
||||
const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
||||
await setting.updateSource({
|
||||
[`${this.basePath}.ownership`]: ownership
|
||||
});
|
||||
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, setting.toObject());
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
|
||||
static openCountdownOwnership(_, target) {
|
||||
const countdownId = target.dataset.countdown;
|
||||
new Promise((resolve, reject) => {
|
||||
const countdown = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath]
|
||||
.countdowns[countdownId];
|
||||
const ownership = { default: countdown.ownership.default, players: countdown.playerOwnership };
|
||||
new OwnershipSelection(resolve, reject, countdown.name, ownership).render(true);
|
||||
}).then(async ownership => {
|
||||
const setting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
||||
await setting.updateSource({
|
||||
[`${this.basePath}.countdowns.${countdownId}.ownership`]: ownership
|
||||
});
|
||||
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, setting);
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
|
||||
async updateCountdownValue(event, increase) {
|
||||
const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
||||
const countdown = countdownSetting[this.basePath].countdowns[event.currentTarget.dataset.countdown];
|
||||
|
||||
if (countdown.playerOwnership[game.user.id] < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentValue = countdown.progress.current;
|
||||
|
||||
if (increase && currentValue === countdown.progress.max) return;
|
||||
|
|
@ -132,20 +232,25 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
: currentValue - 1
|
||||
});
|
||||
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject());
|
||||
this.render();
|
||||
await this.updateSetting(countdownSetting.toObject());
|
||||
}
|
||||
|
||||
static async addCountdown() {
|
||||
const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
||||
await countdownSetting.updateSource({
|
||||
[`${this.basePath}.countdowns.${foundry.utils.randomID()}`]: {
|
||||
name: game.i18n.localize('DAGGERHEART.Countdown.NewCountdown')
|
||||
name: game.i18n.localize('DAGGERHEART.Countdown.NewCountdown'),
|
||||
ownership: game.user.isGM
|
||||
? {}
|
||||
: {
|
||||
players: {
|
||||
[game.user.id]: { type: CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject());
|
||||
this.render();
|
||||
await this.updateSetting(countdownSetting.toObject());
|
||||
}
|
||||
|
||||
static async removeCountdown(_, target) {
|
||||
|
|
@ -162,8 +267,7 @@ class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
|
||||
await countdownSetting.updateSource({ [`${this.basePath}.countdowns.-=${target.dataset.countdown}`]: null });
|
||||
|
||||
await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject());
|
||||
this.render();
|
||||
await this.updateSetting(countdownSetting.toObject());
|
||||
}
|
||||
|
||||
async open() {
|
||||
|
|
@ -197,7 +301,7 @@ export class EncounterCountdowns extends Countdowns {
|
|||
};
|
||||
}
|
||||
|
||||
export const registerCountdownHooks = () => {
|
||||
export const registerCountdownApplicationHooks = () => {
|
||||
const updateCountdowns = async shouldIncrease => {
|
||||
if (game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Automation).countdowns) {
|
||||
const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns);
|
||||
|
|
|
|||
72
module/applications/ownershipSelection.mjs
Normal file
72
module/applications/ownershipSelection.mjs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||
|
||||
export default class OwnershipSelection extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||
constructor(resolve, reject, name, ownership) {
|
||||
super({});
|
||||
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
this.name = name;
|
||||
this.ownership = ownership;
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
tag: 'form',
|
||||
classes: ['daggerheart', 'views', 'ownership-selection'],
|
||||
position: {
|
||||
width: 600,
|
||||
height: 'auto'
|
||||
},
|
||||
form: { handler: this.updateData }
|
||||
};
|
||||
|
||||
static PARTS = {
|
||||
selection: {
|
||||
template: 'systems/daggerheart/templates/views/ownershipSelection.hbs'
|
||||
}
|
||||
};
|
||||
|
||||
get title() {
|
||||
return game.i18n.format('DAGGERHEART.OwnershipSelection.Title', { name: this.name });
|
||||
}
|
||||
|
||||
async _prepareContext(_options) {
|
||||
const context = await super._prepareContext(_options);
|
||||
context.ownershipOptions = Object.keys(CONST.DOCUMENT_OWNERSHIP_LEVELS).map(level => ({
|
||||
value: CONST.DOCUMENT_OWNERSHIP_LEVELS[level],
|
||||
label: game.i18n.localize(`OWNERSHIP.${level}`)
|
||||
}));
|
||||
context.ownership = {
|
||||
default: this.ownership.default,
|
||||
players: Object.keys(this.ownership.players).reduce((acc, x) => {
|
||||
const user = game.users.get(x);
|
||||
if (!user.isGM) {
|
||||
acc[x] = {
|
||||
img: user.character?.img,
|
||||
name: user.name,
|
||||
ownership: this.ownership.players[x].value
|
||||
};
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {})
|
||||
};
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
static async updateData(event, _, formData) {
|
||||
const { ownership } = foundry.utils.expandObject(formData.object);
|
||||
|
||||
this.resolve(ownership);
|
||||
this.close(true);
|
||||
}
|
||||
|
||||
async close(fromSave) {
|
||||
if (!fromSave) {
|
||||
this.reject();
|
||||
}
|
||||
|
||||
await super.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { countdownTypes } from '../config/generalConfig.mjs';
|
||||
import { RefreshType, socketEvent } from '../helpers/socket.mjs';
|
||||
|
||||
export default class DhCountdowns extends foundry.abstract.DataModel {
|
||||
static defineSchema() {
|
||||
|
|
@ -19,9 +20,40 @@ class DhCountdownData extends foundry.abstract.DataModel {
|
|||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCountdown))
|
||||
countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCountdown)),
|
||||
ownership: new fields.SchemaField({
|
||||
default: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE
|
||||
}),
|
||||
players: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
type: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
|
||||
})
|
||||
})
|
||||
)
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
get playerOwnership() {
|
||||
return Array.from(game.users).reduce((acc, user) => {
|
||||
acc[user.id] = {
|
||||
value: user.isGM
|
||||
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
|
||||
? this.ownership.players[user.id].type
|
||||
: this.ownership.default,
|
||||
isGM: user.isGM
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
class DhCountdown extends foundry.abstract.DataModel {
|
||||
|
|
@ -37,6 +69,22 @@ class DhCountdown extends foundry.abstract.DataModel {
|
|||
base64: false,
|
||||
initial: 'icons/magic/time/hourglass-yellow-green.webp'
|
||||
}),
|
||||
ownership: new fields.SchemaField({
|
||||
default: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE
|
||||
}),
|
||||
players: new fields.TypedObjectField(
|
||||
new fields.SchemaField({
|
||||
type: new fields.NumberField({
|
||||
required: true,
|
||||
choices: Object.values(CONST.DOCUMENT_OWNERSHIP_LEVELS),
|
||||
initial: CONST.DOCUMENT_OWNERSHIP_LEVELS.INHERIT
|
||||
})
|
||||
})
|
||||
)
|
||||
}),
|
||||
progress: new fields.SchemaField({
|
||||
current: new fields.NumberField({
|
||||
required: true,
|
||||
|
|
@ -64,4 +112,28 @@ class DhCountdown extends foundry.abstract.DataModel {
|
|||
})
|
||||
};
|
||||
}
|
||||
|
||||
get playerOwnership() {
|
||||
return Array.from(game.users).reduce((acc, user) => {
|
||||
acc[user.id] = {
|
||||
value: user.isGM
|
||||
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
|
||||
? this.ownership.players[user.id].type
|
||||
: this.ownership.default,
|
||||
isGM: user.isGM
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
export const registerCountdownHooks = () => {
|
||||
Hooks.on(socketEvent.Refresh, ({ refreshType, application }) => {
|
||||
if (refreshType === RefreshType.Countdown) {
|
||||
foundry.applications.instances.get(application)?.render();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import BaseDataItem from './base.mjs';
|
|||
const featureSchema = () => {
|
||||
return new foundry.data.fields.SchemaField({
|
||||
name: new foundry.data.fields.StringField({ required: true }),
|
||||
effects: new ForeignDocumentUUIDArrayField({ type: 'Item', required: false }),
|
||||
effects: new ForeignDocumentUUIDArrayField({ type: 'ActiveEffect', required: false }),
|
||||
actions: new foundry.data.fields.ArrayField(new ActionField())
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,20 +1,68 @@
|
|||
export function handleSocketEvent({ action = null, data = {} } = {}) {
|
||||
switch (action) {
|
||||
case socketEvent.GMUpdate:
|
||||
Hooks.callAll(socketEvent.GMUpdate, data.action, data.uuid, data.update);
|
||||
Hooks.callAll(socketEvent.GMUpdate, data);
|
||||
break;
|
||||
case socketEvent.DhpFearUpdate:
|
||||
Hooks.callAll(socketEvent.DhpFearUpdate);
|
||||
break;
|
||||
case socketEvent.Refresh:
|
||||
Hooks.call(socketEvent.Refresh, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export const socketEvent = {
|
||||
GMUpdate: 'DhpGMUpdate',
|
||||
DhpFearUpdate: 'DhpFearUpdate'
|
||||
GMUpdate: 'DhGMUpdate',
|
||||
Refresh: 'DhRefresh',
|
||||
DhpFearUpdate: 'DhFearUpdate'
|
||||
};
|
||||
|
||||
export const GMUpdateEvent = {
|
||||
UpdateDocument: 'DhpGMUpdateDocument',
|
||||
UpdateFear: 'DhpUpdateFear'
|
||||
UpdateDocument: 'DhGMUpdateDocument',
|
||||
UpdateSetting: 'DhGMUpdateSetting',
|
||||
UpdateFear: 'DhGMUpdateFear'
|
||||
};
|
||||
|
||||
export const RefreshType = {
|
||||
Countdown: 'DhCoundownRefresh'
|
||||
};
|
||||
|
||||
export const registerSocketHooks = () => {
|
||||
Hooks.on(socketEvent.GMUpdate, async data => {
|
||||
if (game.user.isGM) {
|
||||
const document = data.uuid ? await fromUuid(data.uuid) : null;
|
||||
switch (data.action) {
|
||||
case GMUpdateEvent.UpdateDocument:
|
||||
if (document && data.update) {
|
||||
await document.update(data.update);
|
||||
}
|
||||
break;
|
||||
case GMUpdateEvent.UpdateSetting:
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(SYSTEM.id, data.uuid, data.update);
|
||||
}
|
||||
break;
|
||||
case GMUpdateEvent.UpdateFear:
|
||||
if (game.user.isGM) {
|
||||
await game.settings.set(
|
||||
SYSTEM.id,
|
||||
SYSTEM.SETTINGS.gameSettings.Resources.Fear,
|
||||
Math.max(Math.min(data.update, 6), 0)
|
||||
);
|
||||
Hooks.callAll(socketEvent.DhpFearUpdate);
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, { action: socketEvent.DhpFearUpdate });
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (data.refresh) {
|
||||
await game.socket.emit(`system.${SYSTEM.id}`, {
|
||||
action: socketEvent.Refresh,
|
||||
data: data.refresh
|
||||
});
|
||||
Hooks.call(socketEvent.Refresh, data.refresh);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,6 +90,14 @@
|
|||
.countdown-fieldset {
|
||||
width: 340px;
|
||||
height: min-content;
|
||||
position: relative;
|
||||
|
||||
.ownership-button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.countdown-container {
|
||||
display: flex;
|
||||
|
|
@ -100,6 +108,10 @@
|
|||
width: 150px;
|
||||
height: 150px;
|
||||
cursor: pointer;
|
||||
|
||||
&.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
}
|
||||
|
||||
.countdown-inner-container {
|
||||
|
|
|
|||
|
|
@ -3077,6 +3077,24 @@ div.daggerheart.views.multiclass {
|
|||
.daggerheart.levelup .levelup-footer {
|
||||
display: flex;
|
||||
}
|
||||
.daggerheart.views.ownership-selection .ownership-outer-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.daggerheart.views.ownership-selection .ownership-outer-container .ownership-container {
|
||||
display: flex;
|
||||
border: 2px solid light-dark(#18162e, #f3c267);
|
||||
border-radius: 6px;
|
||||
padding: 0 4px 0 0;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.daggerheart.views.ownership-selection .ownership-outer-container .ownership-container img {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
border-radius: 6px 0 0 6px;
|
||||
}
|
||||
:root {
|
||||
--shadow-text-stroke: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
|
||||
--fear-animation: background 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease, opacity 0.3s ease;
|
||||
|
|
@ -3268,6 +3286,13 @@ div.daggerheart.views.multiclass {
|
|||
.daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset {
|
||||
width: 340px;
|
||||
height: min-content;
|
||||
position: relative;
|
||||
}
|
||||
.daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .ownership-button {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
font-size: 18px;
|
||||
}
|
||||
.daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .countdown-container {
|
||||
display: flex;
|
||||
|
|
@ -3279,6 +3304,9 @@ div.daggerheart.views.multiclass {
|
|||
height: 150px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .countdown-container img.disabled {
|
||||
cursor: initial;
|
||||
}
|
||||
.daggerheart.dh-style.countdown .window-content > div .expanded-view .countdowns-container .countdown-fieldset .countdown-container .countdown-inner-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
@import './dialog.less';
|
||||
@import './characterCreation.less';
|
||||
@import './levelup.less';
|
||||
@import './ownershipSelection.less';
|
||||
@import '../node_modules/@yaireo/tagify/dist/tagify.css';
|
||||
@import './resources.less';
|
||||
@import './countdown.less';
|
||||
|
|
|
|||
22
styles/ownershipSelection.less
Normal file
22
styles/ownershipSelection.less
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
.daggerheart.views.ownership-selection {
|
||||
.ownership-outer-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
.ownership-container {
|
||||
display: flex;
|
||||
border: 2px solid light-dark(@dark-blue, @golden);
|
||||
border-radius: 6px;
|
||||
padding: 0 4px 0 0;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
||||
img {
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
border-radius: 6px 0 0 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,29 @@
|
|||
<div>
|
||||
<div class="expanded-view {{#if minimized}}hidden{{/if}}">
|
||||
<div class="flexrow"><button data-action="addCountdown">{{localize "DAGGERHEART.Countdown.AddCountdown"}}</button></div>
|
||||
<div class="flexrow">
|
||||
{{#if canCreate}}<button data-action="addCountdown">{{localize "DAGGERHEART.Countdown.AddCountdown"}}</button>{{/if}}
|
||||
{{#if isGM}}<button class="flex0" data-action="openOwnership" data-tooltip="{{localize "DAGGERHEART.Countdown.OpenOwnership"}}"><i class="fa-solid fa-users"></i></button>{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="countdowns-container">
|
||||
{{#each source.countdowns}}
|
||||
<fieldset class="countdown-fieldset">
|
||||
<legend>{{this.name}} <a><i class="fa-solid fa-trash icon-button" data-action="removeCountdown" data-countdown="{{@key}}"></i></a></legend>
|
||||
<legend>
|
||||
{{this.name}}
|
||||
{{#if this.canEdit}}<a><i class="fa-solid fa-trash icon-button" data-action="removeCountdown" data-countdown="{{@key}}"></i></a>{{/if}}
|
||||
{{#if @root.isGM}}<a><i class="fa-solid fa-users icon-button" data-action="openCountdownOwnership" data-countdown="{{@key}}" data-tooltip="{{localize "DAGGERHEART.Countdown.OpenOwnership"}}"></i></a>{{/if}}
|
||||
</legend>
|
||||
|
||||
|
||||
<div class="countdown-container">
|
||||
<img src="{{this.img}}" data-action='editImage' data-countdown="{{@key}}" />
|
||||
<img src="{{this.img}}" {{#if this.canEdit}}data-action='editImage'{{else}}class="disabled"{{/if}} data-countdown="{{@key}}" />
|
||||
<div class="countdown-inner-container">
|
||||
{{formGroup @root.countdownFields.name name=(concat @root.base ".countdowns." @key ".name") value=this.name localize=true}}
|
||||
{{formGroup @root.countdownFields.name name=(concat @root.base ".countdowns." @key ".name") value=this.name localize=true disabled=(not this.canEdit)}}
|
||||
<div class="countdown-value-container">
|
||||
{{formGroup @root.countdownFields.progress.fields.current name=(concat @root.base ".countdowns." @key ".progress.current") value=this.progress.current localize=true}}
|
||||
{{formGroup @root.countdownFields.progress.fields.max name=(concat @root.base ".countdowns." @key ".progress.max") value=this.progress.max localize=true}}
|
||||
{{formGroup @root.countdownFields.progress.fields.current name=(concat @root.base ".countdowns." @key ".progress.current") value=this.progress.current localize=true disabled=(not this.canEdit)}}
|
||||
{{formGroup @root.countdownFields.progress.fields.max name=(concat @root.base ".countdowns." @key ".progress.max") value=this.progress.max localize=true disabled=(not this.canEdit)}}
|
||||
</div>
|
||||
{{formGroup @root.countdownFields.progress.fields.type.fields.value name=(concat @root.base ".countdowns." @key ".progress.type.value") value=this.progress.type.value localize=true localize=true}}
|
||||
{{formGroup @root.countdownFields.progress.fields.type.fields.value name=(concat @root.base ".countdowns." @key ".progress.type.value") value=this.progress.type.value localize=true localize=true disabled=(not this.canEdit)}}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
|
@ -24,7 +32,7 @@
|
|||
</div>
|
||||
<div class="minimized-view {{#if (not minimized)}}hidden{{/if}}">
|
||||
{{#each source.countdowns}}
|
||||
<a class="mini-countdown-container" data-countdown="{{@key}}">
|
||||
<a class="mini-countdown-container {{#if (not this.canEdit)}}disabled{{/if}}" data-countdown="{{@key}}">
|
||||
<img src="{{this.img}}" />
|
||||
<div class="mini-countdown-name">{{this.name}}</div>
|
||||
<div class="mini-countdown-value">{{this.progress.current}}/{{this.progress.max}}</div>
|
||||
|
|
|
|||
22
templates/views/ownershipSelection.hbs
Normal file
22
templates/views/ownershipSelection.hbs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<div class="ownership-outer-container">
|
||||
<div class="form-group">
|
||||
<label>{{localize "DAGGERHEART.OwnershipSelection.Default"}}</label>
|
||||
<div class="form-fields">
|
||||
<select name="ownership.default" data-dtype="Number">
|
||||
{{selectOptions @root.ownershipOptions selected=ownership.default labelAttr="label" valueAttr="value" }}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{{#each ownership.players as |player id|}}
|
||||
<div class="ownership-container">
|
||||
{{#if player.img}}<img src="{{player.img}}" />{{/if}}
|
||||
<div>{{player.name}}</div>
|
||||
<select name="{{concat "ownership.players." id ".type"}}" data-dtype="Number">
|
||||
{{selectOptions @root.ownershipOptions selected=player.ownership labelAttr="label" valueAttr="value" }}
|
||||
</select>
|
||||
</div>
|
||||
{{/each}}
|
||||
<footer class="flexrow">
|
||||
<button type="submit">{{localize "Save"}}</button>
|
||||
</footer>
|
||||
</div>
|
||||
Loading…
Add table
Add a link
Reference in a new issue