diff --git a/package-lock.json b/package-lock.json
index 653f0089..f782fa7b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,7 +12,7 @@
"gulp-json-modify": "^1.0.2"
},
"devDependencies": {
- "@foundryvtt/foundryvtt-cli": "^3.0.0",
+ "@foundryvtt/foundryvtt-cli": "^3.0.2",
"cb": "^0.1.1",
"del": "^8.0.1",
"fvtt-types": "npm:@league-of-foundry-developers/foundry-vtt-types@^13.346.0-beta.20250812191140",
@@ -209,9 +209,9 @@
}
},
"node_modules/@foundryvtt/foundryvtt-cli": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@foundryvtt/foundryvtt-cli/-/foundryvtt-cli-3.0.0.tgz",
- "integrity": "sha512-OiF4HtnYg5An1ivVxB68mOj5LO5gMHd4uHmC5nWdD8IYxpK0pSYw3t+cHrUYDp+Tic78uwFuHxLyc+ZNeZXulA==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@foundryvtt/foundryvtt-cli/-/foundryvtt-cli-3.0.2.tgz",
+ "integrity": "sha512-coh4Cf4FD/GHxk2QMsd+3wLMivNeih4rfkbZy8CaYjdlpo6iciFQwxLqznZWtn+5p06zekvS2xLUF55NnbXQDw==",
"dev": true,
"dependencies": {
"chalk": "^5.4.1",
diff --git a/package.json b/package.json
index 5d99859c..3071030a 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
"installToFoundry": "node installToFoundry.mjs"
},
"devDependencies": {
- "@foundryvtt/foundryvtt-cli": "^3.0.0",
+ "@foundryvtt/foundryvtt-cli": "^3.0.2",
"cb": "^0.1.1",
"del": "^8.0.1",
"fvtt-types": "npm:@league-of-foundry-developers/foundry-vtt-types@^13.346.0-beta.20250812191140",
diff --git a/src/lang/de.json b/src/lang/de.json
index a503b8d3..164dc25c 100644
--- a/src/lang/de.json
+++ b/src/lang/de.json
@@ -1,22 +1,50 @@
{
- "TYPES": {
- "Actor": {
- "Character": "Held",
- "Creature": "Kreatur",
- "Group": "Heldengruppe",
- "Merchant": "Händler"
- },
- "Item": {
- "ActiveEffect": "Aktiver Effekt",
- "Equipment": "Ausrüstungsgegenstand",
- "Skill": "Talent",
- "Advantage": "Vor-/Nachteil",
- "SpecialAbility": "Sonderfertigkeit",
- "Spell": "Zauber",
- "Liturgy": "Liturgie",
- "Species": "Spezies",
- "Culture": "Kultur",
- "Profession": "Profession"
- }
+ "TYPES": {
+ "Actor": {
+ "Character": "Held",
+ "Creature": "Kreatur",
+ "Group": "Heldengruppe",
+ "Merchant": "Händler"
+ },
+ "Item": {
+ "ActiveEffect": "Aktiver Effekt",
+ "Equipment": "Ausrüstungsgegenstand",
+ "Skill": "Talent",
+ "Advantage": "Vor-/Nachteil",
+ "SpecialAbility": "Sonderfertigkeit",
+ "Spell": "Zauber",
+ "Liturgy": "Liturgie",
+ "Species": "Spezies",
+ "Culture": "Kultur",
+ "Profession": "Profession"
}
+ },
+ "COOLDOWN": {
+ "cancel": "{t} abbrechen"
+ },
+ "WEAPON": {
+ "attack": "Mit {weapon} angreifen",
+ "parry": "Mit {weapon} parrieren",
+ "damage": "Mit {weapon} schaden machen",
+ "initiative": "Initiative würfeln"
+ },
+ "COMBAT_DIALOG": {
+ "notReadyReason": {
+ "title": "Angriff kann aus folgenden Gründen nicht ausgeführt werden:",
+ "noTarget": "Kein Ziel ausgewählt",
+ "noWeapon": "Keine Waffe ausgewählt",
+ "noSkill": "Kein Waffentalent ausgewählt",
+ "noManeuver": "Kein Manöver ausgewählt",
+ "impossible": "Erschwernis zu hoch für Talentwert"
+ }
+ },
+ "COMBAT_DIALOG_TP": {
+ "windowTitle": "Schaden Würfeln",
+ "regularFormula": "Schadensformel:",
+ "bonusDamage": "Zusätzlicher Schaden:",
+ "buttonText": "Würfeln"
+ },
+ "ITEM_BROWSER": {
+ "progress": "{current}/{max}: Importiere von {compendium}"
+ }
}
diff --git a/src/main.mjs b/src/main.mjs
index 09d2c24a..f0da9309 100644
--- a/src/main.mjs
+++ b/src/main.mjs
@@ -2,14 +2,23 @@ import {XmlImportDialog} from "./module/dialog/xmlImportDialog.mjs";
import {initGlobalSettings, initUserSettings} from "./module/settings/global-settings.mjs";
import {setUpActorSheets, setUpItemSheets} from "./module/setup/sheets.mjs";
import {loadPartials} from "./module/setup/partials.mjs";
-import {initCombat, initDataModels, initDocumentClasses, initGlobalAccess} from "./module/setup/config.mjs";
+import {
+ initSocketLib,
+ initCombat,
+ initDataModels,
+ initDocumentClasses,
+ initGlobalAccess
+} from "./module/setup/config.mjs";
import {initHandlebarHelpers} from "./module/handlebar-helpers/index.mjs";
Hooks.once("init", () => {
console.log("DSA 4.1 is ready for development!")
- game.DSA41 = initGlobalAccess()
+ game.DSA41 = {
+ ...game.DSA41,
+ ...initGlobalAccess()
+ }
initDocumentClasses(CONFIG)
initUserSettings(game.settings)
@@ -27,6 +36,9 @@ Hooks.once("init", () => {
initHandlebarHelpers(Handlebars)
})
+game.DSA41 = {}
+initSocketLib(game.DSA41)
+
Hooks.on("getActorContextOptions", (application, menuItems) => {
menuItems.push({
name: "Import from XML",
diff --git a/src/module/data/character.mjs b/src/module/data/character.mjs
index 8297bd7d..c571c246 100644
--- a/src/module/data/character.mjs
+++ b/src/module/data/character.mjs
@@ -138,6 +138,10 @@ export class PlayerCharacterDataModel extends foundry.abstract.TypeDataModel {
key: new StringField(),
notiz: new StringField(),
})),
+ erschoepfung: new SchemaField({ // only with DSA_4-1.optional_erschoepfung
+ max: new NumberField({required: true, integer: true}),
+ aktuell: new NumberField({required: true, integer: true}),
+ }),
wunden: new SchemaField({
aktuell: new NumberField({required: true, integer: true}), // only with DSA_4-1.optional_trefferzonen = false
max: new NumberField({required: true, integer: true}), // only with DSA_4-1.optional_trefferzonen = false
diff --git a/src/module/dialog/combatAction.mjs b/src/module/dialog/combatAction.mjs
index 87d9c7f4..05eaae06 100644
--- a/src/module/dialog/combatAction.mjs
+++ b/src/module/dialog/combatAction.mjs
@@ -50,12 +50,12 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
*/
_actor = null
- constructor(actor) {
+ constructor(actor, data) {
super();
this._actor = actor
this._targetId = null
- this._skillId = null
- this._weaponId = null
+ this._skillId = data.skill ? data.skill : null
+ this._weaponId = data.weapon ? data.weapon : null
this._defenseManeuverId = null
this._actionManager = new ActionManager(this._actor)
CombatActionDialog._instance = this
@@ -126,7 +126,7 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
/** @type Cooldown */
const newCooldown = {
start: maneuver.cooldown({weapon, skill, target, mod: this._mod}),
- current: maneuver.cooldown({weapon, skill, target, mod: this._mod}),
+ current: 0,
data: {
cssClass: "Kampf",
weapon: this._weaponId,
@@ -288,9 +288,9 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
const context = await super._prepareContext(options)
context.actor = this._actor
- context.distanceUnit = game.scenes.current.grid.units
+ context.distanceUnit = game.scenes.current?.grid.units
- if (this._actor.getActiveTokens()[0]?.id) {
+ if (context.distanceUnit && this._actor.getActiveTokens()[0]?.id) {
context.tokenDistances = this.#evaluateDistances()
context.weapons = this.#evaluateWeapons()
@@ -307,7 +307,28 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
// TODO get W/M of weapon NOW
- context.ready = this._targetId && this._weaponId && this._skillId && this._defenseManeuverId
+ if (this._targetNumber >= 0 && this._targetId && this._weaponId && this._skillId && maneuver) {
+ context.ready = true
+ } else {
+ context.notReadyReason = `${game.i18n.format("COMBAT_DIALOG.notReadyReason.title")}
`
+ if (!this._targetId) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.noTarget")} `
+ }
+ if (!this._weaponId) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.noWeapon")} `
+ }
+ if (!this._skillId) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.noSkill")} `
+ }
+ if (!maneuver) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.noManeuver")} `
+ }
+ if (!this._targetNumber < 0) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.impossible")} `
+ }
+ context.notReadyReason += " "
+ context.ready = false
+ }
return context
} else {
ui.notifications.error(`Feature funktioniert nur wenn der Akteur ein Token auf der aktuellen Szene hat`);
@@ -335,12 +356,10 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
target.textContent = `(${result})`
targetDescription.textContent = this._modDescription
- if (result <= 0) {
- context.ready = false
+ if (result <= 0 || !context.ready) {
this.element.querySelector(".actions button").classList.remove("ready")
this.element.querySelector(".actions button").setAttribute("disabled", true)
} else {
- context.ready = true
this.element.querySelector(".actions button").classList.add("ready")
this.element.querySelector(".actions button").removeAttribute("disabled")
}
diff --git a/src/module/dialog/defenseAction.mjs b/src/module/dialog/defenseAction.mjs
index 6d4db78e..5e136d90 100644
--- a/src/module/dialog/defenseAction.mjs
+++ b/src/module/dialog/defenseAction.mjs
@@ -49,16 +49,16 @@ export class DefenseActionDialog extends HandlebarsApplicationMixin(ApplicationV
*/
_actor = null
- constructor(actor, attackData) {
+ constructor(actor, data, attackData) {
super();
- this._attackData = attackData ?? {
+ /*this._attackData = attackData ?? {
modToDefense: 0,
attacker: null,
weapon: null, // is important to note as weapons like Chain Weapons or Flails can ignore Shields
- }
+ }*/
this._actor = actor
- this._skillId = null
- this._weaponId = null
+ this._skillId = data.skill ? data.skill : null
+ this._weaponId = data.weapon ? data.weapon : null
this._defenseManeuverId = null
this._actionManager = new ActionManager(this._actor)
//if (this._actor) {
@@ -254,7 +254,26 @@ export class DefenseActionDialog extends HandlebarsApplicationMixin(ApplicationV
// TODO get W/M of weapon NOW
- context.ready = this._targetId && this._weaponId && this._skillId && this._defenseManeuverId
+ if (this._weaponId && this._skillId && this._defenseManeuverId) {
+ context.ready = true
+ } else {
+ context.notReadyReason = `${game.i18n.format("COMBAT_DIALOG.notReadyReason.title")} `
+ if (!this._weaponId) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.noWeapon")} `
+ }
+ if (!this._skillId) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.noSkill")} `
+ }
+ if (!maneuver) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.noManeuver")} `
+ }
+ if (!this._targetNumber < 0) {
+ context.notReadyReason += `${game.i18n.format("COMBAT_DIALOG.notReadyReason.impossible")} `
+ }
+ context.notReadyReason += " "
+ context.ready = false
+ }
+
return context
} else {
ui.notifications.error(`Feature funktioniert nur wenn der Akteur ein Token auf der aktuellen Szene hat`);
@@ -282,12 +301,10 @@ export class DefenseActionDialog extends HandlebarsApplicationMixin(ApplicationV
target.textContent = `(${result})`
targetDescription.textContent = this._modDescription
- if (result <= 0) {
- context.ready = false
+ if (result <= 0 || !context.ready) {
this.element.querySelector(".actions button").classList.remove("ready")
this.element.querySelector(".actions button").setAttribute("disabled", true)
} else {
- context.ready = true
this.element.querySelector(".actions button").classList.add("ready")
this.element.querySelector(".actions button").removeAttribute("disabled")
}
diff --git a/src/module/dialog/itemBrowserDialog.mjs b/src/module/dialog/itemBrowserDialog.mjs
new file mode 100644
index 00000000..21acf80c
--- /dev/null
+++ b/src/module/dialog/itemBrowserDialog.mjs
@@ -0,0 +1,243 @@
+import {Equipment} from "../documents/equipment.mjs";
+
+const {
+ ApplicationV2,
+ HandlebarsApplicationMixin
+} = foundry.applications.api
+
+export class ItemBrowserDialog extends HandlebarsApplicationMixin(ApplicationV2) {
+
+ static DEFAULT_OPTIONS = {
+ classes: ['dsa41', 'dialog', 'item-browser'],
+ tag: "form",
+ form: {
+ submitOnChange: true,
+ closeOnSubmit: false,
+ handler: ItemBrowserDialog.#onSubmitForm
+ },
+ position: {
+ width: 640,
+ height: 480
+ },
+ window: {
+ resizable: true,
+ title: "Gegenstände Browser"
+ },
+ actions: {
+ select: ItemBrowserDialog.#selectItem,
+ buy: ItemBrowserDialog.#buyItem
+ }
+ }
+
+ static PARTS = {
+ form: {
+ template: 'systems/DSA_4-1/templates/dialog/item-browser-dialog.hbs',
+ }
+ }
+
+ /**
+ * @type {Actor}
+ * @private
+ */
+ _actor = null
+ /**
+ *
+ * @type {[Equipment]}
+ * @private
+ */
+ _items = []
+ _selectedItem = null
+ filter_price_lower = 0
+ filter_price_upper = 0
+ filter_weight_lower = 0
+ filter_weight_upper = 0
+ filter_name = ""
+ filter_category = ""
+
+ constructor(actor) {
+ super();
+ this._actor = actor
+ this._items = []
+ this._selectedItem = null
+ }
+
+ static async #onSubmitForm(event, form, formData) {
+ event.preventDefault()
+ this.filter_price_lower = formData.object.filter_price_lower
+ this.filter_price_upper = formData.object.filter_price_upper
+ this.filter_weight_lower = formData.object.filter_weight_lower
+ this.filter_weight_upper = formData.object.filter_weight_upper
+ this.filter_name = formData.object.filter_name
+ this.filter_category = formData.object.filter_category
+
+ this.render({parts: ["form"]})
+ }
+
+ static async #selectItem(event, target) {
+ const {itemId} = target.dataset
+ const selectedItem = this._items.find(item => item.uuid === itemId)
+
+ this._items?.forEach((item) => {
+ item.selected = item.uuid === itemId
+ })
+
+ if (selectedItem) {
+ this._selectedItem = selectedItem
+ }
+ this.render({parts: ["form"]})
+ }
+
+ static async #buyItem(event, target) {
+ if (this._actor && this._selectedItem) {
+ const canBuy = await this._actor.reduceWealth(this._selectedItem.price)
+ if (canBuy) {
+ const document = await foundry.utils.fromUuid(this._selectedItem.uuid)
+ if (document) {
+ await this._actor.createEmbeddedDocuments("Item", [document])
+ ui.notifications.info(this._selectedItem.name + " wurde von " + this._actor.name + " gekauft")
+ }
+ } else {
+ ui.notifications.error(this._selectedItem.name + " ist zu teuer für " + this._actor.name)
+ }
+
+
+ }
+ }
+
+ _canDragDrop(event, options) {
+ return game.user.isGM
+ }
+
+ _canDrag(event, options) {
+ return true
+ }
+
+ /**
+ * An event that occurs when a drag workflow begins for a draggable item on the sheet.
+ * @param {DragEvent} event The initiating drag start event
+ * @returns {Promise}
+ * @protected
+ */
+ async _onDragStart(event) {
+ const target = event.currentTarget;
+ let dragData;
+
+ if (target.dataset.itemId) {
+ dragData = {
+ type: "Item",
+ uuid: target.dataset.itemId
+ }
+ }
+
+ // Set data transfer
+ if (!dragData) return;
+ event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
+ }
+
+ async _prepareContext(options) {
+ const context = await super._prepareContext(options)
+ context.categories = {
+ "": "",
+ "Gegenstand": "Gegenstand",
+ "Nahkampfwaffe": "Nahkampfwaffe",
+ "Fernkampfwaffe": "Fernkampfwaffe",
+ "Munition": "Munition",
+ "Währung": "Währung"
+ }
+ context.filterName = this.filter_name
+ context.filterCategory = this.filter_category
+ context.filter_price_lower = this.filter_price_lower ?? this._minPrice
+ context.filter_price_upper = this.filter_price_upper ?? this._maxPrice
+ context.filter_weight_lower = this.filter_weight_lower ?? this._minWeight
+ context.filter_weight_upper = this.filter_weight_upper ?? this._maxWeight
+ context.price_lower = this._minPrice
+ context.price_upper = this._maxPrice
+ context.weight_lower = this._minWeight
+ context.weight_upper = this._maxWeight
+ context.hasSelectedItem = this._selectedItem != null
+
+ context.items = this._items
+ ?.filter(p => p.name.toLowerCase().indexOf(context.filterName.toLowerCase()) !== -1 || context.filterName === "")
+ ?.filter(p => p.category.indexOf(context.filterCategory) !== -1 || context.filterCategory === "")
+ ?.filter(p => Number(context.filter_price_lower) <= p.price && p.price <= Number(context.filter_price_upper))
+ ?.filter(p => Number(context.filter_weight_lower) <= p.weight && p.weight <= Number(context.filter_weight_upper))
+
+
+
+ return context
+ }
+
+ #updateProgress(compendiumName, current, max) {
+ if (compendiumName && current && max) {
+ this.element.querySelector('.progress').style.display = 'block';
+ this.element.querySelector('.progress .fill').style.width = (current / max * 100) + "%";
+ this.element.querySelector('.progress .text').textContent = game.i18n.format("ITEM_BROWSER.progress", {
+ compendium: compendiumName,
+ current: current,
+ max: max
+ })
+
+ } else {
+ this.element.querySelector('.progress').style.display = 'none';
+ }
+ }
+
+ async _onRender(context, options) {
+
+ if (this._items.length === 0) {
+ const compendia = [
+ game.packs.get('DSA_4-1.Armor'),
+ game.packs.get('DSA_4-1.Weapons'),
+ game.packs.get('DSA_4-1.Ammunition'),
+ game.packs.get('DSA_4-1.Items')
+ ]
+
+ let totalEntries = compendia.reduce((p, c) => p + c.index.size, 0)
+ let parsedEntries = 0
+ let currentCompendiumName = ""
+
+ for (const c of compendia) {
+ const it = await c.getDocuments()
+ currentCompendiumName = c.metadata.label
+ it.forEach((item) => {
+ const uuid = item.uuid
+ const e = new Equipment(item)
+ this._items.push({
+ img: item.img,
+ uuid,
+ type: item.type,
+ name: item.name,
+ price: e.system.price,
+ weight: e.system.weight,
+ category: e.system.category.join(", "),
+ selected: false,
+ })
+
+ parsedEntries += 1
+ this.#updateProgress(currentCompendiumName, parsedEntries, totalEntries)
+ })
+ }
+ this._minPrice = Math.min(...this._items.map(item => item.price))
+ this._maxPrice = Math.max(...this._items.map(item => item.price))
+
+ this._minWeight = Math.min(...this._items.map(item => item.weight))
+ this._maxWeight = Math.max(...this._items.map(item => item.weight))
+
+
+ this.#updateProgress()
+ this.render({parts: ["form"]})
+ }
+
+
+ new foundry.applications.ux.DragDrop.implementation({
+ dropSelector: ".window-content",
+ dragSelector: ".item",
+ permissions: {
+ drag: this._canDrag.bind(this)
+ },
+ callbacks: {
+ dragstart: this._onDragStart.bind(this),
+ }
+ }).bind(this.element)
+ }
+}
\ No newline at end of file
diff --git a/src/module/dialog/liturgyDialog.mjs b/src/module/dialog/liturgyDialog.mjs
index 7d7764d6..23fea809 100644
--- a/src/module/dialog/liturgyDialog.mjs
+++ b/src/module/dialog/liturgyDialog.mjs
@@ -163,7 +163,7 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
}
cooldowns.push({
start: castingTime,
- current: castingTime,
+ current: 0,
data: {
cssClass: "Karmal",
title: this._liturgy.name,
diff --git a/src/module/dialog/restingDialog.mjs b/src/module/dialog/restingDialog.mjs
index 01da6bd9..7dcc00dd 100644
--- a/src/module/dialog/restingDialog.mjs
+++ b/src/module/dialog/restingDialog.mjs
@@ -99,6 +99,7 @@ export class RestingDialog extends HandlebarsApplicationMixin(ApplicationV2) {
lepMod: [-1, -2, -3, -4, -5],
display: "range",
noLabel: "Gutes Wetter",
+ nestingLevel: 1,
labels: [
"Schlechtes Wetter I",
"Schlechtes Wetter II",
@@ -114,6 +115,7 @@ export class RestingDialog extends HandlebarsApplicationMixin(ApplicationV2) {
aspMod: -1,
lepMod: -1,
display: "boolean",
+ nestingLevel: 1,
group: "bad_camp",
active: false,
value: "on"
@@ -220,6 +222,14 @@ export class RestingDialog extends HandlebarsApplicationMixin(ApplicationV2) {
const elementInMod = this.element.querySelector('output[name="inMod"]')
const elementWoundMod = this.element.querySelector('output[name="woundMod"]')
+ if (this.restingType === this.#type.DRAUßEN) {
+ this.element.querySelector('input[name="bad_weather"]').removeAttribute('disabled')
+ this.element.querySelector('input[name="bad_camp"]').removeAttribute('disabled')
+ } else {
+ this.element.querySelector('input[name="bad_weather"]').setAttribute('disabled', 'disabled')
+ this.element.querySelector('input[name="bad_camp"]').setAttribute('disabled', 'disabled')
+ }
+
const context = this.#updateData()
elementLepMod.value = context.lepModDisplay
elementKoMod.value = context.koRollDisplay
@@ -334,8 +344,6 @@ export class RestingDialog extends HandlebarsApplicationMixin(ApplicationV2) {
context.inRollDisplay = `1w20+${this.regInMod}`
}
- console.log(this, context)
-
return context
}
diff --git a/src/module/documents/character.mjs b/src/module/documents/character.mjs
index f158a631..bf116fee 100644
--- a/src/module/documents/character.mjs
+++ b/src/module/documents/character.mjs
@@ -105,6 +105,19 @@ export class Character extends Actor {
systemData.ausweichen.basis = systemData.pa.basis
systemData.ausweichen.aktuell = systemData.ausweichen.basis
+ systemData.ueberanstrengung = 0
+
+ if (game.settings.get("DSA_4-1", "optional_erschoepfung")) {
+
+ systemData.erschoepfung = {
+ aktuell: systemData.erschoepfung.aktuell ?? 0,
+ max: ko
+ }
+ if (systemData.erschoepfung.aktuell > systemData.erschoepfung.max) {
+ systemData.ueberanstrengung = systemData.erschoepfung.aktuell - systemData.erschoepfung.max
+ }
+ }
+
if (game.settings.get("DSA_4-1", "optional_ruestungzonen")) {
systemData.rs = {
@@ -119,11 +132,11 @@ export class Character extends Actor {
} else {
systemData.rs = 0; // only with DSA_4-1.optional_trefferzonen = false
}
- systemData.be = 0;
+ systemData.be = 0 + systemData.ueberanstrengung;
// half KO is the maximum a character can sustain wounds before collapsing
- systemData.wunden.max = ko / 2;
+ systemData.wunden.max = Math.round(ko / 2);
if (game.settings.get("DSA_4-1", "optional_trefferzonen")) {
systemData.wunden.kopf = 0
systemData.wunden.brust = 0
diff --git a/src/module/settings/global-settings.mjs b/src/module/settings/global-settings.mjs
index 50d919a8..65777bb8 100644
--- a/src/module/settings/global-settings.mjs
+++ b/src/module/settings/global-settings.mjs
@@ -36,6 +36,18 @@ function initGlobalSettings(settings) {
requiresReload: true
})
+ settings.register('DSA_4-1', 'optional_erschoepfung', {
+ name: "Optional: Erschöpfung",
+ hint: "Aktiviert Regeln für das Spiel mit Erschöpfung und Überanstregung",
+ scope: "world",
+ config: true,
+ type: Boolean,
+ default: false,
+ onChange: value => {
+ },
+ requiresReload: true
+ })
+
settings.register('DSA_4-1', 'optional_distanzklassen', {
name: "Optional: Distanzklassen",
hint: "Aktiviert Regeln für das Spiel mit Distanzklassen",
diff --git a/src/module/setup/config.mjs b/src/module/setup/config.mjs
index 53a2dfd8..b603f42e 100644
--- a/src/module/setup/config.mjs
+++ b/src/module/setup/config.mjs
@@ -20,6 +20,7 @@ import {Talent} from "../data/talent.mjs";
import {Character} from "../documents/character.mjs";
import {currency} from "../handlebar-helpers/currency.mjs";
import {DeityDataModel} from "../data/deity.mjs";
+import {ItemBrowserDialog} from "../dialog/itemBrowserDialog.mjs";
function initGlobalAccess() {
@@ -30,6 +31,7 @@ function initGlobalAccess() {
Wunde,
RestingDialog,
BattleDialog,
+ ItemBrowserDialog,
Talent,
displayCurrency: currency
}
@@ -71,7 +73,48 @@ function initCombat(config) {
}
}
+function initSocketLib() {
+
+
+ Hooks.on("socketlib.ready", () => {
+ console.log("Socketlib is registering")
+ let socket = socketlib.registerSystem("DSA_4-1")
+ socket.register("removeFromLootTable", removeFromLootTable)
+ socket.register("buyFromLootTable", buyFromLootTable)
+ if (!game.DSA41) {
+ game.DSA41 = {}
+ }
+ game.DSA41.socket = socket
+ })
+
+
+ async function removeFromLootTable(actorId, itemId) {
+ if (actorId && game.actors.get(actorId)) {
+ const actor = game.actors.get(actorId)
+
+ return await actor.deleteEmbeddedDocuments('Item', [itemId])
+ }
+ }
+
+ async function buyFromLootTable(actorId, itemId) {
+ if (actorId && game.actors.get(actorId)) {
+ const actor = game.actors.get(actorId)
+ const item = actor.items.find(p => p.id === itemId)
+ if (item.system.quantity != -1) { // -1 means infinite
+ if (item.system.quantity > 1) {
+ item.update({'system.quantity': item.system.quantity - 1})
+ } else {
+ actor.deleteEmbeddedDocuments('Item', [item._id]) // delete when the quantity is equal to 0
+ }
+ }
+ return true
+ }
+ }
+
+}
+
export {
+ initSocketLib,
initGlobalAccess,
initDocumentClasses,
initDataModels,
diff --git a/src/module/setup/partials.mjs b/src/module/setup/partials.mjs
index 9ff711c4..ce3115dd 100644
--- a/src/module/setup/partials.mjs
+++ b/src/module/setup/partials.mjs
@@ -4,6 +4,7 @@ function loadPartials(hbs) {
hbs.loadTemplates([
// ui partials.
'systems/DSA_4-1/templates/ui/partial-rollable-button.hbs',
+ 'systems/DSA_4-1/templates/ui/partial-cooldown.hbs',
'systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs',
'systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs',
'systems/DSA_4-1/templates/ui/partial-attribute-button.hbs',
@@ -14,7 +15,13 @@ function loadPartials(hbs) {
'systems/DSA_4-1/templates/ui/partial-action-button.hbs',
'systems/DSA_4-1/templates/ui/partial-equipment-button.hbs',
'systems/DSA_4-1/templates/ui/partial-array-editor.hbs',
- 'systems/DSA_4-1/templates/dialog/liturgy-dialog.hbs'
+ 'systems/DSA_4-1/templates/actor/character/tab-set.hbs',
+ 'systems/DSA_4-1/templates/dialog/liturgy-dialog.hbs',
+ 'systems/DSA_4-1/templates/ui/partial-mini-rollable-button.hbs',
+ 'systems/DSA_4-1/templates/ui/partial-mini-rollable-liturgy-button.hbs',
+ 'systems/DSA_4-1/templates/ui/partial-mini-rollable-weaponskill-button.hbs',
+ 'systems/DSA_4-1/templates/ui/partial-mini-rollable-language-button.hbs',
+ 'systems/DSA_4-1/templates/ui/partial-mini-rollable-spell-button.hbs',
]).then(resolve);
})
diff --git a/src/module/setup/sheets.mjs b/src/module/setup/sheets.mjs
index 51fe9bec..781333f5 100644
--- a/src/module/setup/sheets.mjs
+++ b/src/module/setup/sheets.mjs
@@ -4,7 +4,7 @@ import {GroupSheet} from "../sheets/groupSheet.mjs";
import {SkillSheet} from "../sheets/skillSheet.mjs";
import {SpellSheet} from "../sheets/spellSheet.mjs";
import {AdvantageSheet} from "../sheets/advantageSheet.mjs";
-import {EquipmentSheet} from "../sheets/equipmentSheet.mjs";
+import EquipmentSheet from "../sheets/equipmentSheet.mjs";
import {LiturgySheet} from "../sheets/liturgySheet.mjs";
import {SpecialAbilitySheet} from "../sheets/specialAbilitySheet.mjs";
import {ActiveEffectSheet} from "../sheets/activeEffectSheet.mjs";
diff --git a/src/module/sheets/character-standalone/advsf.mjs b/src/module/sheets/character-standalone/advsf.mjs
new file mode 100644
index 00000000..11777bbf
--- /dev/null
+++ b/src/module/sheets/character-standalone/advsf.mjs
@@ -0,0 +1,118 @@
+const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
+const {ActorSheetV2} = foundry.applications.sheets
+
+export class StandaloneADVSF extends HandlebarsApplicationMixin(ActorSheetV2) {
+
+ /** @inheritDoc */
+ static DEFAULT_OPTIONS = {
+ position: {width: 520, height: 480},
+ classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'advsf'],
+ tag: 'form',
+ actions: {
+ rollFlaw: StandaloneADVSF.#rollFlaw,
+ openEmbeddedDocument: StandaloneADVSF.#openEmbeddedDocument,
+
+ }
+ }
+
+ /** @inheritDoc */
+ static PARTS = {
+ form: {
+ template: `systems/DSA_4-1/templates/actor/character/standalone/advsf.hbs`
+ }
+ }
+
+ _actor = null
+
+ constructor(actor) {
+ super(actor)
+ this._actor = actor
+ this.render(true)
+ this.options.window.title = `${this.document.name} Vor und Nachteile`
+ }
+
+ static async #rollFlaw(event, target) {
+ this._actor?.sheet.options.actions.rollFlaw.bind(this)(event, target)
+ }
+
+ static async #openEmbeddedDocument(event, target) {
+ this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target)
+ }
+
+ _configureRenderOptions(options) {
+ super._configureRenderOptions(options)
+
+ options.window.title = `${this.document.name}: Vor und Nachteile`
+
+ return options
+ }
+
+ async _prepareContext(context, options, object) {
+ if (this._actor) {
+ const actorData = this.document
+ context.system = actorData.system
+ context.flags = actorData.flags
+ context.derived = actorData.system
+ context.originalName = actorData.name
+ context.name = context.derived.name ?? actorData.name
+ context.effects = actorData.effects ?? []
+ context.advantages = []
+ context.flaws = []
+
+ actorData.itemTypes.Advantage.forEach((item) => {
+ if (!item.system.schlechteEigenschaft) {
+ context.advantages.push({
+ id: item._id,
+ name: item.name,
+ value: item.system.value,
+ options: item.system.auswahl,
+ description: item.system.description,
+ isAdvantage: !item.system.nachteil,
+ isDisadvantage: item.system.nachteil,
+ isBadAttribute: item.system.schlechteEigenschaft,
+ fav: item.getFlag("DSA_4-1", "favourite")
+ })
+ } else {
+ context.flaws.push({
+ id: item._id,
+ name: item.name,
+ value: item.system.value,
+ options: item.system.auswahl,
+ description: item.system.description,
+ isAdvantage: !item.system.nachteil,
+ isDisadvantage: item.system.nachteil,
+ isBadAttribute: item.system.schlechteEigenschaft,
+ fav: item.getFlag("DSA_4-1", "favourite")
+ })
+ }
+ }
+ )
+
+ context.specialAbilities = []
+ actorData.itemTypes.SpecialAbility.forEach((item) => {
+ context.specialAbilities.push({
+ id: item._id,
+ name: item.system.value ? item.system.value : item.name,
+ fav: item.getFlag("DSA_4-1", "favourite")
+ });
+ }
+ );
+
+ return context
+ }
+ }
+
+ _onRender(context, options) {
+ if (this._actor) {
+ new foundry.applications.ux.DragDrop.implementation({
+ dropSelector: ".advantages, .special-abilities",
+ permissions: {
+ drop: this._actor.sheet._canDragDrop.bind(this._actor.sheet)
+ },
+ callbacks: {
+ drop: this._actor.sheet._onDrop.bind(this._actor.sheet),
+ }
+ }).bind(this.element);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/module/sheets/character-standalone/bagpack.mjs b/src/module/sheets/character-standalone/bagpack.mjs
new file mode 100644
index 00000000..24a52224
--- /dev/null
+++ b/src/module/sheets/character-standalone/bagpack.mjs
@@ -0,0 +1,98 @@
+const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
+const {ActorSheetV2} = foundry.applications.sheets
+
+export class Bagpack extends HandlebarsApplicationMixin(ActorSheetV2) {
+
+ /** @inheritDoc */
+ static DEFAULT_OPTIONS = {
+ position: {width: 520, height: 480},
+ classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'bagpack'],
+ tag: 'form',
+ actions: {
+ openItemBrowser: Bagpack.#openItemBrowser,
+ newItem: Bagpack.#newItem,
+ openEmbeddedDocument: Bagpack.#openEmbeddedDocument,
+
+ }
+ }
+
+ /** @inheritDoc */
+ static PARTS = {
+ form: {
+ template: `systems/DSA_4-1/templates/actor/character/standalone/bagpack.hbs`
+ }
+ }
+
+ _actor = null
+
+ constructor(actor) {
+ super(actor)
+ this._actor = actor
+ this.render(true)
+ }
+
+ static async #openItemBrowser(event, target) {
+ this._actor?.sheet.options.actions.openItemBrowser().bind(this)(event, target)
+ }
+
+ static async #newItem(event, target) {
+ this._actor?.sheet.options.actions.newItem.bind(this)(event, target)
+ }
+
+ static async #openEmbeddedDocument(event, target) {
+ this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target)
+ }
+
+ _configureRenderOptions(options) {
+ super._configureRenderOptions(options)
+
+ options.window.title = `${this.document.name}: Inventar`
+
+ return options
+ }
+
+ async _prepareContext(context, options, object) {
+ const actorData = this.document
+ context.system = actorData.system
+ context.flags = actorData.flags
+
+ context.equipments = []
+ context.carryingweight = 0
+ actorData.itemTypes["Equipment"].sort((a, b) => a.sort - b.sort).forEach((item, index) => {
+
+ // worn items are halved weight
+
+ let effectiveWeight = item.system.weight ?? 0
+ if (this.document.isWorn(item._id)) {
+ effectiveWeight = item.system.weight ? item.system.weight / 2 : 0
+ }
+
+ context.equipments.push({
+ index: index,
+ id: item._id,
+ quantity: item.system.quantity,
+ name: item.name,
+ icon: item.img ?? "",
+ weight: item.system.weight,
+ worn: this.document.isWorn(item._id)
+ })
+ context.carryingweight += item.system.quantity * effectiveWeight;
+
+ })
+ context.maxcarryingcapacity = actorData.system.attribute.kk.aktuell
+ context.carryingpercentage = Math.min((context.carryingweight / context.maxcarryingcapacity) * 100, 100);
+
+ context.wealth = 0
+
+ actorData.itemTypes["Equipment"].forEach(coin => {
+ if (coin.system.category.indexOf("Währung") !== -1) {
+ context.wealth += (coin.system.quantity * coin.system.currencyDenominator)
+ }
+ })
+
+ return context
+ }
+
+ _onRender(context, options) {
+ }
+}
\ No newline at end of file
diff --git a/src/module/sheets/character-standalone/health.mjs b/src/module/sheets/character-standalone/health.mjs
new file mode 100644
index 00000000..6d4157df
--- /dev/null
+++ b/src/module/sheets/character-standalone/health.mjs
@@ -0,0 +1,111 @@
+const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
+const {ActorSheetV2} = foundry.applications.sheets
+
+export class StandaloneHealth extends HandlebarsApplicationMixin(ActorSheetV2) {
+
+ /** @inheritDoc */
+ static DEFAULT_OPTIONS = {
+ position: {width: 520, height: 716},
+ classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'health'],
+ tag: 'form',
+ actions: {
+ openEmbeddedDocument: StandaloneHealth.#openEmbeddedDocument,
+ setWounds: StandaloneHealth.#setWounds,
+
+ }
+ }
+
+ /** @inheritDoc */
+ static PARTS = {
+ form: {
+ template: `systems/DSA_4-1/templates/actor/character/standalone/health.hbs`
+ }
+ }
+
+ _actor = null
+
+ constructor(actor) {
+ super(actor)
+ this._actor = actor
+ this.render(true)
+ }
+
+ static async #openEmbeddedDocument(event, target) {
+ this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target)
+ }
+
+ static async #setWounds(event, target) {
+ this._actor?.sheet.options.actions.setWounds.bind(this)(event, target)
+ }
+
+ _configureRenderOptions(options) {
+ super._configureRenderOptions(options)
+
+ options.window.title = `${this.document.name}: Gesundheit`
+
+ return options
+ }
+
+ async _prepareContext(context, options, object) {
+ const actorData = this.document
+ context.system = actorData.system
+ context.flags = actorData.flags
+ context.derived = this.document.system
+ context.originalName = actorData.name
+ context.name = context.derived.name ?? actorData.name
+ context.effects = actorData.effects ?? []
+
+ const findEquipmentOnSlot = (slot, setNumber, object) => {
+ return object.items.get(object.system.heldenausruestung[setNumber]?.[slot])
+ }
+
+ context.inidice = actorData.system.ini.wuerfel
+ context.inivalue = actorData.system.ini.aktuell
+ context.inimod = actorData.system.ini.mod
+
+ context.zonenruestung = game.settings.get("DSA_4-1", "optional_ruestungzonen")
+ context.trefferzonen = game.settings.get("DSA_4-1", "optional_trefferzonen")
+ context.ausdauer = game.settings.get("DSA_4-1", "optional_ausdauer")
+ context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice')
+
+ context.aupper = Math.min((actorData.system.aup.aktuell / actorData.system.aup.max) * 100, 100)
+ context.lepper = Math.min((actorData.system.lep.aktuell / actorData.system.lep.max) * 100, 100)
+ context.keper = Math.min((actorData.system.kap.aktuell / actorData.system.kap.max) * 100, 100)
+ context.aspper = Math.min((actorData.system.asp.aktuell / actorData.system.asp.max) * 100, 100)
+
+ context.lepcurrent = actorData.system.lep.aktuell ?? 0
+ context.aupcurrent = actorData.system.aup.aktuell ?? 0
+ context.aspcurrent = actorData.system.asp.aktuell ?? 0
+ context.kapcurrent = actorData.system.kap.aktuell ?? 0
+
+ context.maxWounds = actorData.system.wunden.max ?? 3
+ context.wounds = actorData.system.wunden.aktuell ?? 0
+ context.woundsFilled = []
+ for (let i = 1; i <= context.maxWounds; i++) {
+ context.woundsFilled[i] = i <= context.wounds
+ }
+
+ context.withErschoepfung = game.settings.get("DSA_4-1", "optional_erschoepfung")
+ context.ueberanstrengung = actorData.system.ueberanstrengung
+ context.erschoepfung = actorData.system.erschoepfung.aktuell
+ context.maxErschoepfung = actorData.system.erschoepfung.max
+
+ context.erschoepfungFilled = []
+ for (let i = 1; i <= context.maxErschoepfung; i++) {
+ context.erschoepfungFilled[i] = i <= context.erschoepfung
+ }
+
+
+ context.effects = []
+ for (let i = 0; i < actorData.appliedEffects.length; i++) {
+ const item = actorData.appliedEffects[i]
+ context.effects.push(item.name)
+ }
+
+ return context
+
+ }
+
+ _onRender(context, options) {
+ }
+}
\ No newline at end of file
diff --git a/src/module/sheets/character-standalone/liturgies.mjs b/src/module/sheets/character-standalone/liturgies.mjs
new file mode 100644
index 00000000..e88459df
--- /dev/null
+++ b/src/module/sheets/character-standalone/liturgies.mjs
@@ -0,0 +1,152 @@
+import {LiturgyData} from "../../data/miracle/liturgyData.mjs";
+
+const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
+const {ActorSheetV2} = foundry.applications.sheets
+
+export class StandaloneLiturgies extends HandlebarsApplicationMixin(ActorSheetV2) {
+
+ /** @inheritDoc */
+ static DEFAULT_OPTIONS = {
+ position: {width: 520, height: 480},
+ classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'liturgies'],
+ tag: 'form',
+ actions: {
+ openEmbeddedDocument: StandaloneLiturgies.#openEmbeddedDocument,
+ openLiturgyDialog: StandaloneLiturgies.#openLiturgyDialog,
+
+ }
+ }
+
+ /** @inheritDoc */
+ static PARTS = {
+ form: {
+ template: `systems/DSA_4-1/templates/actor/character/standalone/liturgies.hbs`
+ }
+ }
+
+ _actor = null
+
+ constructor(actor) {
+ super(actor)
+ this._actor = actor
+ this.render(true)
+ }
+
+ static async #openEmbeddedDocument(event, target) {
+ this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target)
+ }
+
+ static async #openLiturgyDialog(event, target) {
+ this._actor?.sheet.options.actions.openLiturgyDialog.bind(this)(event, target)
+ }
+
+ _configureRenderOptions(options) {
+ super._configureRenderOptions(options)
+
+ options.window.title = `${this.document.name}: Segnungen und Liturgien`
+
+ return options
+ }
+
+ async _prepareContext(context, options, object) {
+
+ const actorData = this.document
+ context.system = actorData.system
+ context.flags = actorData.flags
+ context.derived = this.document.system
+ context.originalName = actorData.name
+ context.name = context.derived.name ?? actorData.name
+
+ context.effects = actorData.effects ?? []
+ context.liturgies = [];
+ context.blessings = [];
+
+ actorData.itemTypes.Blessing.forEach((item, index) => {
+ context.blessings.push({
+ deity: item.system.gottheit,
+ value: item.system.wert
+ })
+ })
+ actorData.itemTypes.Liturgy.forEach((item, index) => {
+
+ context.blessings.forEach(({deity, value}) => {
+ let insertObject = context.liturgies.find(p => p.deity === deity);
+ if (!insertObject) {
+ insertObject = {
+ deity: deity,
+ lkp: value,
+ O: [],
+ I: [],
+ II: [],
+ III: [],
+ IV: [],
+ V: [],
+ VI: [],
+ VII: [],
+ VIII: [],
+ "NA": [],
+ countO: 1,
+ countI: 1,
+ countII: 1,
+ countIII: 1,
+ countIV: 1,
+ countV: 1,
+ countVI: 1,
+ countVII: 1,
+ countVIII: 1,
+ countNA: 0,
+ total: 3,
+
+ }
+ context.liturgies.push(insertObject);
+ }
+
+ // sort by rank
+ const rankData = LiturgyData.getRankOfLiturgy(item.system, deity)
+ if (rankData) {
+ console.log(rankData)
+ let {index, name, lkp, mod, costKaP} = rankData;
+
+ insertObject["count" + name] = insertObject["count" + name] + 1;
+
+ insertObject[name]?.push({
+ id: item._id,
+ name: item.name,
+ lkpReq: lkp,
+ lkpMod: mod,
+ costKaP,
+ fav: item.getFlag("DSA_4-1", "favourite"),
+ rank: index, // get effective liturgy rank based on deity
+ liturgiekenntnis: deity,
+ })
+ insertObject.total = insertObject.total + 2;
+
+ }
+ })
+ })
+
+
+ // clean up counter
+ Object.values(context.liturgies).forEach((litObject) => {
+
+ if (litObject.I.length === 0) litObject.countI = false;
+ if (litObject.II.length === 0) litObject.countII = false;
+ if (litObject.III.length === 0) litObject.countIII = false;
+ if (litObject.IV.length === 0) litObject.countIV = false;
+ if (litObject.V.length === 0) litObject.countV = false;
+ if (litObject.VI.length === 0) litObject.countVI = false;
+ if (litObject.VII.length === 0) litObject.countVII = false;
+ if (litObject.VIII.length === 0) litObject.countVIII = false;
+ if (litObject.NA.length === 0) litObject.countNA = false;
+
+
+ })
+
+ context.hasLiturgies = context.blessings.length > 0;
+
+ return context
+ }
+
+ _onRender(context, options) {
+ }
+}
\ No newline at end of file
diff --git a/src/module/sheets/character-standalone/skills.mjs b/src/module/sheets/character-standalone/skills.mjs
new file mode 100644
index 00000000..7d752bb6
--- /dev/null
+++ b/src/module/sheets/character-standalone/skills.mjs
@@ -0,0 +1,127 @@
+const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
+const {ActorSheetV2} = foundry.applications.sheets
+
+export class StandaloneSkills extends HandlebarsApplicationMixin(ActorSheetV2) {
+
+ /** @inheritDoc */
+ static DEFAULT_OPTIONS = {
+ position: {width: 520, height: 480},
+ classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'skills'],
+ tag: 'form',
+ actions: {
+ rollCombatSkill: StandaloneSkills.#rollCombatSkill,
+ rollSkill: StandaloneSkills.#rollSkill,
+ openEmbeddedDocument: StandaloneSkills.#openEmbeddedDocument,
+
+ }
+ }
+
+ /** @inheritDoc */
+ static PARTS = {
+ form: {
+ template: `systems/DSA_4-1/templates/actor/character/standalone/skills.hbs`
+ }
+ }
+
+ _actor = null
+
+ constructor(actor) {
+ super(actor)
+ this._actor = actor
+ this.render(true)
+ }
+
+ static async #rollCombatSkill(event, target) {
+ this._actor?.sheet.options.actions.rollCombatSkill.bind(this)(event, target)
+ }
+
+ static async #rollSkill(event, target) {
+ this._actor?.sheet.options.actions.rollSkill.bind(this)(event, target)
+ }
+
+ static async #openEmbeddedDocument(event, target) {
+ this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target)
+ }
+
+ _configureRenderOptions(options) {
+ super._configureRenderOptions(options)
+
+ options.window.title = `${this.document.name}: Talente`
+
+ return options
+ }
+
+ async _prepareContext(context, options, object) {
+ const actorData = this.document
+ context.system = actorData.system
+ context.flags = actorData.flags
+ context.derived = this.document.system
+ context.originalName = actorData.name
+ context.name = context.derived.name ?? actorData.name
+ context.effects = actorData.effects ?? []
+
+ const prepareEigenschaftRoll = (actorData, name) => {
+ if (name && name !== "*") {
+ return actorData.system.attribute[name.toLowerCase()].aktuell
+ } else {
+ return 0
+ }
+ }
+
+ context.skills = {};
+ context.flatSkills = [];
+
+ actorData.itemTypes.Skill.forEach((item, index) => {
+
+ const talentGruppe = item.system.gruppe;
+ const eigenschaften = Object.values(item.system.probe);
+ const werte = [
+ {name: eigenschaften[0], value: prepareEigenschaftRoll(actorData, eigenschaften[0])},
+ {name: eigenschaften[1], value: prepareEigenschaftRoll(actorData, eigenschaften[1])},
+ {name: eigenschaften[2], value: prepareEigenschaftRoll(actorData, eigenschaften[2])}
+ ]
+ if (context.skills[talentGruppe] == null) {
+ context.skills[talentGruppe] = [];
+ }
+ const obj = {
+ type: "talent",
+ gruppe: talentGruppe,
+ name: item.name.replace(/Sprachen kennen/g, "Sprache:").replace(/Lesen\/Schreiben/g, "Schrift: "),
+ taw: "" + item.system.taw,
+ tawPath: `system.items.${index}.taw`,
+ werte,
+ rollEigenschaft1: werte[0].value,
+ rollEigenschaft2: werte[1].value,
+ rollEigenschaft3: werte[2].value,
+ eigenschaft1: werte[0].name,
+ eigenschaft2: werte[1].name,
+ eigenschaft3: werte[2].name,
+ probe: `(${eigenschaften.join("/")})`,
+ id: item._id,
+ at: item.system.at,
+ pa: item.system.pa,
+ komplexität: item.system.komplexität,
+ fav: item.getFlag("DSA_4-1", "favourite")
+ };
+
+ if (talentGruppe === "Kampf") {
+
+ if (item.system.pa != null) { // has no parry value so it must be ranged talent (TODO: but it isnt as there can be combatstatistics which has no pa value assigned to)
+ obj.at = item.system.at + context.derived.at.aktuell
+ obj.pa = item.system.pa + context.derived.pa.aktuell
+ } else {
+ obj.at = item.system.at + context.derived.fk.aktuell
+ }
+ }
+
+ context.skills[talentGruppe].push(obj);
+ context.flatSkills.push(obj);
+ }
+ )
+
+ return context
+ }
+
+ _onRender(context, options) {
+ }
+}
\ No newline at end of file
diff --git a/src/module/sheets/character-standalone/spells.mjs b/src/module/sheets/character-standalone/spells.mjs
new file mode 100644
index 00000000..57b822e8
--- /dev/null
+++ b/src/module/sheets/character-standalone/spells.mjs
@@ -0,0 +1,98 @@
+const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
+const {ActorSheetV2} = foundry.applications.sheets
+
+export class StandaloneSpells extends HandlebarsApplicationMixin(ActorSheetV2) {
+
+ /** @inheritDoc */
+ static DEFAULT_OPTIONS = {
+ position: {width: 520, height: 480},
+ classes: ['dsa41', 'sheet', 'actor', 'character', 'standalone', 'spells'],
+ tag: 'form',
+ actions: {
+ openEmbeddedDocument: StandaloneSpells.#openEmbeddedDocument,
+
+ }
+ }
+
+ /** @inheritDoc */
+ static PARTS = {
+ form: {
+ template: `systems/DSA_4-1/templates/actor/character/standalone/spells.hbs`
+ }
+ }
+
+ _actor = null
+
+ constructor(actor) {
+ super(actor)
+ this._actor = actor
+ this.render(true)
+ }
+
+ static async #openEmbeddedDocument(event, target) {
+ this._actor?.sheet.options.actions.openEmbeddedDocument.bind(this)(event, target)
+ }
+
+ _configureRenderOptions(options) {
+ super._configureRenderOptions(options)
+
+ options.window.title = `${this.document.name}: Zauber und Rituale`
+
+ return options
+ }
+
+ async _prepareContext(context, options, object) {
+
+ const actorData = this.document
+ context.spells = []
+ context.system = actorData.system
+ context.flags = actorData.flags
+ context.derived = this.document.system
+ context.originalName = actorData.name
+ context.name = context.derived.name ?? actorData.name
+ context.effects = actorData.effects ?? []
+
+ const cleanUpMerkmal = (merkmale) => {
+ return merkmale.split(",").map((merkmal) => merkmal.trim())
+ }
+
+ const prepareEigenschaftRoll = (actorData, name) => {
+ if (name && name !== "*") {
+ return actorData.system.attribute[name.toLowerCase()].aktuell
+ } else {
+ return 0
+ }
+ }
+
+ actorData.itemTypes["Spell"].forEach((item, index) => {
+
+ const eigenschaften = item.system.probe;
+ const werte = [
+ {name: eigenschaften[0], value: prepareEigenschaftRoll(actorData, eigenschaften[0])},
+ {name: eigenschaften[1], value: prepareEigenschaftRoll(actorData, eigenschaften[1])},
+ {name: eigenschaften[2], value: prepareEigenschaftRoll(actorData, eigenschaften[2])}
+ ]
+ context.spells.push({
+ id: item._id,
+ name: item.name,
+ zfw: item.system.zfw,
+ hauszauber: item.system.hauszauber,
+ merkmal: cleanUpMerkmal(item.system.merkmal),
+ rollEigenschaft1: werte[0].value,
+ rollEigenschaft2: werte[1].value,
+ rollEigenschaft3: werte[2].value,
+ eigenschaft1: werte[0].name,
+ eigenschaft2: werte[1].name,
+ eigenschaft3: werte[2].name,
+ fav: item.getFlag("DSA_4-1", "favourite")
+ })
+
+ })
+ context.hasSpells = context.spells.length > 0
+
+ return context
+ }
+
+ _onRender(context, options) {
+ }
+}
\ No newline at end of file
diff --git a/src/module/sheets/character/advsf.mjs b/src/module/sheets/character/advsf.mjs
index f0074d84..2bd10a79 100644
--- a/src/module/sheets/character/advsf.mjs
+++ b/src/module/sheets/character/advsf.mjs
@@ -21,7 +21,8 @@ export default {
description: item.system.description,
isAdvantage: !item.system.nachteil,
isDisadvantage: item.system.nachteil,
- isBadAttribute: item.system.schlechteEigenschaft
+ isBadAttribute: item.system.schlechteEigenschaft,
+ fav: item.getFlag("DSA_4-1", "favourite")
})
} else {
context.flaws.push({
@@ -32,7 +33,8 @@ export default {
description: item.system.description,
isAdvantage: !item.system.nachteil,
isDisadvantage: item.system.nachteil,
- isBadAttribute: item.system.schlechteEigenschaft
+ isBadAttribute: item.system.schlechteEigenschaft,
+ fav: item.getFlag("DSA_4-1", "favourite")
})
}
}
@@ -43,6 +45,7 @@ export default {
context.specialAbilities.push({
id: item._id,
name: item.system.value ? item.system.value : item.name,
+ fav: item.getFlag("DSA_4-1", "favourite")
});
}
);
diff --git a/src/module/sheets/character/equipment.mjs b/src/module/sheets/character/equipment.mjs
index d38ac604..8c34b1c8 100644
--- a/src/module/sheets/character/equipment.mjs
+++ b/src/module/sheets/character/equipment.mjs
@@ -1,7 +1,7 @@
import {PlayerCharacterDataModel} from "../../data/character.mjs";
export default {
- _prepareContext: (context) => {
+ _prepareContext: (context, actor, thisObject) => {
const actorData = context.document
context.spells = []
@@ -53,7 +53,7 @@ export default {
context.sets.push({
tab: "set" + (setIndex + 1),
- name: romanNumerals[setIndex],
+ label: romanNumerals[setIndex],
index: setIndex,
slots: [
{
@@ -280,7 +280,7 @@ export default {
name: "Aus dem Inventar entfernen",
icon: ' ',
callback: (target) => {
- thisObject.document.deleteEmbeddedDocuments('Item', [target.dataset.itemId])
+ game.DSA41.socket.executeAsGM("removeFromLootTable", thisObject.document.id, target.dataset.itemId)
},
condition: (target) => {
const {itemId} = target.dataset
@@ -290,7 +290,7 @@ export default {
], {jQuery: false});
},
_getTabConfig: (group) => {
- group.tabs.push({id: "equipment", group: "sheet", label: "Ausrüstung"})
+ group?.tabs.push({id: "equipment", group: "sheet", label: "Ausrüstung"})
},
template: `systems/DSA_4-1/templates/actor/character/tab-equipment.hbs`
}
\ No newline at end of file
diff --git a/src/module/sheets/character/combat.mjs b/src/module/sheets/character/health.mjs
similarity index 52%
rename from src/module/sheets/character/combat.mjs
rename to src/module/sheets/character/health.mjs
index 10485d66..9c3de352 100644
--- a/src/module/sheets/character/combat.mjs
+++ b/src/module/sheets/character/health.mjs
@@ -1,5 +1,3 @@
-import {ActionManager} from "../actions/action-manager.mjs";
-
export default {
_prepareContext: async (context, object) => {
@@ -15,9 +13,6 @@ export default {
return object.items.get(object.system.heldenausruestung[setNumber]?.[slot])
}
- const am = new ActionManager(actorData)
- context.actions = am.evaluate().filter(action => action.type !== ActionManager.ATTACK)
-
context.inidice = actorData.system.ini.wuerfel
context.inivalue = actorData.system.ini.aktuell
context.inimod = actorData.system.ini.mod
@@ -26,9 +21,35 @@ export default {
context.lepper = Math.min((actorData.system.lep.aktuell / actorData.system.lep.max) * 100, 100)
context.keper = Math.min((actorData.system.kap.aktuell / actorData.system.kap.max) * 100, 100)
context.aspper = Math.min((actorData.system.asp.aktuell / actorData.system.asp.max) * 100, 100)
- context.lepcurrent = actorData.system.lep.aktuell ?? 0
+ context.lepcurrent = actorData.system.lep.aktuell ?? 0
context.aupcurrent = actorData.system.aup.aktuell ?? 0
+ context.aspcurrent = actorData.system.asp.aktuell ?? 0
+ context.kapcurrent = actorData.system.kap.aktuell ?? 0
+
+ context.maxWounds = actorData.system.wunden.max ?? 3
+ context.wounds = actorData.system.wunden.aktuell ?? 0
+ context.woundsFilled = []
+ for (let i = 1; i <= context.maxWounds; i++) {
+ context.woundsFilled[i] = i <= context.wounds
+ }
+
+ context.withErschoepfung = game.settings.get("DSA_4-1", "optional_erschoepfung")
+ context.ueberanstrengung = actorData.system.ueberanstrengung
+ context.erschoepfung = actorData.system.erschoepfung.aktuell
+ context.maxErschoepfung = actorData.system.erschoepfung.max
+
+ context.erschoepfungFilled = []
+ for (let i = 1; i <= context.maxErschoepfung; i++) {
+ context.erschoepfungFilled[i] = i <= context.erschoepfung
+ }
+
+
+ context.effects = []
+ for (let i = 0; i < actorData.appliedEffects.length; i++) {
+ const item = actorData.appliedEffects[i]
+ context.effects.push(item.name)
+ }
return context
@@ -37,7 +58,7 @@ export default {
},
_getTabConfig: (group) => {
- group.tabs.push({id: "combat", group: "sheet", label: "Kampf"})
+ group.tabs.push({id: "health", group: "sheet", label: "Gesundheit"})
},
- template: `systems/DSA_4-1/templates/actor/character/tab-combat.hbs`
+ template: `systems/DSA_4-1/templates/actor/character/tab-health.hbs`
}
\ No newline at end of file
diff --git a/src/module/sheets/character/liturgies.mjs b/src/module/sheets/character/liturgies.mjs
index 4c3d38f0..ac5022c8 100644
--- a/src/module/sheets/character/liturgies.mjs
+++ b/src/module/sheets/character/liturgies.mjs
@@ -68,6 +68,7 @@ export default {
lkpReq: lkp,
lkpMod: mod,
costKaP,
+ fav: item.getFlag("DSA_4-1", "favourite"),
rank: index, // get effective liturgy rank based on deity
liturgiekenntnis: deity,
})
@@ -104,7 +105,7 @@ export default {
_getTabConfig: (group, thisObject) => {
const hasLiturgies = thisObject.document.items.filter(p => p.type === "Liturgy").length > 0 ?? false
if (hasLiturgies) {
- group.tabs.push({id: "liturgies", group: "sheet", label: "Liturgien"})
+ group?.tabs.push({id: "liturgies", group: "sheet", label: "Liturgien"})
}
},
template: `systems/DSA_4-1/templates/actor/character/tab-liturgies.hbs`
diff --git a/src/module/sheets/character/meta.mjs b/src/module/sheets/character/meta.mjs
index de5d56fe..57b92286 100644
--- a/src/module/sheets/character/meta.mjs
+++ b/src/module/sheets/character/meta.mjs
@@ -14,7 +14,7 @@ export default {
},
_getTabConfig: (group) => {
- group.tabs.push({id: "meta", group: "sheet", label: "Meta"})
+ group?.tabs.push({id: "meta", group: "sheet", label: "Meta"})
},
template: `systems/DSA_4-1/templates/actor/character/tab-meta.hbs`
}
\ No newline at end of file
diff --git a/src/module/sheets/character/skills.mjs b/src/module/sheets/character/skills.mjs
index 9cf1d9d5..319f1f58 100644
--- a/src/module/sheets/character/skills.mjs
+++ b/src/module/sheets/character/skills.mjs
@@ -2,7 +2,6 @@ export default {
_prepareContext: (context) => {
const actorData = context.document
- context.spells = []
context.system = actorData.system
context.flags = actorData.flags
context.derived = context.document.system
@@ -51,7 +50,8 @@ export default {
id: item._id,
at: item.system.at,
pa: item.system.pa,
- komplexität: item.system.komplexität
+ komplexität: item.system.komplexität,
+ fav: item.getFlag("DSA_4-1", "favourite")
};
if (talentGruppe === "Kampf") {
diff --git a/src/module/sheets/character/spells.mjs b/src/module/sheets/character/spells.mjs
index 917679be..db409ba5 100644
--- a/src/module/sheets/character/spells.mjs
+++ b/src/module/sheets/character/spells.mjs
@@ -42,6 +42,7 @@ export default {
eigenschaft1: werte[0].name,
eigenschaft2: werte[1].name,
eigenschaft3: werte[2].name,
+ fav: item.getFlag("DSA_4-1", "favourite")
})
})
diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs
index 5508fab8..46331c88 100644
--- a/src/module/sheets/characterSheet.mjs
+++ b/src/module/sheets/characterSheet.mjs
@@ -1,5 +1,5 @@
import Advsf from "./character/advsf.mjs"
-import Combat from "./character/combat.mjs"
+import Health from "./character/health.mjs"
import Effects from "./character/effects.mjs"
import Equipment from "./character/equipment.mjs"
import Liturgies from "./character/liturgies.mjs"
@@ -14,6 +14,14 @@ import {RestingDialog} from "../dialog/restingDialog.mjs";
import {LiturgyDialog} from "../dialog/liturgyDialog.mjs";
import {TalentDialog} from "../dialog/talentDialog.mjs";
import {AttributeDialog} from "../dialog/attributeDialog.mjs";
+import {ItemBrowserDialog} from "../dialog/itemBrowserDialog.mjs";
+import * as EquipmentDocument from "../documents/equipment.mjs";
+import {StandaloneADVSF} from "./character-standalone/advsf.mjs";
+import {StandaloneSkills} from "./character-standalone/skills.mjs";
+import {Bagpack} from "./character-standalone/bagpack.mjs";
+import {StandaloneSpells} from "./character-standalone/spells.mjs";
+import {StandaloneLiturgies} from "./character-standalone/liturgies.mjs";
+import {StandaloneHealth} from "./character-standalone/health.mjs";
const {HandlebarsApplicationMixin, DocumentSheetV2} = foundry.applications.api
const {ActorSheetV2} = foundry.applications.sheets
@@ -37,19 +45,31 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
actions: {
rollCombatSkill: CharacterSheet.#rollCombatSkill,
rollSkill: CharacterSheet.#rollSkill,
- rollFlaw: CharacterSheet.#rollFlaw,
+ rollFlaw: CharacterSheet.rollFlaw,
rollAttribute: CharacterSheet.#rollAttribute,
editImage: DocumentSheetV2.DEFAULT_OPTIONS.actions.editImage,
- openEmbeddedDocument: CharacterSheet.#openEmbeddedDocument,
+ openEmbeddedDocument: CharacterSheet.openEmbeddedDocument,
openCultureDocument: CharacterSheet.#openCultureDocument,
openSpeciesDocument: CharacterSheet.#openSpeciesDocument,
openCombatAction: CharacterSheet.#openCombatAction,
- openLiturgyDialog: CharacterSheet.#openLiturgyDialog,
+ openLiturgyDialog: CharacterSheet.openLiturgyDialog,
+ openSpellDialog: CharacterSheet.openSpellDialog,
progressCooldown: CharacterSheet.#progressCooldown,
cancelCooldown: CharacterSheet.#cancelCooldown,
activateCooldown: CharacterSheet.#activateCooldown,
rest: CharacterSheet.#startResting,
removeEffect: CharacterSheet.#removeEffect,
+ rollDamage: CharacterSheet.#rollDamage,
+ openItemBrowser: CharacterSheet.openItemBrowser,
+ newItem: CharacterSheet.addNewItem,
+ toggleFav: CharacterSheet.toggleFav,
+ openStandaloneADVSF: CharacterSheet.#openStandaloneADVSF,
+ openStandaloneSkills: CharacterSheet.#openStandaloneSkills,
+ openBagpack: CharacterSheet.#openBagpack,
+ openStandaloneSpells: CharacterSheet.#openStandaloneSpells,
+ openStandaloneLiturgies: CharacterSheet.#openStandaloneLiturgies,
+ openStandaloneHealth: CharacterSheet.#openStandaloneHealth,
+ setWounds: CharacterSheet.#setWounds,
}
}
@@ -58,7 +78,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
sheet: {
tabs: [],
initial: 'meta'
- }
+ },
}
/** @inheritDoc */
@@ -75,15 +95,16 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
advsf: {
template: Advsf.template
},
- combat: {
- template: Combat.template
+ health: {
+ template: Health.template
},
equipment: {
template: Equipment.template,
scrollable: ['.inventory']
},
skills: {
- template: Skills.template
+ template: Skills.template,
+ scrollable: ['.tab.skills']
},
spells: {
template: Spells.template
@@ -93,7 +114,16 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
},
effects: {
template: Effects.template
- }
+ },
+ set1: {
+ template: "systems/DSA_4-1/templates/actor/character/tab-set.hbs"
+ },
+ set2: {
+ template: "systems/DSA_4-1/templates/actor/character/tab-set.hbs"
+ },
+ set3: {
+ template: "systems/DSA_4-1/templates/actor/character/tab-set.hbs"
+ },
}
@@ -128,7 +158,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
}).render(true)
}
- static async #rollFlaw(event, target) {
+ static async rollFlaw(event, target) {
new AttributeDialog(this.document, target.dataset.itemId).render(true)
}
@@ -139,7 +169,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
cooldowns.splice(cooldownId, 1)
if (cooldown) {
- cooldown.current = cooldown.current - 1
+ cooldown.current = cooldown.current + 1
}
cooldowns.push(cooldown)
@@ -163,7 +193,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
const cooldowns = this.document.system.cooldowns
const cooldown = this.document.system.cooldowns[cooldownId]
- if (cooldown && cooldown.current <= 0) {
+ if (cooldown && cooldown.current >= cooldown.start) {
const am = new ActionManager(this.document)
console.log(cooldown.data.maneuver)
const action = new Function(`return ${cooldown.data.maneuver}`)
@@ -183,7 +213,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
*
* @param {MouseEvent} event
*/
- static #openEmbeddedDocument(event) {
+ static openEmbeddedDocument(event) {
let dataset = event.target.dataset
if (!dataset.itemId && !dataset.id) {
dataset = event.target.parentElement.dataset
@@ -202,21 +232,29 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
}
static #openCombatAction(event, target) {
+ let {weapon, skill} = target.dataset
+
switch (target.dataset.mode) {
case "attack":
- new CombatActionDialog(this.document).render(true)
+ new CombatActionDialog(this.document, {weapon, skill}).render(true)
break
case "defense":
- new DefenseActionDialog(this.document).render(true)
+ new DefenseActionDialog(this.document, {weapon, skill}).render(true)
break
}
}
- static #openLiturgyDialog(event, target) {
+ static openLiturgyDialog(event, target) {
const {id, lkp, deity} = target.dataset
new LiturgyDialog(this.document, lkp, id, deity).render(true)
}
+ static openSpellDialog(event, target) {
+ const {itemId} = target.dataset
+ console.log(itemId)
+ this.document.itemTypes["Spell"]?.find(p => p.id === itemId)?.sheet.render(true)
+ }
+
static #startResting(event, target) {
const dialog = new RestingDialog(this.document)
@@ -238,6 +276,59 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
}
+ static async openItemBrowser(event, target) {
+ new ItemBrowserDialog(this.document).render(true)
+ }
+
+ static async addNewItem(event, target) {
+ let item = new EquipmentDocument.Equipment({
+ name: "Neuer Gegenstand",
+ type: "Equipment",
+ })
+ const items = await this.document.createEmbeddedDocuments("Item", [item])
+ items[0].sheet.render(true)
+ }
+
+ static async toggleFav(event, target) {
+ const {itemId} = target.dataset
+ const doc = this.document.items.find(p => p.id === itemId)
+
+ if (doc) {
+ const previous = doc.getFlag("DSA_4-1", "favourite") ?? false
+ doc.setFlag("DSA_4-1", "favourite", !previous)
+ }
+ }
+
+ static async #openStandaloneADVSF(event, target) {
+ new StandaloneADVSF(this.document)
+ }
+
+ static async #openStandaloneHealth(event, target) {
+ new StandaloneHealth(this.document)
+ }
+
+ static async #openStandaloneSkills(event, target) {
+ new StandaloneSkills(this.document)
+ }
+
+ static async #openBagpack(event, target) {
+ new Bagpack(this.document)
+ }
+
+ static async #openStandaloneSpells(event, target) {
+ new StandaloneSpells(this.document)
+ }
+
+ static async #openStandaloneLiturgies(event, target) {
+ new StandaloneLiturgies(this.document)
+ }
+
+ static async #setWounds(event, target) {
+ const {value} = target.dataset
+ this.document.update({"system.wunden.aktuell": value})
+ this.render(true)
+ }
+
_configureRenderOptions(options) {
super._configureRenderOptions(options)
@@ -248,6 +339,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
return options
}
+
/**
* Handle form submission
* @this {AdvantageSheet}
@@ -261,13 +353,46 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
await this.document.update(formData.object)
}
+ static async #rollDamage(event, target) {
+ let {weapon, isRanged} = target.dataset
+ isRanged = isRanged == "true"
+ weapon = this.document.items.get(weapon)
+ if (weapon) {
+ const damageFormula = isRanged ? weapon.system.rangedAttackDamage : weapon.system.meleeAttackDamage
+ const calculation = await foundry.applications.api.DialogV2.prompt({
+ window: {title: game.i18n.format("COMBAT_DIALOG_TP.windowTitle")},
+ content: `${game.i18n.format("COMBAT_DIALOG_TP.regularFormula")}
${game.i18n.format("COMBAT_DIALOG_TP.bonusDamage")}
`,
+ ok: {
+ label: game.i18n.format("COMBAT_DIALOG_TP.buttonText"),
+ callback: (event, button, dialog) => {
+ return {
+ formula: button.form.elements.formula.value,
+ bonusDamage: button.form.elements.bonusDamage.value
+ }
+ }
+ }
+ });
+
+ const sanitisedFormula = calculation.formula.replace(/wW/g, "d")
+ const suffix = calculation.bonusDamage >= 0 ? "+" + calculation.bonusDamage : calculation.bonusDamage
+
+ let r = new Roll(sanitisedFormula + suffix, this.document.getRollData());
+ const label = `Schadenswurf`
+ await r.toMessage({
+ speaker: ChatMessage.getSpeaker({actor: this.document}),
+ flavor: label,
+ rollMode: game.settings.get('core', 'rollMode'),
+ })
+ }
+ }
+
_getTabsConfig(group) {
const tabs = foundry.utils.deepClone(super._getTabsConfig(group))
Meta._getTabConfig(tabs, this)
Social._getTabConfig(tabs, this)
Advsf._getTabConfig(tabs, this)
- Combat._getTabConfig(tabs, this)
+ Health._getTabConfig(tabs, this)
Equipment._getTabConfig(tabs, this)
Skills._getTabConfig(tabs, this)
Spells._getTabConfig(tabs, this)
@@ -329,13 +454,6 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
context.img = actorData.img
context.effects = actorData.effects ?? []
- context.maxWounds = actorData.system.wunden.max ?? 3
- context.wounds = actorData.system.wunden.gesamt ?? 0
- context.woundsFilled = []
- for (let i = 1; i <= context.maxWounds; i++) {
- context.woundsFilled[i] = i <= context.wounds
- }
-
context.zonenruestung = game.settings.get("DSA_4-1", "optional_ruestungzonen")
context.trefferzonen = game.settings.get("DSA_4-1", "optional_trefferzonen")
context.ausdauer = game.settings.get("DSA_4-1", "optional_ausdauer")
@@ -350,8 +468,11 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
context.lepper = Math.min((actorData.system.lep.aktuell / actorData.system.lep.max) * 100, 100)
context.keper = Math.min((actorData.system.kap.aktuell / actorData.system.kap.max) * 100, 100)
context.aspper = Math.min((actorData.system.asp.aktuell / actorData.system.asp.max) * 100, 100)
+
context.lepcurrent = actorData.system.lep.aktuell ?? 0
context.aupcurrent = actorData.system.aup.aktuell ?? 0
+ context.aspcurrent = actorData.system.asp.aktuell ?? 0
+ context.kapcurrent = actorData.system.kap.aktuell ?? 0
const fernkampf = actorData.findEquipmentOnSlot("fernkampf", actorData.system.setEquipped, actorData)
const links = actorData.findEquipmentOnSlot("links", actorData.system.setEquipped, actorData)
@@ -360,14 +481,19 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
if (fernkampf) {
const fkitems = fernkampf.system.rangedSkills.map((skillInQuestion) => actorData.items.find(p => p.name === skillInQuestion))
- fkitems.forEach(skill => {
- context.attacks.push({
- name: skill.name,
- using: fernkampf.name,
- at: `${this.document.system.fk.aktuell + skill.system.at}`,
- tp: `${fernkampf.system.rangedAttackDamage}`,
- ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`,
- })
+ fkitems?.forEach(skill => {
+ if (skill) {
+ context.attacks.push({
+ name: skill.name,
+ id: fernkampf._id,
+ skillId: skill._id,
+ using: fernkampf.name,
+ isRanged: true,
+ at: `${this.document.system.fk.aktuell + skill.system.at}`,
+ tp: `${fernkampf.system.rangedAttackDamage}`,
+ ini: `${context.inidice}w6 + ${context.inivalue + fernkampf.system.iniModifier ?? 0}`,
+ })
+ }
})
}
if (links) {
@@ -378,11 +504,14 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
meitems.push(item)
}
})
- meitems.forEach(skill => {
+ meitems?.forEach(skill => {
const obj = skill
context.attacks.push({
name: obj.name,
+ id: links._id,
+ skillId: skill._id,
using: links.name,
+ isRanged: false,
at: `${this.document.system.at.links.aktuell + obj.system.at + links.system.attackModifier}`,
pa: `${this.document.system.pa.links.aktuell + obj.system.pa + links.system.parryModifier}`,
tp: `${links.system.meleeAttackDamage}`,
@@ -398,11 +527,14 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
meitems.push(item)
}
})
- meitems.forEach(skill => {
+ meitems?.forEach(skill => {
const obj = skill
context.attacks.push({
name: obj.name,
+ id: rechts._id,
+ skillId: skill._id,
using: rechts.name,
+ isRanged: false,
at: `${this.document.system.at.rechts.aktuell + obj.system.at + rechts.system.attackModifier}`,
pa: `${this.document.system.pa.rechts.aktuell + obj.system.pa + rechts.system.parryModifier}`,
tp: `${rechts.system.meleeAttackDamage}`,
@@ -411,6 +543,45 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
})
}
+ context.favourites = actorData.items.filter(item => item.getFlag("DSA_4-1", "favourite") === true).map(item => {
+ let id = item.id
+ let t = null
+ switch (item.type) {
+ case "Spell":
+ t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-spell-button.hbs"
+ break;
+ case "Skill":
+ switch (item.system.gruppe) {
+ case "Kampf":
+ t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-weaponskill-button.hbs"
+ break;
+ case "Sprachen":
+ t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-language-button.hbs"
+ break;
+ default:
+ t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-button.hbs"
+ }
+ break;
+ case "Liturgy":
+ t = "systems/DSA_4-1/templates/ui/partial-mini-rollable-liturgy-button.hbs"
+ break;
+ default:
+ t = null
+ }
+
+ let obj = Object.assign({}, item)
+
+ obj.fav = item.getFlag("DSA_4-1", "favourite")
+ obj.id = id
+ obj.group = item.system.gruppe ?? null
+
+ if (t) {
+ obj.template = t
+ }
+
+ return obj
+ })
+
context.cooldowns = actorData.system.cooldowns ?? []
context.cooldowns.forEach(cooldown => {
let weapon = null
@@ -418,15 +589,20 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
let tooltip = cooldown.data.title
if (cooldown.data.weapon) {
weapon = this.document.itemTypes["Equipment"].find(p => p._id === cooldown.data.weapon)
- tooltip += ` Waffe:${weapon.name}`
+ tooltip += ` Waffe: ${weapon.name}`
}
if (cooldown.data.target) {
target = game.actors.get(game.scenes.current.tokens.find(p => p._id === cooldown.data.target).actorId)
- tooltip += ` Waffe:${target.name}`
+ tooltip += ` Ziel: ${target.name}`
}
cooldown.title = cooldown.data.title
cooldown.progress = ((cooldown.current / cooldown.start) * 100) + "%"
- cooldown.tooltip = tooltip + ` Aktionen verbleibend: ${cooldown.current}`
+ if (cooldown.start - cooldown.current > 0) {
+ cooldown.tooltip = tooltip + ` Aktionen verbleibend: ${cooldown.start - cooldown.current} : 1 Aktion aufwenden`
+ } else {
+ cooldown.tooltip = tooltip + ` Aktionen verbleibend: ${cooldown.start - cooldown.current} : Aktion durchführen`
+ }
+
})
context.hasSpells = actorData.itemTypes["Spell"].length > 0
@@ -493,11 +669,11 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
case "advsf":
await Advsf._prepareContext(context, this.document)
break
- case "combat":
- await Combat._prepareContext(context, this.document)
+ case "health":
+ await Health._prepareContext(context, this.document)
break
case "equipment":
- await Equipment._prepareContext(context, this.document)
+ await Equipment._prepareContext(context, this.document, this)
break
case "skills":
await Skills._prepareContext(context, this.document)
@@ -515,11 +691,23 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
return context
}
+ _onPosition(position) {
+
+ if (position.width < 300) {
+ this.element.classList.add("tiny")
+ this.element.querySelector(".sidebuttons").style.left = (position.width + position.left) + "px"
+ this.element.querySelector(".sidebuttons").style.top = (position.top) + "px"
+ } else {
+ this.element.classList.remove("tiny")
+ }
+
+ }
+
_onRender(context, options) {
Meta._onRender(context, options, this.element)
Social._onRender(context, options, this.element)
Advsf._onRender(context, options, this)
- Combat._onRender(context, options, this.element)
+ Health._onRender(context, options, this.element)
Effects._onRender(context, options, this.element)
Equipment._onRender(context, options, this)
Liturgies._onRender(context, options, this.element)
@@ -559,7 +747,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
} else {
if (document.parent && document.parent !== this.actor) {
- document.parent.items.get(document._id).delete()
+ game.DSA41.socket.executeAsGM("removeFromLootTable", document.parent.id, document._id)
}
await this._onDropDocument(event, document)
diff --git a/src/module/sheets/creatureSheet.mjs b/src/module/sheets/creatureSheet.mjs
index 87aafffa..895dc9e2 100644
--- a/src/module/sheets/creatureSheet.mjs
+++ b/src/module/sheets/creatureSheet.mjs
@@ -25,7 +25,6 @@ export class CreatureSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
static TABS = {
sheet: {
tabs: [],
- initial: 'meta'
}
}
@@ -66,6 +65,19 @@ export class CreatureSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
tabs.tabs.push(tab)
}
}
+
+ if (!game.user.isGM) {
+ if (this.document.system.visibility.meta) {
+ tabs.initial = 'meta'
+ } else if (this.document.system.visibility.attacks) {
+ tabs.initial = 'attacks'
+ } else if (this.document.system.visibility.description) {
+ tabs.initial = 'description'
+ } else if (this.document.system.visibility.loot) {
+ tabs.initial = 'loot'
+ }
+ }
+
return tabs
}
diff --git a/src/module/sheets/equipmentSheet.mjs b/src/module/sheets/equipmentSheet.mjs
index 6d29b1fd..76b352c2 100644
--- a/src/module/sheets/equipmentSheet.mjs
+++ b/src/module/sheets/equipmentSheet.mjs
@@ -1,6 +1,6 @@
const {DocumentSheetV2, HandlebarsApplicationMixin} = foundry.applications.api
-export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
+class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
/** @inheritDoc */
static DEFAULT_OPTIONS = {
@@ -311,3 +311,5 @@ export class EquipmentSheet extends HandlebarsApplicationMixin(DocumentSheetV2)
}
}
+
+export default EquipmentSheet
diff --git a/src/module/sheets/merchantSheet.mjs b/src/module/sheets/merchantSheet.mjs
index bc9b2b63..2774656f 100644
--- a/src/module/sheets/merchantSheet.mjs
+++ b/src/module/sheets/merchantSheet.mjs
@@ -109,13 +109,8 @@ export class MerchantSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
actor.createEmbeddedDocuments('Item', [item]).then(documents => {
documents[0].update({'system.quantity': 1})
})
- if (item.system.quantity != -1) { // -1 means infinite
- if (item.system.quantity > 1) {
- item.update({'system.quantity': item.system.quantity - 1})
- } else {
- this.document.deleteEmbeddedDocuments('Item', [item._id]) // delete when the quantity is equal to 0
- }
- }
+
+ game.DSA41.socket.executeAsGM("buyFromLootTable", this.document.id, item.id)
ChatMessage.create({
user: game.user._id,
speaker: {actor},
diff --git a/src/style/atoms/_buttons.scss b/src/style/atoms/_buttons.scss
new file mode 100644
index 00000000..270daf15
--- /dev/null
+++ b/src/style/atoms/_buttons.scss
@@ -0,0 +1,58 @@
+@use "./colours";
+
+@mixin raised_button {
+ background: rgba(0, 0, 0, 0.05);
+ border: 1px solid #ccc;
+ box-shadow: 1px 1px 1px #ccc;
+ border-top-right-radius: 8px;
+ border-bottom-right-radius: 8px;
+}
+
+@mixin uncut_raised_button {
+ @include raised_button;
+ border-radius: 8px;
+
+ button {
+ background: unset;
+ border: unset;
+ box-shadow: unset;
+ color: black;
+
+ &:hover {
+ color: black;
+ }
+
+ @include colours.highlight;
+ }
+}
+
+@mixin pill-button($color:false, $button-color: #F80) {
+ background-image: url("/systems/DSA_4-1/assets/velvet_button.png");
+ background-color: $color;
+ background-repeat: repeat-y;
+ background-size: cover;
+ @if $color {
+ background-blend-mode: overlay;
+ }
+ border-color: $button-color;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 8px;
+ box-shadow: 2px 2px 4px #000;
+ color: $button-color;
+ cursor: pointer;
+ display: inline-block;
+ text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
+ padding: 0 8px;
+ height: 28px;
+ line-height: 28px;
+ vertical-align: middle;
+}
+
+@mixin mini-button($color:false, $button-color: #F80) {
+ @include pill-button($color, $button-color);
+ width: 100%;
+ border-radius: 2px;
+ height: 24px;
+ line-height: 24px;
+}
\ No newline at end of file
diff --git a/src/style/atoms/_colours.scss b/src/style/atoms/_colours.scss
index e495c79a..774e4429 100644
--- a/src/style/atoms/_colours.scss
+++ b/src/style/atoms/_colours.scss
@@ -1,25 +1,25 @@
$nachteil-color: #555753;
$nachteil-text-color: #FFF;
-$liturgie-color: #edd400;
+$liturgie-color: #59aebf;
$liturgie-text-color: #000;
$zauber-color: #3465a4;
$zauber-text-color: #000;
$talent-color: #f57900;
$talent-text-color: #000;
-$kampftalent-color: #cc0000;
+$kampftalent-color: #c36e14;
$kampftalent-text-color: #FFF;
-$talent-body-color: #16bd6c;
+$talent-body-color: #45d18c;
$talent-body-text-color: #000;
-$talent-nature-color: #46800d;
+$talent-nature-color: #7cb544;
$talent-nature-text-color: #000;
-$talent-social-color: #ae9809;
+$talent-social-color: #c8588a;
$talent-social-text-color: #000;
-$talent-knowledge-color: #d319ba;
+$talent-knowledge-color: #2ba9c5;
$talent-knowledge-text-color: #000;
-$talent-language-color: #573bbc;
-$talent-language-text-color: #fff;
-$talent-crafting-color: #ae6813;
+$talent-language-color: #957fe8;
+$talent-language-text-color: #000;
+$talent-crafting-color: #cd9551;
$talent-crafting-text-color: #000;
@@ -83,4 +83,14 @@ $special-action: rgba(68, 34, 204, 0.8);
$special-action-color: #000;
+@mixin highlight {
+ &:hover {
+ text-shadow: 0 0 10px red;
+ }
+ cursor: pointer;
+}
+@mixin svg-highlight {
+ filter: drop-shadow(0px 0px 10px rgb(255 0 0));
+ cursor: pointer;
+}
\ No newline at end of file
diff --git a/src/style/atoms/_typography.scss b/src/style/atoms/_typography.scss
index 0827abfe..cdbf65cc 100644
--- a/src/style/atoms/_typography.scss
+++ b/src/style/atoms/_typography.scss
@@ -24,16 +24,21 @@
}
input,
- .rkp .pill,
.cooldown > span,
.attribute.rollable > .name,
.attribute.rollable > .wert {
font-family: Andalus, sans-serif;
}
+ .mini-skill, .mini-weaponskill, .mini-language-skill, .mini-liturgy, .mini-spell,
.editor.prosemirror.active, .editor.prosemirror.inactive {
font-family: Gentium, sans-serif;
}
+ .mini-skill, .mini-weaponskill, .mini-language-skill, .mini-liturgy, .mini-spell {
+ font-weight: bold;
+ text-transform: capitalize;
+ }
+
}
diff --git a/src/style/molecules/_attribute-die.scss b/src/style/molecules/_attribute-die.scss
index c3126fcf..484520a5 100644
--- a/src/style/molecules/_attribute-die.scss
+++ b/src/style/molecules/_attribute-die.scss
@@ -31,11 +31,12 @@
position: absolute;
left: -1px;
width: 48px;
- top: -1px;
- font-size: smaller;
+ top: 2px;
+ font-size: large;
line-height: 48px;
vertical-align: middle;
text-align: center;
+
@if $darkmode {
color: colours.$attribute-die-label-color-darkmode;
} @else {
@@ -62,7 +63,7 @@
&.colorfulDice {
- &.Mut {
+ .Mut {
.die svg path {
fill: colours.$attribute-die-co-color;
diff --git a/src/style/molecules/_equipment.scss b/src/style/molecules/_equipment.scss
index 8b541f92..1ff14ae4 100644
--- a/src/style/molecules/_equipment.scss
+++ b/src/style/molecules/_equipment.scss
@@ -1,4 +1,5 @@
@use "../atoms/assets";
+@use "../atoms/colours" as colour;
@mixin equipment($darkmode: false) {
position: relative;
@@ -9,14 +10,12 @@
padding: 2px 0 0 2px;
margin: 4px 0 0 4px;
gap: 8px;
- @if darkmode {
- background: rgba(0, 0, 0, 0.3);
- } @else {
- background: assets.$tab-pane-background;
- }
+ background: assets.$tab-pane-background;
.icon {
- width: 32px;
+ object-fit: cover;
+ max-width: 32px;
+ max-height: 32px;
padding: 0;
}
@@ -46,7 +45,7 @@
&:hover {
.name {
- text-shadow: 0 0 10px rgb(255 0 0);
+ @include colour.highlight;
}
border: 1px solid #ccc;
@@ -55,4 +54,12 @@
padding: 0 4px 4px 0;
z-index: 2;
}
+
+ &.worn {
+
+ .name {
+ font-weight: bold;
+ }
+
+ }
}
\ No newline at end of file
diff --git a/src/style/molecules/_liturgy-banner.scss b/src/style/molecules/_liturgy-banner.scss
index 75b73fe7..affcde17 100644
--- a/src/style/molecules/_liturgy-banner.scss
+++ b/src/style/molecules/_liturgy-banner.scss
@@ -205,24 +205,29 @@ $deity_colours_tint: (
.liturgy.rollable {
width: 24px;
+ padding: 0;
svg {
- $color: #e4de61;
- width: 24px;
- height: 24px;
+
+ $color: colour.$liturgie-color;
+ width: 32px;
+ height: 32px;
top: 1px;
z-index: 1;
position: relative;
-
path {
fill: $color;
}
}
+
+ &:hover {
+ @include colour.svg-highlight;
+ }
}
- .clickable:hover {
- text-shadow: 0 0 10px rgb(255 0 0);
+ .clickable {
+ @include colour.highlight;
}
}
diff --git a/src/style/molecules/_rollable.scss b/src/style/molecules/_rollable.scss
index a1c7cb5b..ca2d0893 100644
--- a/src/style/molecules/_rollable.scss
+++ b/src/style/molecules/_rollable.scss
@@ -2,6 +2,7 @@
@use 'sass:map';
@use "../atoms/colours" as colour;
@use "../atoms/numbers" as numbers;
+@use "../atoms/buttons";
$rollable_colours: (
"nachteil": colour.$nachteil-color,
@@ -36,7 +37,7 @@ $rollable_colours_font: (
display: block;
height: 32px;
position: relative;
- margin: 4px;
+ margin: 4px 32px 4px 4px;
.die {
width: 32px;
@@ -52,7 +53,7 @@ $rollable_colours_font: (
.value {
position: absolute;
left: 0;
- top: 0;
+ top: 1px;
width: 32px;
line-height: 30px;
vertical-align: middle;
@@ -69,6 +70,24 @@ $rollable_colours_font: (
top: 6px;
}
}
+
+ &:active {
+
+
+ scale: 0.8;
+
+ .value {
+
+ img {
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ left: 4px;
+ top: 7px;
+ }
+ }
+
+ }
}
.container {
@@ -122,43 +141,30 @@ $rollable_colours_font: (
}
}
}
+
+ .outside {
+ position: absolute;
+ right: -24px;
+ top: 8px;
+ bottom: 8px;
+ z-index: 3;
+
+ @include colour.highlight;
+ }
}
// interactivity
.block.rollable {
- &:hover {
+ .die:hover {
- .die svg {
- filter: drop-shadow(0px 0px 10px rgb(255 0 0));
+ svg {
+ @include colour.svg-highlight;
}
}
- &:active {
- .die {
- width: 28px;
- height: 28px;
- left: 2px;
- top: 2px;
-
- .value {
- width: 28px;
- height: 28px;
- left: -1px;
- top: -2px;
-
- img {
- position: absolute;
- width: 20px;
- height: 20px;
- left: 4px;
- top: 7px;
- }
- }
- }
- }
}
}
@@ -168,7 +174,6 @@ $rollable_colours_font: (
.#{$name}.rollable {
.die {
- stroke-width: 0.5;
svg {
@@ -176,8 +181,7 @@ $rollable_colours_font: (
path {
fill: $color;
- stroke: colour.$rollable-die-border-color;
- stroke-width: 5px;
+
}
}
@@ -189,9 +193,8 @@ $rollable_colours_font: (
}
.container {
- background-image: linear-gradient(to right, rgba($color, numbers.$start_gradient), rgba($color, numbers.$end_gradient));
- border-top-right-radius: 8px;
- border-bottom-right-radius: 8px;
+ // background-image: linear-gradient(to right, rgba($color, numbers.$start_gradient), rgba($color, numbers.$end_gradient));
+ @include buttons.raised_button;
}
}
}
diff --git a/src/style/molecules/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss
index 2ec297a8..f8a5ba5c 100644
--- a/src/style/molecules/_sidebar-elements.scss
+++ b/src/style/molecules/_sidebar-elements.scss
@@ -1,5 +1,6 @@
@use "../atoms/colours" as colors;
@use "sass:color";
+@use "../atoms/buttons";
.dsa41.sheet.actor.character {
@@ -11,7 +12,7 @@
width: 100%;
position: relative;
border: 1px inset #ccc;
- background-color: rgba(0, 0, 0, 0.2);
+ background-color: rgba(0, 0, 0, 0.5);
margin: 8px 0;
label {
@@ -19,8 +20,6 @@
left: 0;
top: 0;
bottom: 0;
- width: 48px;
- background-color: rgba(0, 0, 0, 0.1);
z-index: 3;
line-height: 24px;
vertical-align: middle;
@@ -112,9 +111,7 @@
cursor: pointer;
}
- &:hover {
- text-shadow: 0 0 2px rgba(255, 0, 0, 1);
- }
+ @include colors.highlight;
}
.pa {
@@ -126,21 +123,84 @@
cursor: pointer;
}
- &:hover {
- text-shadow: 0 0 2px rgba(255, 0, 0, 1);
- }
+ @include colors.highlight;
}
.ini {
grid-area: ini;
+ cursor: pointer;
+
+ label {
+ cursor: pointer;
+ }
+
+ @include colors.highlight;
}
.tp {
grid-area: tp;
+ cursor: pointer;
+ label {
+ cursor: pointer;
+ }
+
+ @include colors.highlight;
}
}
+ .favourites {
+
+ h3 {
+ text-align: center;
+ margin: 8px 0;
+ }
+
+ .mini-skill, .mini-weaponskill, .mini-language-skill, .mini-spell, .mini-liturgy {
+ margin-bottom: 4px;
+
+
+ @include colors.highlight;
+ }
+
+ .mini-skill.Körperlich {
+ @include buttons.mini-button($color: color.scale(colors.$talent-body-color, $lightness: -50%), $button-color: gold);
+ }
+
+ .mini-skill.Gesellschaft {
+ @include buttons.mini-button($color: color.scale(colors.$talent-social-color, $lightness: -50%), $button-color: gold);
+ }
+
+ .mini-skill.Natur {
+ @include buttons.mini-button($color: color.scale(colors.$talent-nature-color, $lightness: -50%), $button-color: gold);
+ }
+
+ .mini-skill.Wissen {
+ @include buttons.mini-button($color: color.scale(colors.$talent-knowledge-color, $lightness: -50%), $button-color: gold);
+ }
+
+ .mini-skill.Handwerk {
+ @include buttons.mini-button($color: color.scale(colors.$talent-crafting-color, $lightness: -50%), $button-color: gold);
+ }
+
+ .mini-weaponskill {
+ @include buttons.mini-button($color: color.scale(colors.$kampftalent-color, $lightness: -50%), $button-color: gold);
+ }
+
+ .mini-language-skill {
+ @include buttons.mini-button($color: color.scale(colors.$talent-language-color, $lightness: -50%), $button-color: gold);
+ }
+
+ .mini-spell {
+ @include buttons.mini-button($color: colors.$zauber-color, $button-color: gold);
+ }
+
+ .mini-liturgy {
+ @include buttons.mini-button($color: colors.$liturgie-color, $button-color: gold);
+ }
+
+ }
+
.cooldowns {
h3 {
@@ -208,22 +268,13 @@
position: absolute;
background: url('/systems/DSA_4-1/assets/gradient.png');
background-size: 12px 100%;
+ background-blend-mode: overlay;
+ background-color: rgba(128, 0, 192, 1);
left: 0;
bottom: 0;
top: 0;
border-radius: 12px;
z-index: 2;
-
- &::after { // progress fill
- content: '';
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- border-radius: 12px;
- background-color: rgba(128, 0, 192, 0.5);
- }
}
&::after {
@@ -238,20 +289,20 @@
}
- &.Kampf .progress::after {
- background-color: rgba(colors.$kampftalent-color, 0.5);
+ &.Kampf .progress {
+ background-color: rgba(colors.$kampftalent-color, 1);
}
- &.Karmal .progress::after {
- background-color: rgba(colors.$liturgie-color, 0.5);
+ &.Karmal .progress {
+ background-color: rgba(colors.$liturgie-color, 1);
}
- &.Magisch .progress::after {
- background-color: rgba(colors.$zauber-color, 0.5);
+ &.Magisch .progress {
+ background-color: rgba(colors.$zauber-color, 1);
}
- &.Talent .progress::after {
- background-color: rgba(colors.$talent-color, 0.5);
+ &.Talent .progress {
+ background-color: rgba(colors.$talent-color, 1);
}
}
diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss
index 5b452e73..52e67a4b 100644
--- a/src/style/organisms/_character-sheet.scss
+++ b/src/style/organisms/_character-sheet.scss
@@ -5,10 +5,11 @@
@use "./character-tabs/social";
@use "./character-tabs/advsf";
@use "./character-tabs/inventory";
-@use "./character-tabs/combat";
+@use "./character-tabs/health";
@use "./character-tabs/spells";
@use "./character-tabs/liturgies";
@use "./character-tabs/skills";
+@use "../atoms/buttons";
.application.sheet.dsa41.actor.character {
@@ -36,6 +37,14 @@
font-size: large;
}
+ .rkp {
+
+ .pill {
+ @include buttons.pill-button;
+ }
+
+ }
+
}
div.head-data {
@@ -50,6 +59,7 @@
.profile-img {
width: $sidebar-width - 16px;
}
+
}
nav.sheet-tabs.tabs {
@@ -86,8 +96,8 @@
@include inventory.tab;
}
- .tab.combat.active {
- @include combat.tab;
+ .tab.health.active {
+ @include health.tab;
}
.tab.skills.active {
@@ -102,6 +112,76 @@
@include liturgies.tab;
}
+ .sidebuttons {
+ display: none;
+ }
+ }
+
+ &.tiny:not(.minimized):not(.minimizing) {
+
+ .header-fields {
+ & > div:not(.attributes) {
+ display: none;
+ }
+
+ & > div.attributes {
+ position: absolute;
+ left: -8px;
+ top: -8px;
+ right: -8px;
+ display: grid;
+ gap: 8px;
+ grid-template-columns: repeat(4, 1fr);
+ }
+
+ }
+
+ div.head-data {
+ width: unset;
+ top: 136px;
+ left: 8px;
+ right: 8px;
+ bottom: 8px;
+
+ .profile-img {
+ justify-self: center;
+ }
+ }
+
+ .sheet-tabs {
+ display: none;
+ }
+
+ section.tab.tab.tab {
+ display: none;
+ }
+
+ .sidebuttons {
+ position: fixed;
+ display: block;
+ margin-left: 27px;
+ margin-top: 48px;
+ pointer-events: none;
+ rotate: 90deg;
+ transform-origin: top left;
+
+ div {
+ display: flex;
+ gap: 4px;
+
+ button {
+ background-image: url("/systems/DSA_4-1/assets/velvet_button.png");
+ background-repeat: repeat-y;
+ background-size: cover;
+ color: white;
+ font-weight: bold;
+ pointer-events: all;
+ border-radius: 0;
+ border-top-left-radius: 8px;
+ border-top-right-radius: 8px;
+ }
+ }
+ }
}
}
@@ -126,8 +206,8 @@
@include inventory.tab(true);
}
- .tab.combat.active {
- @include combat.tab(true);
+ .tab.health.active {
+ @include health.tab(true);
}
.tab.skills.active {
diff --git a/src/style/organisms/_combat-action-dialog.scss b/src/style/organisms/_combat-action-dialog.scss
index 274d1032..e5359f2b 100644
--- a/src/style/organisms/_combat-action-dialog.scss
+++ b/src/style/organisms/_combat-action-dialog.scss
@@ -45,6 +45,8 @@
li {
+ cursor: pointer;
+
height: 32px;
display: grid;
line-height: 32px;
@@ -63,6 +65,7 @@
}
&.name-only {
+ padding-left: 40px;
display: block;
}
}
diff --git a/src/style/organisms/_group-sheet.scss b/src/style/organisms/_group-sheet.scss
index 00635e88..4d4aa441 100644
--- a/src/style/organisms/_group-sheet.scss
+++ b/src/style/organisms/_group-sheet.scss
@@ -1,3 +1,5 @@
+@use "../atoms/colours" as colour;
+
.application.sheet.dsa41.actor.group {
.sheet-header {
@@ -30,8 +32,8 @@
}
}
- .rollable:hover {
- text-shadow: 0 0 10px rgb(255 0 0);
+ .rollable {
+ @include colour.highlight;
}
.character {
@@ -131,9 +133,7 @@
display: inline-block;
padding: 0 4px;
- &:hover {
- text-shadow: 0 0 10px rgb(255 0 0);
- }
+ @include colour.highlight;
}
}
}
@@ -168,7 +168,7 @@
&:hover {
.item-name {
- text-shadow: 0 0 10px rgb(255 0 0);
+ @include colour.highlight;
}
}
}
diff --git a/src/style/organisms/_item-browser-dialog.scss b/src/style/organisms/_item-browser-dialog.scss
new file mode 100644
index 00000000..9636d2df
--- /dev/null
+++ b/src/style/organisms/_item-browser-dialog.scss
@@ -0,0 +1,102 @@
+.dsa41.dialog.item-browser {
+
+ .window-content [data-application-part] {
+
+ position: relative;
+
+ .progress {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 24px;
+ border-radius: 4px;
+ background-color: rgba(0, 0, 0, 0.3);
+
+ .fill {
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ background: url('/systems/DSA_4-1/assets/gradient.png');
+ background-size: 24px 100%;
+ background-color: rgba(64, 192, 192, 0.8);
+ background-blend-mode: multiply;
+ }
+
+ .text {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ height: 24px;
+ line-height: 24px;
+ vertical-align: middle;
+ font-weight: bold;
+ margin-left: 8px;
+ text-shadow: 2px 2px 0 rgba(0, 0, 0, 0.3);
+ color: white;
+ }
+
+
+ }
+
+ display: grid;
+ grid-template-columns: 240px 1fr;
+ height: 100%;
+ gap: 16px;
+
+ aside {
+ width: 240px;
+ }
+
+ .scrollable-table {
+
+ display: grid;
+ grid-template-rows: 32px 1fr;
+ overflow: hidden;
+
+ .header {
+ display: grid;
+ grid-template-columns: 64px 1fr 120px 120px 120px;
+ gap: 4px;
+ background-color: rgba(0, 0, 0, 0.3);
+
+ * {
+ font-weight: bold;
+ line-height: 32px;
+ vertical-align: middle;
+ }
+ }
+
+ .scroll-y {
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ border: 1px inset #ccc;
+
+ .item {
+ display: grid;
+ grid-template-columns: 64px 1fr 120px 120px 120px;
+ gap: 4px;
+
+ &:nth-child(odd) {
+ background-color: rgba(0, 0, 0, 0.1);
+ }
+
+ &.selected {
+ background-color: rgba(255, 140, 0, 0.2);
+ border: 1px solid orange;
+ }
+ }
+
+ }
+
+
+ }
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/style/organisms/_merchant-sheet.scss b/src/style/organisms/_merchant-sheet.scss
index 8325fdf6..1eba2f36 100644
--- a/src/style/organisms/_merchant-sheet.scss
+++ b/src/style/organisms/_merchant-sheet.scss
@@ -1,3 +1,6 @@
+@use "../atoms/buttons";
+
+
.dsa41.actor.merchant {
.tab.goods.active {
@@ -22,9 +25,12 @@
overflow-y: auto;
.merchant-good {
+ @include buttons.uncut_raised_button;
+
width: 100%;
display: grid;
break-inside: avoid;
+
grid-template-columns: 32px 1fr 32px;
grid-template-rows: 16px 16px;
grid-template-areas: "img title options" "img price options";
@@ -39,6 +45,7 @@
button {
grid-area: options;
+ height: 100%;
}
.price {
@@ -57,12 +64,7 @@
overflow-y: auto;
.service {
-
- border: 1px inset rgba(0, 0, 0, 1);
- background-color: rgba(0, 0, 0, 0.2);
- border-radius: 4px;
- padding: 4px;
- margin: 4px 0;
+ @include buttons.uncut_raised_button;
display: grid;
grid-template-columns: 32px 1fr 32px;
@@ -105,6 +107,9 @@
}
&.infinite {
+ width: 32px;
+ bottom: -2px;
+
&::before {
content: '∞';
}
diff --git a/src/style/organisms/_resting-dialog.scss b/src/style/organisms/_resting-dialog.scss
index f2b212b6..6d6ef938 100644
--- a/src/style/organisms/_resting-dialog.scss
+++ b/src/style/organisms/_resting-dialog.scss
@@ -14,6 +14,10 @@
margin-left: 32px;
padding-bottom: 16px;
+ &.setting-nest-1 {
+ margin-left: 64px;
+ }
+
&.range {
padding-bottom: 0;
margin-left: 34px;
diff --git a/src/style/organisms/character-tabs/_advsf.scss b/src/style/organisms/character-tabs/_advsf.scss
index 7d7834c9..26022e6f 100644
--- a/src/style/organisms/character-tabs/_advsf.scss
+++ b/src/style/organisms/character-tabs/_advsf.scss
@@ -1,3 +1,5 @@
+@use "../../atoms/buttons";
+
@mixin tab($darkmode: false) {
.advantages-and-specialabilities {
@@ -21,19 +23,9 @@
.advantage, .special-ability, .flaw {
position: relative;
- border: 1px solid gold;
- box-shadow: 2px 2px 4px #000;
- border-radius: 8px;
- height: 24px;
- color: gold;
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
- display: inline-block;
- padding: 0 8px;
margin-left: 0;
margin-bottom: 4px;
- background-image: url("/systems/DSA_4-1/assets/velvet_button.png");
- background-repeat: repeat-y;
- background-size: cover;
+ @include buttons.pill-button($color: rgb(0, 128, 0), $button-color: gold);
span {
position: relative;
@@ -43,20 +35,7 @@
}
&.special-ability {
- &::after {
- background: rgba(128, 0, 96, 0.5);
- }
- }
-
- &::after {
- content: "";
- position: absolute;
- left: 0;
- top: 0;
- right: 0;
- bottom: 0;
- border-radius: 8px;
- background: rgba(0, 128, 0, 0.5);
+ @include buttons.pill-button($color: rgb(128, 0, 96), $button-color: gold);
}
& + .advantage, & + .special-ability {
@@ -80,21 +59,23 @@
width: 24px;
}
- &::after {
- background: rgba(106, 36, 216, 0.5);
- }
-
+ @include buttons.pill-button($color: rgb(106, 36, 216), $button-color: gold);
}
&.disadvantage {
font-style: italic;
-
- &::after {
- background: rgba(128, 0, 0, 0.5);
- }
+ @include buttons.pill-button($color: rgb(128, 0, 0), $button-color: gold);
}
}
}
}
}
+
+.dsa41.actor.character.standalone.advsf {
+ @include tab;
+
+ .advantages-and-specialabilities {
+ flex-direction: column;
+ }
+}
diff --git a/src/style/organisms/character-tabs/_combat.scss b/src/style/organisms/character-tabs/_health.scss
similarity index 56%
rename from src/style/organisms/character-tabs/_combat.scss
rename to src/style/organisms/character-tabs/_health.scss
index 1e3163b7..52769dbe 100644
--- a/src/style/organisms/character-tabs/_combat.scss
+++ b/src/style/organisms/character-tabs/_health.scss
@@ -3,8 +3,8 @@
display: grid;
grid-template-columns: 1fr 320px;
- grid-template-rows: 32px 32px 1fr;
- grid-template-areas: "res res" "wounds wounds" "actions actions" "cooldowns cooldowns";
+ grid-template-rows: 32px 32px 32px 1fr;
+ grid-template-areas: "res res" "wounds wounds" "fatigue fatigue" "effects effects" "effects effects";
padding: 8px;
gap: 8px;
@@ -31,7 +31,7 @@
}
- .wounds {
+ .wounds, .fatigue {
position: relative;
height: 24px;
display: flex;
@@ -90,22 +90,46 @@
}
- .actions {
- grid-area: actions;
- padding: 0;
+ .fatigue {
+ grid-area: fatigue;
+ flex-direction: row;
- .grid-of-actions {
- display: unset;
+ label {
+ span {
+ display: inline-block;
+ height: 26px;
+ line-height: 26px;
+ vertical-align: middle;
+ }
+
+ input {
+ position: absolute;
+ right: 0;
+ height: 26px;
+ text-align: center;
+ padding: 0;
+ margin: 0;
+ width: 28px;
+ }
}
+
+ .filled-segment {
+ background-color: rgba(0, 128, 0, 0.8);
+
+ &.danger {
+ background-color: rgba(255, 0, 0, 0.8);
+ }
+ }
+
}
- .cooldowns {
- grid-area: cooldowns;
+ .effects {
+ grid-area: effects;
}
&.zones {
- grid-template-areas: "res res" "wounds wounds" "actions paperdoll" "cooldowns paperdoll";
+ grid-template-areas: "res res" "wounds wounds" "fatigue fatigue" "effects paperdoll" "effects paperdoll";
.paperdoll {
grid-area: paperdoll;
@@ -230,4 +254,145 @@
}
+}
+
+.mini-health {
+ @include tab;
+
+ display: flex;
+ flex-direction: column;
+ padding: 0;
+
+ input {
+ height: 26px !important;
+ text-align: center !important;
+ padding: 0 !important;
+ margin: 0 !important;
+ width: 28px !important;
+ }
+
+ .side-by-side {
+ display: flex;
+
+ > * {
+ flex: 1;
+ }
+ }
+
+ .paperdoll {
+
+ div {
+ position: relative;
+
+ .wound {
+ position: absolute;
+ width: 32px;
+ height: 32px;
+ border-radius: 16px;
+ border: 1px solid black;
+ background-color: rgba(0, 0, 0, 0.5);
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
+ line-height: 32px;
+ vertical-align: middle;
+ text-align: center;
+ color: red;
+
+
+ &.armlinks {
+ top: 146px;
+ left: 210px;
+ }
+
+ &.armrechts {
+ top: 146px;
+ left: 60px;
+ }
+
+ &.beinlinks {
+ top: 346px;
+ left: 210px;
+ }
+
+ &.beinrechts {
+ top: 346px;
+ left: 60px;
+ }
+
+ &.bauch {
+ top: 166px;
+ left: 136px;
+ }
+
+ &.kopf {
+ top: 6px;
+ left: 136px
+ }
+
+ &.brust {
+ top: 86px;
+ left: 110px;
+ }
+
+ &.ruecken {
+ top: 86px;
+ left: 160px;
+ }
+
+ }
+
+ .armor {
+ position: absolute;
+ width: 32px;
+ height: 32px;
+ border-radius: 0 0 16px 16px;
+ line-height: 32px;
+ vertical-align: middle;
+ text-align: center;
+ border: 1px solid silver;
+ background-color: rgba(0, 0, 0, 0.5);
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
+ color: silver;
+
+ &.armlinks {
+ top: 180px;
+ left: 210px;
+ }
+
+ &.armrechts {
+ top: 180px;
+ left: 60px;
+ }
+
+ &.beinlinks {
+ top: 380px;
+ left: 210px;
+ }
+
+ &.beinrechts {
+ top: 380px;
+ left: 60px;
+ }
+
+ &.bauch {
+ top: 200px;
+ left: 136px;
+ }
+
+ &.kopf {
+ top: 40px;
+ left: 136px
+ }
+
+ &.ruecken {
+ top: 120px;
+ left: 160px;
+ }
+
+ &.brust {
+ top: 120px;
+ left: 110px;
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/style/organisms/character-tabs/_inventory.scss b/src/style/organisms/character-tabs/_inventory.scss
index 3ad244aa..d8c96658 100644
--- a/src/style/organisms/character-tabs/_inventory.scss
+++ b/src/style/organisms/character-tabs/_inventory.scss
@@ -28,7 +28,7 @@
position: relative;
border: 1px inset #ccc;
background-color: rgba(0, 0, 0, 0.2);
- height: 8px;
+ height: 16px;
span.fill {
position: absolute;
@@ -56,11 +56,29 @@
}
}
- h3.inventory-header {
+ .inventory-header {
line-height: 32px;
grid-area: inventory-header;
margin: 0;
padding: 0;
+ display: flex;
+
+ h3 {
+ flex: 1;
+ line-height: 32px;
+ }
+
+ .buttons {
+ flex: 0;
+ display: flex;
+ gap: 4px;
+
+ button {
+
+ }
+ }
+
+
}
@@ -81,5 +99,67 @@
}
}
+
+ h3.equipment-header {
+ line-height: 32px;
+ grid-area: equipment-header;
+ margin: 0;
+ padding: 0;
+ }
+
+ .set {
+ grid-area: equipment;
+ margin: 0;
+ padding: 0;
+ }
}
}
+
+.dsa41.sheet.actor.character.standalone.bagpack {
+ @include tab;
+
+
+ .coinage {
+ position: absolute;
+ bottom: 0;
+ right: 8px;
+ height: 38px;
+ line-height: 38px;
+ vertical-align: middle;
+ }
+
+ .capacity {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ }
+
+ .buttons {
+ position: absolute;
+ bottom: 4px;
+ left: 4px;
+
+ button {
+ display: inline-block;
+ }
+
+ }
+
+ .inventory-table {
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ position: absolute;
+ left: 4px;
+ top: 4px;
+ right: 4px;
+ bottom: 38px;
+
+ .equipment {
+ @include equipment.equipment
+ }
+
+ }
+}
+
diff --git a/src/style/organisms/character-tabs/_skills.scss b/src/style/organisms/character-tabs/_skills.scss
index 3a2a7e4f..e9acdc57 100644
--- a/src/style/organisms/character-tabs/_skills.scss
+++ b/src/style/organisms/character-tabs/_skills.scss
@@ -17,6 +17,13 @@
gap: unset;
padding: unset;
+ fieldset {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+
}
ul {
@@ -38,4 +45,18 @@
}
}
+}
+
+.mini-skills {
+ overflow-x: hidden;
+ overflow-y: auto;
+ height: 100%;
+ @include tab;
+
+ container: unset;
+
+ ul {
+ list-style-type: none;
+ padding-left: 0;
+ }
}
\ No newline at end of file
diff --git a/src/style/organisms/character-tabs/_spells.scss b/src/style/organisms/character-tabs/_spells.scss
index 8a47be00..93c98bc6 100644
--- a/src/style/organisms/character-tabs/_spells.scss
+++ b/src/style/organisms/character-tabs/_spells.scss
@@ -27,12 +27,16 @@
z-index: 2;
top: 0;
left: -4px;
- display: none;
path {
fill: colour.$zauber-color;
}
}
+
+ &:hover {
+ @include colour.svg-highlight;
+ }
+
}
@@ -44,6 +48,8 @@
span {
position: relative;
z-index: 1;
+
+ @include colour.highlight;
}
}
@@ -59,9 +65,9 @@
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
position: absolute;
- top: 2px;
left: 12px;
bottom: 2px;
+ height: 2px;
right: 33%;
z-index: 0;
pointer-events: none;
@@ -87,4 +93,61 @@
padding: 0 4px;
}
}
+}
+
+.mini-spells {
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+
+ .table-header {
+ display: grid;
+ grid-template-columns: 1fr 100px 30px;
+ padding: 0 8px;
+ font-weight: bold;
+ }
+
+ .scrollable-table {
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ thead {
+ display: none;
+
+ }
+
+
+ tr {
+
+ td:nth-child(1) {
+ width: 32px;
+ }
+
+ td:nth-child(3) {
+ width: 100px;
+ }
+
+ td:nth-child(4) {
+ width: 30px;
+ }
+
+ .spell.rollable {
+ position: relative;
+
+ svg {
+
+ position: absolute;
+ width: 32px;
+ height: 32px;
+ z-index: 2;
+ top: 0;
+ left: -4px;
+
+ path {
+ fill: colour.$zauber-color;
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/style/styles.scss b/src/style/styles.scss
index e78462f6..070b26d5 100644
--- a/src/style/styles.scss
+++ b/src/style/styles.scss
@@ -35,4 +35,5 @@
@use "organisms/battle-dialog";
@use "organisms/liturgy-sheet";
@use "organisms/dialog";
-@use "organisms/deity-sheet";
\ No newline at end of file
+@use "organisms/deity-sheet";
+@use "organisms/item-browser-dialog";
\ No newline at end of file
diff --git a/src/system.json b/src/system.json
index 94324e87..2c5045b7 100644
--- a/src/system.json
+++ b/src/system.json
@@ -2,11 +2,12 @@
"id": "DSA_4-1",
"title": "Das Schwarze Auge 4.1",
"description": "Noch ein Spielsystem für Das Schwarze Auge 4.1",
- "version": "0.5.1-rc1",
+ "version": "0.0.1",
"compatibility": {
"minimum": 12,
"verified": 13
},
+ "dependencies": [],
"authors": [
{
"name": "GrandpaPoppy"
@@ -340,7 +341,16 @@
}
}
},
- "socket": false,
+ "socket": true,
+ "relationships": {
+ "requires": [
+ {
+ "id": "socketlib",
+ "type": "module",
+ "manifest": "https://github.com/farling42/foundryvtt-socketlib/releases/latest/download/module.json"
+ }
+ ]
+ },
"initiative": "1d6",
"grid": {
"distance": 1,
@@ -349,5 +359,5 @@
"primaryTokenAttribute": "lep.aktuell",
"url": "https://git.macniel.online/macniel/foundry-dsa41-game",
"manifest": "https://git.macniel.online/macniel/foundry-dsa41-game/raw/branch/main/src/system.json",
- "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/0.5.1-rc1/release.zip"
+ "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/0.0.1/release.zip"
}
diff --git a/src/templates/actor/character/main-sheet.hbs b/src/templates/actor/character/main-sheet.hbs
index e4420fc3..611361ed 100644
--- a/src/templates/actor/character/main-sheet.hbs
+++ b/src/templates/actor/character/main-sheet.hbs
@@ -32,12 +32,14 @@
{{#if ausdauer}}
{{/if}}
@@ -62,25 +64,34 @@
{{this.using}} ({{this.name}})
{{#if this.at}}
-
+ {{/if}}
+
+ {{/if}}
+
+ {{#if (or trefferzonen zonenruestung)}}
+
+ {{/if}}
+
+
+
Einflüsse
+
+ {{#each effects}}
+ {{this}}
+ {{/each}}
+
+
+
+ {{#if (or trefferzonen zonenruestung)}}
+
+
{{#if (and trefferzonen zonenruestung)}}Trefferzonen{{/if}}{{#if
+ (and trefferzonen (not zonenruestung))}}Wunden{{/if}}{{#if
+ (and (not trefferzonen) zonenruestung)}}Rüstung{{/if}}
+
+
+
+
+ {{#if trefferzonen}}
+
{{derived.wunden.kopf}}
+
{{derived.wunden.brust}}
+
{{derived.wunden.armlinks}}
+
{{derived.wunden.armrechts}}
+
{{derived.wunden.ruecken}}
+
{{derived.wunden.bauch}}
+
{{derived.wunden.beinlinks}}
+
{{derived.wunden.beinrechts}}
+ {{/if}}
+ {{#if zonenruestung}}
+
{{derived.rs.kopf}}
+
{{derived.rs.brust}}
+
{{derived.rs.armlinks}}
+
{{derived.rs.armrechts}}
+
{{derived.rs.ruecken}}
+
{{derived.rs.bauch}}
+
{{derived.rs.beinlinks}}
+
{{derived.rs.beinrechts}}
+ {{/if}}
+
+
+ {{/if}}
+
+ {{#if (or trefferzonen zonenruestung)}}
+
+ {{/if}}
+
diff --git a/src/templates/actor/character/standalone/liturgies.hbs b/src/templates/actor/character/standalone/liturgies.hbs
new file mode 100644
index 00000000..e8b8cb52
--- /dev/null
+++ b/src/templates/actor/character/standalone/liturgies.hbs
@@ -0,0 +1,204 @@
+
+
+
\ No newline at end of file
diff --git a/src/templates/actor/character/standalone/skills.hbs b/src/templates/actor/character/standalone/skills.hbs
new file mode 100644
index 00000000..67ff834e
--- /dev/null
+++ b/src/templates/actor/character/standalone/skills.hbs
@@ -0,0 +1,97 @@
+
+
+
+ Kampftalente
+
+ {{#each skills.Kampf}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-weaponskill-button.hbs" this}}
+
+ {{/each}}
+
+
+
+
+
+ Körperliche Talente
+
+
+ {{#each skills.Körperlich}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}}
+
+ {{/each}}
+
+
+
+
+
+ Gesellschaftliche Talente
+
+
+ {{#each skills.Gesellschaft}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}}
+
+ {{/each}}
+
+
+
+
+
+ Natur Talente
+
+
+ {{#each skills.Natur}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}}
+
+ {{/each}}
+
+
+
+
+
+ Wissenstalente
+
+
+ {{#each skills.Wissen}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}}
+
+ {{/each}}
+
+
+
+
+
+ Schriften & Sprachen
+
+
+ {{#each skills.Schriften}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}}
+
+ {{/each}}
+ {{#each skills.Sprachen}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-language-button.hbs" this}}
+
+ {{/each}}
+
+
+
+
+
+ Handwerkliche Talente
+
+
+ {{#each skills.Handwerk}}
+
+ {{> "systems/DSA_4-1/templates/ui/partial-rollable-button.hbs" this}}
+
+ {{/each}}
+
+
+
+
\ No newline at end of file
diff --git a/src/templates/actor/character/standalone/spells.hbs b/src/templates/actor/character/standalone/spells.hbs
new file mode 100644
index 00000000..2ed2e4b5
--- /dev/null
+++ b/src/templates/actor/character/standalone/spells.hbs
@@ -0,0 +1,51 @@
+
\ No newline at end of file
diff --git a/src/templates/actor/character/tab-equipment.hbs b/src/templates/actor/character/tab-equipment.hbs
index 2f59d916..f289a702 100644
--- a/src/templates/actor/character/tab-equipment.hbs
+++ b/src/templates/actor/character/tab-equipment.hbs
@@ -15,29 +15,32 @@
-
+
{{> "systems/DSA_4-1/templates/ui/partial-equipment-button.hbs" equipments}}
-
-
+
\ No newline at end of file
diff --git a/src/templates/actor/character/tab-combat.hbs b/src/templates/actor/character/tab-health.hbs
similarity index 72%
rename from src/templates/actor/character/tab-combat.hbs
rename to src/templates/actor/character/tab-health.hbs
index 67511b0f..dab36be2 100644
--- a/src/templates/actor/character/tab-combat.hbs
+++ b/src/templates/actor/character/tab-health.hbs
@@ -1,7 +1,6 @@
-
-
+
@@ -43,35 +42,54 @@
{{#if (not trefferzonen)}}
-
Wunden: {{this.wounds}} / {{this.maxWounds}}
+
Wunden: {{this.wounds}} / {{this.maxWounds}}
{{#each this.woundsFilled}}
{{#if this}}
-
{{@index}}
{{else}}
-
{{@index}}
+
{{@index}}
{{/if}}
{{/each}}
{{/if}}
+ {{#if withErschoepfung}}
+
+
Erschöpfung
+
+
+ {{#each this.erschoepfungFilled}}
+ {{#if this}}
+
Zusätzliche BE: {{../ueberanstrengung}}"
+ {{else}}data-tooltip="Erschöpft
{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}>{{@index}}
+ {{else}}
+
Zusätzliche BE: {{../ueberanstrengung}}"
+ {{else}}data-tooltip="Erschöpft
{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}>{{@index}}
+ {{/if}}
+ {{/each}}
-
-
Aktionen im Kampf
-
-
- Angriff
- variabel
-
-
- Verteidigen
- variabel
-
-
- {{#each this.actions}}
- {{> "systems/DSA_4-1/templates/ui/partial-action-button.hbs" this}}
- {{/each}}
+ {{#if (gt this.ueberanstrengung 0)}}
+
Zusätzliche BE: {{ueberanstrengung}}"
+ {{else}}data-tooltip="Erschöpft
{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}>{{system.erschoepfung.aktuell}}
+ {{else}}
+
Zusätzliche BE: {{ueberanstrengung}}"
+ {{else}}data-tooltip="Erschöpft
{{../system.erschoepfung.aktuell}} von maximal {{../system.erschoepfung.max}}"{{/if}}>
+ {{/if}}
+ {{/if}}
+
+
+
Einflüsse
+
+ {{#each effects}}
+ {{this}}
+ {{/each}}
+
{{#if (or trefferzonen zonenruestung)}}
@@ -111,5 +129,4 @@
{{/if}}
-
diff --git a/src/templates/actor/character/tab-set.hbs b/src/templates/actor/character/tab-set.hbs
index 43b5bb2c..cde2bd41 100644
--- a/src/templates/actor/character/tab-set.hbs
+++ b/src/templates/actor/character/tab-set.hbs
@@ -1,29 +1,25 @@
-
+
+
+ {{#each this.slots}}
+
+ {{/each}}
+ {{!--
+ {{#if (eq ../actor.system.setEquipped @index)}}
+
Ausgerüstet
+ {{else}}
+
Wechseln
+ {{/if}}
-
-
-
-
+ --}}
- {{#each this.slots}}
-
- {{/each}}
- {{#if (eq ../actor.system.setEquipped @index)}}
-
Ausgerüstet
- {{else}}
-
Wechseln
- {{/if}}
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/templates/actor/character/tab-skills.hbs b/src/templates/actor/character/tab-skills.hbs
index 26c619c2..49203fec 100644
--- a/src/templates/actor/character/tab-skills.hbs
+++ b/src/templates/actor/character/tab-skills.hbs
@@ -2,8 +2,9 @@
data-tab="{{tabs.skills.id}}"
data-group="{{tabs.skills.group}}">
-
-
Kampftalente
+
+
+ Kampftalente
{{#each skills.Kampf}}
@@ -11,9 +12,11 @@
{{/each}}
+
-
-
Körperliche Talente
+
+
+ Körperliche Talente
{{#each skills.Körperlich}}
@@ -22,9 +25,11 @@
{{/each}}
+
-
-
Gesellschaftliche Talente
+
+
+ Gesellschaftliche Talente
{{#each skills.Gesellschaft}}
@@ -33,9 +38,11 @@
{{/each}}
+
-
-
Natur Talente
+
+
+ Natur Talente
{{#each skills.Natur}}
@@ -44,9 +51,11 @@
{{/each}}
+
-
-
Wissenstalente
+
+
+ Wissenstalente
{{#each skills.Wissen}}
@@ -55,9 +64,11 @@
{{/each}}
+
-
-
Schriften & Sprachen
+
+
+ Schriften & Sprachen
{{#each skills.Schriften}}
@@ -71,9 +82,11 @@
{{/each}}
+
-
-
Handwerkliche Talente
+
+
+ Handwerkliche Talente
{{#each skills.Handwerk}}
@@ -82,6 +95,7 @@
{{/each}}
+
\ No newline at end of file
diff --git a/src/templates/actor/character/tab-spells.hbs b/src/templates/actor/character/tab-spells.hbs
index 46ec9463..42ca511e 100644
--- a/src/templates/actor/character/tab-spells.hbs
+++ b/src/templates/actor/character/tab-spells.hbs
@@ -25,6 +25,7 @@
Probe
ZfW
Merkmale
+
@@ -33,7 +34,7 @@
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
-
+
{{this.name}}
{{this.eigenschaft1}}
{{this.eigenschaft2}}
@@ -43,6 +44,15 @@
{{#each this.merkmal}}
{{this}} {{/each}}
+
+
+ {{#if this.fav}}
+
+ {{else}}
+
+ {{/if}}
+
+
{{/each}}
diff --git a/src/templates/actor/merchant/tab-services.hbs b/src/templates/actor/merchant/tab-services.hbs
index 6f69dd1d..ca964624 100644
--- a/src/templates/actor/merchant/tab-services.hbs
+++ b/src/templates/actor/merchant/tab-services.hbs
@@ -40,7 +40,8 @@
{{this.name}}
{{currency this.price}}
{{this.availability}}
+ (lte this.availability 0)}}infinite{{/if}}">{{#unless
+ (lte this.availability 0)}}{{this.availability}}{{/unless}}
{{/if}}
diff --git a/src/templates/dialog/combat-action.hbs b/src/templates/dialog/combat-action.hbs
index e39875e7..8fdad05a 100644
--- a/src/templates/dialog/combat-action.hbs
+++ b/src/templates/dialog/combat-action.hbs
@@ -5,7 +5,7 @@
{{#each tokenDistances}}
- {{this.actor.name}} ({{this.d}} {{../distanceUnit}}
)
@@ -18,7 +18,7 @@
Waffe auswählen
{{#each weapons}}
- {{this.name}}
({{this.skillName}}) {{#if this.combatStatistics}}
@@ -31,7 +31,7 @@
Manöver auswählen
{{#each maneuver}}
- {{this.name}}
{{/each}}
@@ -55,7 +55,8 @@
- Angreifen Angreifen
diff --git a/src/templates/dialog/defense-action.hbs b/src/templates/dialog/defense-action.hbs
index 90eae4e7..c9724512 100644
--- a/src/templates/dialog/defense-action.hbs
+++ b/src/templates/dialog/defense-action.hbs
@@ -3,7 +3,7 @@
Waffe auswählen
{{#each circumstances}}
-
+
\ No newline at end of file
diff --git a/src/templates/item/spell/tab-variants.hbs b/src/templates/item/spell/tab-variants.hbs
index 334d3786..c382c66d 100644
--- a/src/templates/item/spell/tab-variants.hbs
+++ b/src/templates/item/spell/tab-variants.hbs
@@ -1,7 +1,7 @@
\ No newline at end of file
diff --git a/src/templates/ui/partial-cooldown.hbs b/src/templates/ui/partial-cooldown.hbs
new file mode 100644
index 00000000..d6cb26ee
--- /dev/null
+++ b/src/templates/ui/partial-cooldown.hbs
@@ -0,0 +1,14 @@
+
+
+
{{this.title}}
+
+
+
+
\ No newline at end of file
diff --git a/src/templates/ui/partial-mini-rollable-button.hbs b/src/templates/ui/partial-mini-rollable-button.hbs
new file mode 100644
index 00000000..36984790
--- /dev/null
+++ b/src/templates/ui/partial-mini-rollable-button.hbs
@@ -0,0 +1,3 @@
+
+ {{this.name}}
+
\ No newline at end of file
diff --git a/src/templates/ui/partial-mini-rollable-language-button.hbs b/src/templates/ui/partial-mini-rollable-language-button.hbs
new file mode 100644
index 00000000..7fb3506c
--- /dev/null
+++ b/src/templates/ui/partial-mini-rollable-language-button.hbs
@@ -0,0 +1,3 @@
+
+ {{this.name}}
+
\ No newline at end of file
diff --git a/src/templates/ui/partial-mini-rollable-liturgy-button.hbs b/src/templates/ui/partial-mini-rollable-liturgy-button.hbs
new file mode 100644
index 00000000..e032c98a
--- /dev/null
+++ b/src/templates/ui/partial-mini-rollable-liturgy-button.hbs
@@ -0,0 +1,3 @@
+
+ {{this.name}}
+
\ No newline at end of file
diff --git a/src/templates/ui/partial-mini-rollable-spell-button.hbs b/src/templates/ui/partial-mini-rollable-spell-button.hbs
new file mode 100644
index 00000000..da472975
--- /dev/null
+++ b/src/templates/ui/partial-mini-rollable-spell-button.hbs
@@ -0,0 +1,3 @@
+
+ {{this.name}}
+
\ No newline at end of file
diff --git a/src/templates/ui/partial-mini-rollable-weaponskill-button.hbs b/src/templates/ui/partial-mini-rollable-weaponskill-button.hbs
new file mode 100644
index 00000000..aabced0f
--- /dev/null
+++ b/src/templates/ui/partial-mini-rollable-weaponskill-button.hbs
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/src/templates/ui/partial-rollable-button.hbs b/src/templates/ui/partial-rollable-button.hbs
index 7007661b..dcfe6edc 100644
--- a/src/templates/ui/partial-rollable-button.hbs
+++ b/src/templates/ui/partial-rollable-button.hbs
@@ -1,9 +1,5 @@
-
+
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
@@ -25,4 +21,11 @@
{{/each}}
+
+ {{#if this.fav}}
+
+ {{else}}
+
+ {{/if}}
+
diff --git a/src/templates/ui/partial-rollable-language-button.hbs b/src/templates/ui/partial-rollable-language-button.hbs
index 76027387..b4196107 100644
--- a/src/templates/ui/partial-rollable-language-button.hbs
+++ b/src/templates/ui/partial-rollable-language-button.hbs
@@ -1,10 +1,7 @@
-
+
-
+
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
{{#if this.taw}}
{{this.taw}}
@@ -26,4 +23,11 @@
{{/each}}
+
+ {{#if this.fav}}
+
+ {{else}}
+
+ {{/if}}
+
diff --git a/src/templates/ui/partial-rollable-weaponskill-button.hbs b/src/templates/ui/partial-rollable-weaponskill-button.hbs
index 552ea31f..fe7648dd 100644
--- a/src/templates/ui/partial-rollable-weaponskill-button.hbs
+++ b/src/templates/ui/partial-rollable-weaponskill-button.hbs
@@ -1,11 +1,10 @@
-
+
{{> 'systems/DSA_4-1/templates/ui/partial-die.hbs' }}
- {{#if this.taw}}
{{this.taw}}
{{else}}
@@ -25,4 +24,11 @@
{{/if}}
+
+ {{#if this.fav}}
+
+ {{else}}
+
+ {{/if}}
+