implements spell restrictions

pull/67/head
macniel 2025-11-27 15:25:40 +01:00
parent 959f47f348
commit 94a80eb321
5 changed files with 108 additions and 20 deletions

View File

@ -44,6 +44,13 @@
"bonusDamage": "Zusätzlicher Schaden:", "bonusDamage": "Zusätzlicher Schaden:",
"buttonText": "Würfeln" "buttonText": "Würfeln"
}, },
"SPELL_DIALOG": {
"notReadyReason": {
"title": "Zauber kann aus folgenden Gründen nicht gewirkt werden:",
"noRepresentation": "Keine Repräsentation gewählt",
"tooManySpoMods": "Zu viele Spontane Modifikationen ausgewählt"
}
},
"ITEM_BROWSER": { "ITEM_BROWSER": {
"progress": "{current}/{max}: Importiere von {compendium}" "progress": "{current}/{max}: Importiere von {compendium}"
} }

View File

@ -1,4 +1,24 @@
const data = { export const leadingAttribute = {
"Alchimist": "KL",
"Borbaradianer": "KL",
"Druide": "KL",
"Geode (Herren der Erde)": "KL",
"Magier": "KL",
"Scharlatane": "KL",
"Zibilijas": "KL",
"Achaz": "IN",
"Derwisch": "IN",
"Durro-Dûn": "IN",
"Elfe": "IN",
"Ferkina": "IN",
"Geode (Diener Sumus)": "IN",
"Hexe": "IN",
"Schamane": "IN",
"Schelm": "IN",
"Zaubertänzer": "IN"
}
export const spoModData = {
"Veränderte Technik": { "Veränderte Technik": {
name: "Veränderte Technik", name: "Veränderte Technik",
@ -30,7 +50,7 @@ const data = {
}, },
"Erzwingen": { "Erzwingen": {
name: "Erzwingen", name: "Erzwingen",
description: "Verringert Erschwernis um 1 je doppelten AsP Punkt", description: "Verringert Erschwernis um 1 je quadrierten AsP Punkt",
mod: -1, mod: -1,
castTimeMod: 1, castTimeMod: 1,
castTimeMode: "Addition" castTimeMode: "Addition"
@ -38,7 +58,7 @@ const data = {
"Kosten einsparen": { "Kosten einsparen": {
name: "Kosten einsparen", name: "Kosten einsparen",
description: "Reduziert die Kosten des Zaubers um 10% für jede zusätzlich aufgewendete Aktion", description: "Reduziert die Kosten des Zaubers um 10% für jede zusätzlich aufgewendete Aktion",
mod: 3, mod: -3,
castingCosts: 0.1, castingCosts: 0.1,
castingCostsMode: "Multiply", castingCostsMode: "Multiply",
castTimeMod: 1, castTimeMod: 1,
@ -48,19 +68,17 @@ const data = {
"Vergrößerung von Reichweite oder Wirkungsradius": { "Vergrößerung von Reichweite oder Wirkungsradius": {
name: "Vergrößerung von Reichweite oder Wirkungsradius", name: "Vergrößerung von Reichweite oder Wirkungsradius",
description: "Vergrößert die Reichweite oder wenn möglich den Wirkungsradius auf kosten von Aktionen", description: "Vergrößert die Reichweite oder wenn möglich den Wirkungsradius auf kosten von Aktionen",
mod: 5, mod: -5,
castTimeMod: 1, castTimeMod: 1,
castTimeMode: "Addition" castTimeMode: "Addition"
}, },
"Verkleinerung von Reichweite oder Wirkungsradius": { "Verkleinerung von Reichweite oder Wirkungsradius": {
name: "Verkleinerung von Reichweite oder Wirkungsradius", name: "Verkleinerung von Reichweite oder Wirkungsradius",
description: "Verkleinert die Reichweite oder wenn möglich den Wirkungsradius auf kosten von Aktionen", description: "Verkleinert die Reichweite oder wenn möglich den Wirkungsradius auf kosten von Aktionen",
mod: 3, mod: -3,
castTimeMod: 1, castTimeMod: 1,
castTimeMode: "Addition" castTimeMode: "Addition"
}, },
} }
export default data

View File

@ -1,6 +1,6 @@
import {Talent} from "../data/talent.mjs";
import {ATTRIBUTE} from "../data/attribute.mjs"; import {ATTRIBUTE} from "../data/attribute.mjs";
import SpoModData from "../data/spomods/spoModData.mjs"; import {spoModData, leadingAttribute} from "../data/spellData/spellData.mjs";
const { const {
ApplicationV2, ApplicationV2,
@ -50,6 +50,7 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
_variants = {} _variants = {}
_costModel = {} _costModel = {}
_castTimeModel = {} _castTimeModel = {}
_spomods = {}
displayModResult = 0 displayModResult = 0
constructor(actor, spellId) { constructor(actor, spellId) {
@ -142,6 +143,8 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
}) })
this._spomods = foundry.utils.expandObject(formData.object)["spoMods"]
this.render({parts: ["form"]}) this.render({parts: ["form"]})
} }
@ -247,10 +250,11 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
context.text = this._spell.system.wirkung context.text = this._spell.system.wirkung
context.dice = [] context.dice = []
context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice') context.colorfulDice = game.settings.get('DSA_4-1', 'optional_colorfuldice')
context.modResult = this._spell.system.zfw - this.mod context.modResult = this._spell.system.zfw + this.mod
context.penalty = (this.mod > 0 ? "+" : "") + this.mod context.penalty = (this.mod > 0 ? "+" : "") + this.mod
context.displayModResult = (context.modResult > 0 ? "+" : "") + context.modResult context.displayModResult = (context.modResult > 0 ? "+" : "") + context.modResult
context.castingTime = this.#normalizeCastingTime(this._spell) context.castingTime = this.#normalizeCastingTime(this._spell)
context.ready = true
// variable probe (should consider Achaz as they can replace one KL in a KL/KL/* spell with IN // variable probe (should consider Achaz as they can replace one KL in a KL/KL/* spell with IN
@ -291,6 +295,9 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
Object.entries(this._spell.system.repräsentation).forEach(([key, value]) => { Object.entries(this._spell.system.repräsentation).forEach(([key, value]) => {
context.representationOptions[key] = key context.representationOptions[key] = key
}) })
if (!this._selectedRepresentation) {
context.ready = false
}
// Costs and Mutators // Costs and Mutators
@ -308,26 +315,70 @@ export class SpellDialog extends HandlebarsApplicationMixin(ApplicationV2) {
} }
// SpoMods // SpoMods
context.spoModCount = Object.values(this._spomods).reduce((previousValue, currentValue) => previousValue + currentValue, 0)
context.maxSpoModCount = 0
if (this._selectedRepresentation) {
const leadingAttributKey = leadingAttribute[this._selectedRepresentation]
context.maxSpoModCount = (this._actor.system.attribute[leadingAttributKey.toLowerCase()].aktuell ?? 0) - 12
if (context.maxSpoModCount < 0) {
context.maxSpoModCount = 0
}
}
if (context.spoModCount > context.maxSpoModCount) {
context.ready = false
}
const mapper = (spoModName) => {
let data = spoModData[spoModName]
let value = this._spomods[data.name] ?? 0
let totalModValue = data.mod * value
return {
...data,
value,
totalModValue
}
}
context.spoMods = [] context.spoMods = []
if (this._spell.system.modifikationen) { if (this._spell.system.modifikationen) {
this._spell.system.modifikationen.split(",").forEach(spoMod => { this._spell.system.modifikationen.split(",").forEach(spoMod => {
switch (spoMod.trim()) { switch (spoMod.trim()) {
case "Zauberdauer": case "Zauberdauer":
context.spoMods.push(SpoModData["Halbierte Zauberdauer"]) context.spoMods.push(mapper("Halbierte Zauberdauer"))
context.spoMods.push(SpoModData["Verdoppelte Zauberdauer"]) context.spoMods.push(mapper("Verdoppelte Zauberdauer"))
break; break;
case "Kosten": case "Kosten":
context.spoMods.push(SpoModData["Kosten einsparen"]) context.spoMods.push(mapper("Kosten einsparen"))
break; break;
case "Reichweite": case "Reichweite":
context.spoMods.push(SpoModData["Verkleinerung von Reichweite oder Wirkungsradius"]) context.spoMods.push(mapper("Verkleinerung von Reichweite oder Wirkungsradius"))
context.spoMods.push(SpoModData["Vergrößerung von Reichweite oder Wirkungsradius"]) context.spoMods.push(mapper("Vergrößerung von Reichweite oder Wirkungsradius"))
break; break;
} }
}) })
} }
if (!context.ready) {
context.notReadyReasons = `<em>${game.i18n.format("SPELL_DIALOG.notReadyReason.title")}</em><ul>`
if (context.spoModCount > context.maxSpoModCount) {
context.notReadyReasons += `<li>${game.i18n.format("SPELL_DIALOG.notReadyReason.tooManySpoMods")}</li>`
}
if (!this._selectedRepresentation) {
context.notReadyReasons += `<li>${game.i18n.format("SPELL_DIALOG.notReadyReason.noRepresentation")}</li>`
}
context.notReadyReasons += "</ul>"
}
return context return context
} }

View File

@ -38,6 +38,15 @@
.variant { .variant {
display: grid; display: grid;
grid-template-columns: 80px 1fr; grid-template-columns: 80px 1fr;
input[type="number"] {
padding: 0;
margin: 0;
height: 21px;
max-width: 30px;
}
} }
} }

