diff --git a/src/lang/de.json b/src/lang/de.json
index a503b8d3..2561331e 100644
--- a/src/lang/de.json
+++ b/src/lang/de.json
@@ -1,22 +1,49 @@
{
- "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": {
+ "progress": "{t} weiter durchführen",
+ "cancel": "{t} abbrechen",
+ "activate": "{t} auslösen"
+ },
+ "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"
+ }
}
diff --git a/src/module/dialog/combatAction.mjs b/src/module/dialog/combatAction.mjs
index 87d9c7f4..c89f0165 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
@@ -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/setup/partials.mjs b/src/module/setup/partials.mjs
index 9ff711c4..cf2de449 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',
diff --git a/src/module/sheets/characterSheet.mjs b/src/module/sheets/characterSheet.mjs
index 5508fab8..b59c2cfb 100644
--- a/src/module/sheets/characterSheet.mjs
+++ b/src/module/sheets/characterSheet.mjs
@@ -50,6 +50,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
activateCooldown: CharacterSheet.#activateCooldown,
rest: CharacterSheet.#startResting,
removeEffect: CharacterSheet.#removeEffect,
+ rollDamage: CharacterSheet.#rollDamage,
}
}
@@ -202,12 +203,14 @@ 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
}
}
@@ -261,6 +264,39 @@ 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: ``,
+ 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))
@@ -363,7 +399,10 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
fkitems.forEach(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}`,
@@ -382,7 +421,10 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
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}`,
@@ -402,7 +444,10 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
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}`,
diff --git a/src/style/atoms/_typography.scss b/src/style/atoms/_typography.scss
index 0827abfe..a56c325e 100644
--- a/src/style/atoms/_typography.scss
+++ b/src/style/atoms/_typography.scss
@@ -24,7 +24,6 @@
}
input,
- .rkp .pill,
.cooldown > span,
.attribute.rollable > .name,
.attribute.rollable > .wert {
diff --git a/src/style/molecules/_equipment.scss b/src/style/molecules/_equipment.scss
index 8b541f92..86c606e2 100644
--- a/src/style/molecules/_equipment.scss
+++ b/src/style/molecules/_equipment.scss
@@ -9,14 +9,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;
}
@@ -55,4 +53,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/_sidebar-elements.scss b/src/style/molecules/_sidebar-elements.scss
index 2ec297a8..7a696c23 100644
--- a/src/style/molecules/_sidebar-elements.scss
+++ b/src/style/molecules/_sidebar-elements.scss
@@ -133,10 +133,28 @@
.ini {
grid-area: ini;
+ cursor: pointer;
+
+ label {
+ cursor: pointer;
+ }
+
+ &:hover {
+ text-shadow: 0 0 2px rgba(255, 0, 0, 1);
+ }
}
.tp {
grid-area: tp;
+ cursor: pointer;
+
+ label {
+ cursor: pointer;
+ }
+
+ &:hover {
+ text-shadow: 0 0 2px rgba(255, 0, 0, 1);
+ }
}
}
diff --git a/src/style/organisms/_character-sheet.scss b/src/style/organisms/_character-sheet.scss
index 5b452e73..a653ed6f 100644
--- a/src/style/organisms/_character-sheet.scss
+++ b/src/style/organisms/_character-sheet.scss
@@ -36,6 +36,14 @@
font-size: large;
}
+ .rkp {
+
+ .pill {
+ cursor: pointer;
+ }
+
+ }
+
}
div.head-data {
@@ -50,6 +58,7 @@
.profile-img {
width: $sidebar-width - 16px;
}
+
}
nav.sheet-tabs.tabs {
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/system.json b/src/system.json
index 94324e87..be6b6c09 100644
--- a/src/system.json
+++ b/src/system.json
@@ -2,7 +2,7 @@
"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
@@ -349,5 +349,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..f4198f96 100644
--- a/src/templates/actor/character/main-sheet.hbs
+++ b/src/templates/actor/character/main-sheet.hbs
@@ -62,25 +62,34 @@
{{this.using}} ({{this.name}})
{{#if this.at}}
-