liturgies can now be pushed into queue.

pull/64/head
macniel 2025-10-31 19:15:15 +01:00
parent a861245d44
commit 9948521512
10 changed files with 142 additions and 32 deletions

View File

@ -10,6 +10,7 @@
"scripts": { "scripts": {
"test": "true", "test": "true",
"build": "gulp", "build": "gulp",
"localBuild": "VERSION=0.0.1 gulp",
"installToFoundry": "node installToFoundry.mjs" "installToFoundry": "node installToFoundry.mjs"
}, },
"devDependencies": { "devDependencies": {

View File

@ -32,6 +32,7 @@ import {MerchantDataModel} from "./module/data/merchant.mjs";
import {MerchantSheet} from "./module/sheets/merchantSheet.mjs"; import {MerchantSheet} from "./module/sheets/merchantSheet.mjs";
import {RestingDialog} from "./module/dialog/restingDialog.mjs"; import {RestingDialog} from "./module/dialog/restingDialog.mjs";
import {BattleDialog} from "./module/dialog/battleDialog.mjs"; import {BattleDialog} from "./module/dialog/battleDialog.mjs";
import {Talent} from "./module/data/talent.mjs";
async function preloadHandlebarsTemplates() { async function preloadHandlebarsTemplates() {
return foundry.applications.handlebars.loadTemplates([ return foundry.applications.handlebars.loadTemplates([
@ -60,7 +61,8 @@ Hooks.once("init", () => {
Trefferzone, Trefferzone,
Wunde, Wunde,
RestingDialog, RestingDialog,
BattleDialog BattleDialog,
Talent
} }
// Configure custom Document implementations. // Configure custom Document implementations.

View File

@ -89,7 +89,8 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
weapon: this._weaponId, weapon: this._weaponId,
skill: this._skillId, skill: this._skillId,
target: this._targetId, target: this._targetId,
maneuver, title: maneuver.name,
maneuver: maneuver.activate.toString(),
mod: this._mod, mod: this._mod,
circumstance: this._circumstance, circumstance: this._circumstance,
penalty: this._penalty, penalty: this._penalty,
@ -104,10 +105,12 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
start: maneuver.cooldown({weapon, skill, target, mod: this._mod}), start: maneuver.cooldown({weapon, skill, target, mod: this._mod}),
current: maneuver.cooldown({weapon, skill, target, mod: this._mod}), current: maneuver.cooldown({weapon, skill, target, mod: this._mod}),
data: { data: {
cssClass: "Kampf",
weapon: this._weaponId, weapon: this._weaponId,
skill: this._skillId, skill: this._skillId,
target: this._targetId, target: this._targetId,
maneuver, title: maneuver.name,
maneuver: maneuver.activate.toString(),
mod: this._mod, mod: this._mod,
circumstance: this._circumstance, circumstance: this._circumstance,
penalty: this._penalty, penalty: this._penalty,

View File

@ -135,10 +135,55 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
const castingTime = this.#normalizeCastingTime(this._liturgy) const castingTime = this.#normalizeCastingTime(this._liturgy)
//TODO push it into the sun eeerh cooldown queue //TODO push it into the sun eeerh cooldown queue
//if (castingTime > 0) { if (castingTime > 0) {
const cooldowns = this._actor.system.cooldowns
let m = (queue, data) => {
new game.DSA41.Talent({
name: data.title,
taw: data.taw,
mod: data.mod,
eigenschaften: {
mu: data.eigenschaften.mu,
in: data.eigenschaften.in,
ch: data.eigenschaften.ch,
},
eigenschaft1: "mu",
eigenschaft2: "in",
eigenschaft3: "ch"
}).evaluate("publicroll").then(result => {
// this._actor.system.cooldowns.push() result.evaluatedRoll.toMessage({
//} else { speaker: ChatMessage.getSpeaker({actor: game.actors.get(data.actorId)}),
flavor: `Liturgie: ${data.title}<br/>LkP*: ${result.tap}<br/>${result.meisterlich ? "Meisterlich" : ""}${result.patzer ? "Petzer" : ""}<br/>${data.variant}`,
})
})
}
cooldowns.push({
start: castingTime,
current: castingTime,
data: {
cssClass: "Karmal",
title: this._liturgy.name,
taw: lkp,
mod: mod,
actorId: this._actor._id,
variant: this._variation.effect,
eigenschaften: {
mu: this._actor.system.attribute.mu.aktuell,
in: this._actor.system.attribute.in.aktuell,
ch: this._actor.system.attribute.ch.aktuell,
},
eigenschaft1: "mu",
eigenschaft2: "in",
eigenschaft3: "ch",
circumstance: circumstance,
maneuver: m.toString()
}
})
await this._actor.update({"system.cooldowns": cooldowns})
ui.notifications.info(`Neue Aktion für ${this._liturgy.name} mit Abklingzeit von ${castingTime} Aktionen hinzugefügt`);
} else {
const result = await new Talent({ const result = await new Talent({
name: this._liturgy.name, name: this._liturgy.name,
taw: lkp, taw: lkp,
@ -157,7 +202,7 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
speaker: ChatMessage.getSpeaker({actor: this._actor}), speaker: ChatMessage.getSpeaker({actor: this._actor}),
flavor: `Liturgie: ${this._liturgy.name}<br/>Zauberdauer: ${castingTime > 0 ? castingTime + " Aktionen" : resultingLiturgy.castduration}<br/>LkP*: ${result.tap}<br/>${result.meisterlich ? "Meisterlich" : ""}${result.patzer ? "Petzer" : ""}<br/>${this._variation.effect}`, flavor: `Liturgie: ${this._liturgy.name}<br/>Zauberdauer: ${castingTime > 0 ? castingTime + " Aktionen" : resultingLiturgy.castduration}<br/>LkP*: ${result.tap}<br/>${result.meisterlich ? "Meisterlich" : ""}${result.patzer ? "Petzer" : ""}<br/>${this._variation.effect}`,
}) })
//} }
this.close() this.close()
} }
@ -175,7 +220,7 @@ export class LiturgyDialog extends HandlebarsApplicationMixin(ApplicationV2) {
const [_, actions] = castingTime.match(stoßgebetRegExp) const [_, actions] = castingTime.match(stoßgebetRegExp)
return actions return actions
} else if (castingTime.match(gebetRegExp)) { } else if (castingTime.match(gebetRegExp)) {
const [_, actions] = castingTime.match(stoßgebetRegExp) const [_, actions] = castingTime.match(gebetRegExp)
return actions * 20 return actions * 20
} else if (castingTime.match(invalidForCooldownRegExp)) { } else if (castingTime.match(invalidForCooldownRegExp)) {
return -1 return -1

View File

@ -80,7 +80,11 @@ export class ActionManager {
type: ActionManager.ATTACK, type: ActionManager.ATTACK,
cost: ActionManager.REGULAR, cost: ActionManager.REGULAR,
source: ActionManager.DEFAULT, source: ActionManager.DEFAULT,
eval: (options) => this.#hatWaffeinHand(options) activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => this.#hatWaffeinHand(options),
}, },
{ {
name: "Fernkampfangriff", name: "Fernkampfangriff",
@ -89,6 +93,8 @@ export class ActionManager {
source: ActionManager.DEFAULT, source: ActionManager.DEFAULT,
cooldown: (options) => 1, cooldown: (options) => 1,
activate: (queue, data) => { activate: (queue, data) => {
data.actor.rollAttack(data)
return true
}, },
eval: (options) => this.#hatFernkampfWaffeinHand(options), eval: (options) => this.#hatFernkampfWaffeinHand(options),
}, },
@ -98,6 +104,10 @@ export class ActionManager {
cost: ActionManager.CONTINUING, cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT, source: ActionManager.DEFAULT,
cooldown: (options) => options.mod, cooldown: (options) => options.mod,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => { eval: (options) => {
const step1 = this.#hatFernkampfWaffeinHand(options) const step1 = this.#hatFernkampfWaffeinHand(options)
const step2 = !this.#hatSonderfertigkeit("Scharfschütze", options) const step2 = !this.#hatSonderfertigkeit("Scharfschütze", options)
@ -117,6 +127,7 @@ export class ActionManager {
source: ActionManager.SF, source: ActionManager.SF,
cooldown: (options) => options.mod - 2, cooldown: (options) => options.mod - 2,
activate: (queue, data) => { activate: (queue, data) => {
console.log(queue, data)
data.actor.rollAttack(data) data.actor.rollAttack(data)
return true return true
}, },
@ -211,6 +222,10 @@ export class ActionManager {
source: ActionManager.SF, source: ActionManager.SF,
modDescription: "verringert PA des Ziels um {}", modDescription: "verringert PA des Ziels um {}",
mod: (value) => value, mod: (value) => value,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => { eval: (options) => {
const step1 = this.#hatWaffeinHand(options) && this.#hatSonderfertigkeit("Finte", options) const step1 = this.#hatWaffeinHand(options) && this.#hatSonderfertigkeit("Finte", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Finte", options) const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Finte", options)
@ -227,6 +242,10 @@ export class ActionManager {
source: ActionManager.DEFAULT, source: ActionManager.DEFAULT,
modDescription: "erhöht TP vom Angriff um {}", modDescription: "erhöht TP vom Angriff um {}",
mod: (value) => -(value * 2), mod: (value) => -(value * 2),
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => { eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand(options) const step1 = !this.#hatFernkampfWaffeinHand(options)
const step2 = !this.#hatSonderfertigkeit("Wuchtschlag", options) const step2 = !this.#hatSonderfertigkeit("Wuchtschlag", options)
@ -244,6 +263,10 @@ export class ActionManager {
source: ActionManager.SF, source: ActionManager.SF,
modDescription: "erhöht TP vom Angriff um {}", modDescription: "erhöht TP vom Angriff um {}",
mod: (value) => -(value), mod: (value) => -(value),
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => { eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand(options) && this.#hatSonderfertigkeit("Wuchtschlag", options) const step1 = !this.#hatFernkampfWaffeinHand(options) && this.#hatSonderfertigkeit("Wuchtschlag", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Wuchtschlag", options) const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Wuchtschlag", options)
@ -258,6 +281,10 @@ export class ActionManager {
type: ActionManager.ATTACK, type: ActionManager.ATTACK,
cost: ActionManager.REGULAR, cost: ActionManager.REGULAR,
source: ActionManager.SF, source: ActionManager.SF,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => { eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand(options) && this.#hatSonderfertigkeit("Betäubungsschlag", options) const step1 = !this.#hatFernkampfWaffeinHand(options) && this.#hatSonderfertigkeit("Betäubungsschlag", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Betäubungsschlag", options) const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Betäubungsschlag", options)

View File

@ -146,7 +146,7 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
cooldowns.push(cooldown) cooldowns.push(cooldown)
this.document.update({"system.cooldowns": cooldowns.sort((a, b) => a.current - b.current)}) this.document.update({"system.cooldowns": cooldowns.sort((a, b) => a.current - b.current)})
ui.notifications.info(`Abklingzeit von ${cooldown.data.maneuver.name} um 1 Aktion reduziert`) ui.notifications.info(`Abklingzeit von ${cooldown.data.title} um 1 Aktion reduziert`)
} }
static async #cancelCooldown(event, target) { static async #cancelCooldown(event, target) {
@ -167,17 +167,18 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
if (cooldown && cooldown.current <= 0) { if (cooldown && cooldown.current <= 0) {
const am = new ActionManager(this.document) const am = new ActionManager(this.document)
const action = am.evaluate().find(action => action.name === cooldown.data.maneuver.id) console.log(cooldown.data.maneuver)
const action = new Function(`return ${cooldown.data.maneuver}`)
if (action) { if (action) {
action.activate(cooldowns, {...cooldown.data, actor: this.document}) action()(this.document.system.cooldowns, {...cooldown.data, actor: this.document})
} }
} }
cooldowns.splice(cooldownId, 1) cooldowns.splice(cooldownId, 1)
this.document.update({"system.cooldowns": cooldowns.sort((a, b) => a.current - b.current)}) this.document.update({"system.cooldowns": cooldowns.sort((a, b) => a.current - b.current)})
ui.notifications.info(`${cooldown.data.maneuver.name} ausgeführt`) ui.notifications.info(`${cooldown.data.title} ausgeführt`)
} }
/** /**
@ -426,11 +427,20 @@ class CharacterSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
context.cooldowns = actorData.system.cooldowns ?? [] context.cooldowns = actorData.system.cooldowns ?? []
context.cooldowns.forEach(cooldown => { context.cooldowns.forEach(cooldown => {
const weapon = this.document.itemTypes["Equipment"].find(p => p._id === cooldown.data.weapon) let weapon = null
const skill = this.document.itemTypes["Skill"].find(p => p._id === cooldown.data.skillId) let target = null
const target = game.actors.get(game.scenes.current.tokens.find(p => p._id === cooldown.data.target).actorId) let tooltip = cooldown.data.title
if (cooldown.data.weapon) {
weapon = this.document.itemTypes["Equipment"].find(p => p._id === cooldown.data.weapon)
tooltip += `<br/>Waffe:${weapon.name}`
}
if (cooldown.data.target) {
target = game.actors.get(game.scenes.current.tokens.find(p => p._id === cooldown.data.target).actorId)
tooltip += `<br/>Waffe:${target.name}`
}
cooldown.title = cooldown.data.title
cooldown.progress = ((cooldown.current / cooldown.start) * 100) + "%" cooldown.progress = ((cooldown.current / cooldown.start) * 100) + "%"
cooldown.tooltip = `${cooldown.data.maneuver.name}<br/>Waffe:${weapon.name}<br/>Ziel: ${target.name}<br/>Wurfziel: ${cooldown.data.targetNumber}<br/>Aktionen verbleibend: ${cooldown.current}` cooldown.tooltip = tooltip + `<br/>Aktionen verbleibend: ${cooldown.current}`
}) })
context.hasSpells = actorData.itemTypes["Spell"].length > 0 context.hasSpells = actorData.itemTypes["Spell"].length > 0

View File

@ -1,13 +1,13 @@
$nachteil-color: #555753ff; $nachteil-color: #555753;
$nachteil-text-color: #FFFF; $nachteil-text-color: #FFF;
$liturgie-color: #edd400ff; $liturgie-color: #edd400;
$liturgie-text-color: #000F; $liturgie-text-color: #000;
$zauber-color: #3465a4ff; $zauber-color: #3465a4;
$zauber-text-color: #000F; $zauber-text-color: #000;
$talent-color: #f57900ff; $talent-color: #f57900;
$talent-text-color: #000F; $talent-text-color: #000;
$kampftalent-color: #cc0000ff; $kampftalent-color: #cc0000;
$kampftalent-text-color: #FFFF; $kampftalent-text-color: #FFF;
$talent-body-color: #16bd6c; $talent-body-color: #16bd6c;
$talent-body-text-color: #000; $talent-body-text-color: #000;
@ -79,3 +79,5 @@ $default-action-color: #000;
$special-action: rgba(68, 34, 204, 0.8); $special-action: rgba(68, 34, 204, 0.8);
$special-action-color: #000; $special-action-color: #000;

View File

@ -1,3 +1,6 @@
@use "../atoms/colours" as colors;
@use "sass:color";
.dsa41.sheet.actor.character { .dsa41.sheet.actor.character {
.head-data { .head-data {
@ -234,6 +237,23 @@
background-color: rgba(0, 0, 0, 0.8); background-color: rgba(0, 0, 0, 0.8);
} }
&.Kampf .progress::after {
background-color: rgba(colors.$kampftalent-color, 0.5);
}
&.Karmal .progress::after {
background-color: rgba(colors.$liturgie-color, 0.5);
}
&.Magisch .progress::after {
background-color: rgba(colors.$zauber-color, 0.5);
}
&.Talent .progress::after {
background-color: rgba(colors.$talent-color, 0.5);
}
} }
} }

View File

@ -2,7 +2,7 @@
"id": "DSA_4-1", "id": "DSA_4-1",
"title": "Das Schwarze Auge 4.1", "title": "Das Schwarze Auge 4.1",
"description": "Noch ein Spielsystem für Das Schwarze Auge 4.1", "description": "Noch ein Spielsystem für Das Schwarze Auge 4.1",
"version": "0.3.3", "version": "0.0.1",
"compatibility": { "compatibility": {
"minimum": 12, "minimum": 12,
"verified": 13 "verified": 13
@ -348,5 +348,5 @@
"primaryTokenAttribute": "lep.aktuell", "primaryTokenAttribute": "lep.aktuell",
"url": "https://git.macniel.online/macniel/foundry-dsa41-game", "url": "https://git.macniel.online/macniel/foundry-dsa41-game",
"manifest": "https://git.macniel.online/macniel/foundry-dsa41-game/raw/branch/main/src/system.json", "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.3.3/release.zip" "download": "https://git.macniel.online/macniel/foundry-dsa41-game/releases/download/0.0.1/release.zip"
} }

View File

@ -91,13 +91,13 @@
<section class="cooldowns"> <section class="cooldowns">
<h3>Abklingzeiten</h3> <h3>Abklingzeiten</h3>
{{#each this.cooldowns}} {{#each this.cooldowns}}
<div class="cooldown"> <div class="cooldown{{#if this.data.cssClass}} {{this.data.cssClass}}{{/if}}">
<div class="progress" style="width: {{this.progress}}"></div> <div class="progress" style="width: {{this.progress}}"></div>
{{#if (gt this.current 0)}} {{#if (gt this.current 0)}}
<button class="btn-left" data-action="progressCooldown" data-cooldown-id="{{@key}}"> <button class="btn-left" data-action="progressCooldown" data-cooldown-id="{{@key}}">
<i class="fa fa-timer"></i> <i class="fa fa-timer"></i>
</button> </button>
<span data-tooltip="{{this.tooltip}}">{{this.data.maneuver.name}}</span> <span data-tooltip="{{this.tooltip}}">{{this.title}}</span>
<button class="btn-right" data-action="cancelCooldown" data-cooldown-id="{{@key}}"> <button class="btn-right" data-action="cancelCooldown" data-cooldown-id="{{@key}}">
<i class="fa fa-xmark"></i> <i class="fa fa-xmark"></i>
</button> </button>
@ -105,7 +105,7 @@
<button class="btn-left" data-action="activateCooldown" data-cooldown-id="{{@key}}"> <button class="btn-left" data-action="activateCooldown" data-cooldown-id="{{@key}}">
<i class="fa fa-person-running"></i> <i class="fa fa-person-running"></i>
</button> </button>
<span data-tooltip="{{this.tooltip}}">{{this.data.maneuver.name}}</span> <span data-tooltip="{{this.tooltip}}">{{this.title}}</span>
<button class="btn-right" data-action="cancelCooldown" data-cooldown-id="{{@key}}"> <button class="btn-right" data-action="cancelCooldown" data-cooldown-id="{{@key}}">
<i class="fa fa-xmark"></i> <i class="fa fa-xmark"></i>
</button> </button>