350 lines
11 KiB
JavaScript
350 lines
11 KiB
JavaScript
const {
|
|
ApplicationV2,
|
|
HandlebarsApplicationMixin
|
|
} = foundry.applications.api
|
|
|
|
export class RestingDialog extends HandlebarsApplicationMixin(ApplicationV2) {
|
|
|
|
static DEFAULT_OPTIONS = {
|
|
classes: ['dsa41', 'dialog', 'resting'],
|
|
tag: "form",
|
|
position: {
|
|
width: 480,
|
|
height: 800
|
|
},
|
|
window: {
|
|
resizable: false,
|
|
title: "Rasten und Regenerieren"
|
|
},
|
|
form: {
|
|
submitOnChange: true,
|
|
closeOnSubmit: false,
|
|
handler: RestingDialog.#onSubmitForm
|
|
},
|
|
actions: {
|
|
regenerate: RestingDialog.#regenerate
|
|
}
|
|
}
|
|
|
|
static PARTS = {
|
|
form: {
|
|
template: 'systems/DSA_4-1/templates/dialog/resting-dialog.hbs',
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @type {Actor}
|
|
* @private
|
|
*/
|
|
_actor = null
|
|
|
|
/**
|
|
* @typedef RestingCircumstance
|
|
* @property {String} name Displaytext of this circumstance modifier
|
|
* @property {Number|[Number]} aspMod modifier to AsP regeneration
|
|
* @property {Number|[Number]} lepMod modifier to LeP regeneration
|
|
* @property {Boolean|Number} active indicates if this modifier is active and or which index of aspMod/lepMod to be used
|
|
*/
|
|
|
|
/**
|
|
* @typedef RestingOptions
|
|
* @property {Number} length the time of this rest, will be used for reducing exhaustion and overexertion
|
|
* @property {Number} wounds the amount of wounds the actor has suffered
|
|
* @property {Number|Boolean} treated if the wounds have been treated with the Skill "Heilkunde: Wunden" the Value is the Modificator for the wound regeneration
|
|
* @property {RestingCircumstance} circumstances the circumstances of this Rest
|
|
*/
|
|
|
|
#type = {
|
|
DRAUßEN: "draußen",
|
|
SCHLAFSAAL: "schlafsaal",
|
|
EINZELZIMMER: "einzelzimmer",
|
|
SUITE: "suite",
|
|
}
|
|
|
|
/**
|
|
* @type {[RestingCircumstance]}
|
|
* @private
|
|
*/
|
|
#circumstances = [
|
|
{
|
|
name: "Ruhestörung",
|
|
display: "boolean",
|
|
lepMod: -1,
|
|
aspMod: -1,
|
|
group: "interrupted",
|
|
active: false,
|
|
value: "on"
|
|
},
|
|
{
|
|
name: "Wache gehalten",
|
|
display: "boolean",
|
|
lepMod: -1,
|
|
aspMod: -1,
|
|
group: "watch",
|
|
active: false,
|
|
value: "on"
|
|
},
|
|
{
|
|
name: "Unter freiem Himmel",
|
|
display: "radio",
|
|
aspMod: 0,
|
|
lepMod: 0,
|
|
active: false,
|
|
value: this.#type.DRAUßEN,
|
|
group: "type"
|
|
},
|
|
{
|
|
name: "Schlechtes Wetter",
|
|
aspMod: [-1, -2, -3, -4, -5],
|
|
lepMod: [-1, -2, -3, -4, -5],
|
|
display: "range",
|
|
noLabel: "Gutes Wetter",
|
|
labels: [
|
|
"Schlechtes Wetter I",
|
|
"Schlechtes Wetter II",
|
|
"Schlechtes Wetter III",
|
|
"Schlechtes Wetter IV",
|
|
"Schlechtes Wetter V",
|
|
],
|
|
group: "bad_weather",
|
|
active: -1,
|
|
},
|
|
{
|
|
name: "Schlechter Lagerplatz",
|
|
aspMod: -1,
|
|
lepMod: -1,
|
|
display: "boolean",
|
|
group: "bad_camp",
|
|
active: false,
|
|
value: "on"
|
|
},
|
|
{
|
|
name: "Magere Lagerstätte (Schlafsaal, Heuboden)",
|
|
aspMod: 0,
|
|
lepMod: 0,
|
|
display: "radio",
|
|
group: "type",
|
|
value: this.#type.SCHLAFSAAL,
|
|
active: false,
|
|
},
|
|
{
|
|
name: "Komfortable Schlafstätte",
|
|
aspMod: 1,
|
|
lepMod: 1,
|
|
display: "radio",
|
|
group: "type",
|
|
value: this.#type.EINZELZIMMER,
|
|
active: false,
|
|
},
|
|
{
|
|
name: "Luxuriöse Schlafstätte (Suite)",
|
|
aspMod: 2,
|
|
lepMod: 2,
|
|
display: "radio",
|
|
group: "type",
|
|
value: this.#type.SUITE,
|
|
active: false,
|
|
}
|
|
|
|
]
|
|
|
|
|
|
constructor(actor) {
|
|
super();
|
|
this._actor = actor;
|
|
this.restDuration = 6
|
|
this.restingType = this.#circumstances.find(p => p.value === this.#type.DRAUßEN)
|
|
this.badWeather = -1
|
|
this.woundTreated = false
|
|
this.woundRegenerationModifier = 0
|
|
this.wounds = 1
|
|
this.badCamp = false
|
|
this.watch = false
|
|
this.interrupted = false
|
|
|
|
this.lepModifier = this._actor.system.regeneration.lep.split("d6")[1]
|
|
this.aspModifier = this._actor.system.regeneration.asp.split("d6")[1]
|
|
|
|
|
|
this.regKoMod = this._actor.system.regeneration.ko
|
|
this.regInMod = this._actor.system.regeneration.in
|
|
|
|
|
|
}
|
|
|
|
static async #regenerate() {
|
|
const context = this.#updateData()
|
|
const rollData = this._actor.getRollData()
|
|
|
|
// regenerate LeP
|
|
|
|
const targetBonusLep = rollData.attribute.ko.aktuell + context.koRoll
|
|
const targetBonusAsp = rollData.attribute.in.aktuell + context.inRoll
|
|
|
|
const regenerationRoll = await new Roll("1d20[Konstitution]+1d20[Intuition]+1d20[Konstitution] + 2d6").evaluate()
|
|
|
|
const [koRoll, _, inRoll, __, woundRoll, ___, lepAndAsp] = regenerationRoll.terms // the 3d20s
|
|
const plusLep = koRoll.results[0].result <= targetBonusLep ? 1 : 0
|
|
const plusAsp = inRoll.results[0].result <= targetBonusAsp ? 1 : 0
|
|
const woundHealed = woundRoll.results[0].result <= rollData.attribute.ko.aktuell + (context.woundMod * -1)
|
|
const [regLep, regAsp] = lepAndAsp.results // the 2d6s
|
|
|
|
await regenerationRoll.toMessage({
|
|
speaker: ChatMessage.getSpeaker({actor: this.actor}),
|
|
flavor:
|
|
`Regeneration in der Nacht:<br/>
|
|
LE: ${regLep.result} ${context.lepMod > 0 ? ("+" + context.lepMod) : ""} ${plusLep > 0 ? "+1" : ""}<br/>
|
|
AE: ${regAsp.result} ${context.aspMod > 0 ? ("+" + context.aspMod) : ""} ${plusAsp > 0 ? "+1" : ""}<br/>
|
|
Wunde: ${woundHealed ? "geheilt" : "nicht geheilt"}`,
|
|
rollMode: game.settings.get('core', 'rollMode'),
|
|
})
|
|
this.close()
|
|
}
|
|
|
|
static async #onSubmitForm(event, form, formData) {
|
|
event.preventDefault()
|
|
this.restDuration = formData.object.length
|
|
this.restingType = formData.object.type
|
|
this.badWeather = formData.object.bad_weather
|
|
this.woundTreated = formData.object.wound_treated
|
|
this.woundRegenerationModifier = formData.object.wound_treat_modifier
|
|
this.wounds = formData.object.wounds
|
|
this.badCamp = formData.object.bad_camp === "on"
|
|
this.watch = formData.object.watch === "on"
|
|
this.interrupted = formData.object.interrupted === "on"
|
|
|
|
|
|
const elementLepMod = this.element.querySelector('output[name="lepMod"]')
|
|
const elementKoMod = this.element.querySelector('output[name="koMod"]')
|
|
const elementAspMod = this.element.querySelector('output[name="aspMod"]')
|
|
const elementInMod = this.element.querySelector('output[name="inMod"]')
|
|
const elementWoundMod = this.element.querySelector('output[name="woundMod"]')
|
|
|
|
const context = this.#updateData()
|
|
elementLepMod.value = context.lepModDisplay
|
|
elementKoMod.value = context.koRollDisplay
|
|
elementAspMod.value = context.aspModDisplay
|
|
elementInMod.value = context.inRollDisplay
|
|
elementWoundMod.value = context.woundModDisplay
|
|
}
|
|
|
|
#updateData(context = {}) {
|
|
context.circumstances = this.#circumstances
|
|
context.actorId = this._actor._id
|
|
context.hasWounds = true
|
|
context.hasAsP = true
|
|
context.wounds = this.wounds
|
|
|
|
// TODO count wounds
|
|
|
|
let lepRestModifier = 0
|
|
let aspRestModifier = 0
|
|
|
|
if (this.restingType) {
|
|
const circ = this.#circumstances.find(p => p.value === this.restingType)
|
|
if (circ) {
|
|
lepRestModifier += Number(circ.lepMod)
|
|
aspRestModifier += Number(circ.aspMod)
|
|
}
|
|
}
|
|
|
|
if (this.restingType === this.#type.DRAUßEN && this.badWeather !== -1) {
|
|
const circ = this.#circumstances.find(p => p.group === "bad_weather")
|
|
if (circ) {
|
|
|
|
if (circ["lepMod"][this.badWeather] !== 0) {
|
|
lepRestModifier += circ["lepMod"][this.badWeather]
|
|
}
|
|
|
|
if (circ["aspMod"][this.badWeather] !== 0) {
|
|
aspRestModifier += circ["aspMod"][this.badWeather]
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (this.woundTreated) {
|
|
context.woundModDisplay = `1w20-${this.woundRegenerationModifier ?? 0}`
|
|
context.woundMod = this.woundRegenerationModifier ?? 0
|
|
} else {
|
|
if (context.hasWounds) {
|
|
context.woundModDisplay = `1w20+${context.wounds * 3}`
|
|
context.woundMod = context.wounds * 3
|
|
}
|
|
}
|
|
|
|
if (this.restingType === this.#type.DRAUßEN && this.badCamp) {
|
|
const circ = this.#circumstances.find(p => p.group === "bad_camp")
|
|
if (circ) {
|
|
lepRestModifier += Number(circ.lepMod)
|
|
aspRestModifier += Number(circ.aspMod)
|
|
}
|
|
}
|
|
|
|
if (this.watch) {
|
|
const circ = this.#circumstances.find(p => p.group === "watch")
|
|
if (circ) {
|
|
lepRestModifier += Number(circ.lepMod)
|
|
aspRestModifier += Number(circ.aspMod)
|
|
}
|
|
}
|
|
|
|
if (this.interrupted) {
|
|
const circ = this.#circumstances.find(p => p.group === "interrupted")
|
|
if (circ) {
|
|
lepRestModifier += Number(circ.lepMod)
|
|
aspRestModifier += Number(circ.aspMod)
|
|
}
|
|
}
|
|
|
|
const lepMod = (Number(this.lepModifier) + (lepRestModifier)) ?? 0
|
|
const aspMod = (Number(this.aspModifier) + (aspRestModifier)) ?? 0
|
|
|
|
context.lepMod = lepMod
|
|
|
|
if (lepMod == 0) {
|
|
context.lepModDisplay = "1w6"
|
|
} else if (lepMod > 0) {
|
|
context.lepModDisplay = "1w6+" + lepMod
|
|
} else {
|
|
context.lepModDisplay = "1w6" + lepMod
|
|
}
|
|
|
|
context.aspMod = aspMod
|
|
if (aspMod == 0) {
|
|
context.aspModDisplay = "1w6"
|
|
} else if (lepMod > 0) {
|
|
context.aspModDisplay = "1w6+" + aspMod
|
|
} else {
|
|
context.aspModDisplay = "1w6" + aspMod
|
|
|
|
}
|
|
|
|
context.koRoll = this.regKoMod
|
|
if (this.regKoMod < 0) {
|
|
context.koRollDisplay = `1w20${this.regKoMod}`
|
|
} else {
|
|
context.koRollDisplay = `1w20+${this.regKoMod}`
|
|
}
|
|
|
|
context.inRoll = this.regInMod
|
|
if (this.regInMod < 0) {
|
|
context.inRollDisplay = `1w20${this.regInMod}`
|
|
} else {
|
|
context.inRollDisplay = `1w20+${this.regInMod}`
|
|
}
|
|
|
|
console.log(this, context)
|
|
|
|
return context
|
|
}
|
|
|
|
async _prepareContext(options) {
|
|
const context = await super._prepareContext(options)
|
|
return this.#updateData(context)
|
|
}
|
|
|
|
_onRender(context, options) {
|
|
|
|
}
|
|
} |