View File

@ -52,14 +52,15 @@
{{#if this.spoMods}} {{#if this.spoMods}}
<fieldset class="scroll-y"> <fieldset class="scroll-y">
<legend>Spontane Modifikation</legend> <legend>Spontane Modifikation {{#if this.spoModCount}}{{#if this.maxSpoModCount}}
[{{this.spoModCount}}/{{this.maxSpoModCount}}]{{/if}}{{/if}}</legend>
<div class="variantList"> <div class="variantList">
{{#each this.spoMods}} {{#each this.spoMods}}
<div class="variant" data-tooltip="{{{description}}}"> <div class="variant" data-tooltip="{{{description}}}">
<div class="selection"> <div class="selection">
<label> <label>
<input type="checkbox" name="spoMods.{{name}}" {{checked variantChecked}}> <input type="number" name="spoMods.{{name}}" value="{{value}}">
{{#if (gte mod 0)}}+{{/if}}{{mod}} <span>&times; {{#if (gte mod 0)}}+{{/if}}{{mod}}</span>
</label> </label>
</div> </div>
<div class="variantText"> <div class="variantText">
@ -104,7 +105,9 @@
</fieldset> </fieldset>
<button class="actions" data-action="use"><i class="fa-solid fa-sparkles"></i> Zauber wirken {{#if modResult}} <button class="actions" {{#if ready}}data-action="cast" {{else}}
data-tooltip="{{{notReadyReasons}}}" disabled="disabled" {{/if}}><i class="fa-solid fa-sparkles"></i> Zauber
wirken {{#if modResult}}
[{{displayModResult}}]{{/if}}</button> [{{displayModResult}}]{{/if}}</button>
</section> </section>