finalises dialog

pull/61/head
macniel 2025-10-22 16:42:07 +02:00
parent 10d05683ad
commit 2b22a8fa6f
5 changed files with 157 additions and 65 deletions

View File

@ -71,11 +71,11 @@ export class SpecialAbilityDataModel extends BaseItem {
}
}
isActive(options) { // TODO also handle Waffenlimit
isActive(options) {
const requirements = this.#getRequirements()
let passes = false
let passes = true
let mod = 0
const flatActor = foundry.utils.flattenObject(this.parent.actor.system)
@ -89,13 +89,18 @@ export class SpecialAbilityDataModel extends BaseItem {
if (requirement.talent) {
targetField = this.parent.actor.itemTypes["Skill"].find(p => p.name.toLocaleLowerCase() === requirement.talent.toLocaleLowerCase()).taw
}
if (requirement.minValue) {
passes = targetField >= requirement.minValue
} else if (requirement.maxValue) {
passes = targetField <= requirement.maxValue
passes = requirement.minValue <= targetField
if (!passes) console.log(`fails requirement ${requirement.attribute ?? requirement.talent} (${requirement.minValue} <= ${targetField})`)
}
if (requirement.maxValue) {
passes = targetField <= requirement.maxValue
if (!passes) console.log(`fails requirement ${requirement.attribute ?? requirement.talent} (${targetField} <= ${requirement.maxValue})`)
}
if (requirement.sonderfertigkeit) {
passes = this.parent.actor.itemTypes["SpecialAbility"].find(p => p.name === requirement.sonderfertigkeit) != undefined
if (!passes) console.log(`fails requirement ${requirement.sonderfertigkeit} (not in possession)`)
}
if (requirement["compare"]) {
const {ownAttribute, operation, targetAttribute} = requirement["compare"]
if (options.target) {
@ -122,29 +127,39 @@ export class SpecialAbilityDataModel extends BaseItem {
passes = ourTargetField > foreignTargetField;
break;
}
if (!passes) {
console.log(`fails compare requirement ${ownAttribute} ${operation} ${targetAttribute}`)
}
} else {
console.log(`fails compare requirement as no target has been selected`)
return false // cant pass as we dont have a target
}
passes = false
}
if (!passes) {
console.log("fails atleast 1 requirement of ", this)
break
}
}
if (passes) { // TODO: how are we going to communicate the malus?
this.system.waffenLimit.forEach(waff => {
if (waff.waffe) {
passes = options.weapon.name === waff.waffe
if (waff.mod) mod = waff.mod
} else if (waff.gruppe) {
passes = options.skill.name === waff.gruppe
if (waff.mod) mod = waff.mod
console.log(this.name, "requirements", passes)
if (passes) {
if (options?.weapon) {
for (const waff of this.waffenLimit) {
if (waff.waffe) {
passes = options?.weapon.name === waff.waffe ?? false
if (waff.mod) mod = waff.mod
if (passes)
break
}
if (waff.gruppe) {
passes = options?.skill.name === waff.gruppe ?? false
if (waff.mod) mod = waff.mod
if (passes)
break
}
}
})
}
}
console.log("return value", {passes, mod})
return {passes, mod}
}
}

View File

@ -18,8 +18,8 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
classes: ['dsa41', 'dialog', 'combat'],
tag: "form",
position: {
width: 320,
height: 540
width: 480,
height: 640
},
window: {
resizable: false,
@ -114,7 +114,6 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
const tokenId = this._actor.getActiveTokens()[0].id
const thisTokenRepresentative = tokens.get(tokenId)
/**
*
* @type {[TokenDistance]}
@ -124,7 +123,7 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
isSelected: this._targetId === token.id,
...this.#getDistanceBetween(thisTokenRepresentative, token)
}
})
}).sort((a, b) => a.d - b.d).sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1))
}
#evaluateWeapons() {
@ -178,7 +177,7 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
}
})
this._weapons = weapons
this._weapons = weapons.sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1))
return this._weapons
}
@ -200,9 +199,10 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
type: action.type,
source: action.source,
cost: action.cost,
penalty: action.eval?.mod ?? 0,
mod: action.mod,
}
})
}).sort((a, b) => (a.isSelected ? 0 : 1) - (b.isSelected ? 0 : 1))
return this._maneuvers
}
@ -237,16 +237,25 @@ export class CombatActionDialog extends HandlebarsApplicationMixin(ApplicationV2
}
_onRender(context, options) {
#update(context) {
const target = this.element.querySelector(".actions button .value")
this.element.querySelectorAll('[name="mod"], [name="malus"]').forEach(e => e.addEventListener('change', (event) => {
const at = Number(context.targetNumber)
const malus = Number(this.element.querySelector('[name="malus"]').value)
const mod = Number(this.element.querySelector('[name="mod"]').value)
const maneuver = this._maneuvers?.find(p => p.id === this._combatManeuverId)
const result = at + (maneuver.mod?.(mod) ?? 0) + malus
const at = Number(context.targetNumber)
const maneuver = this._maneuvers?.find(p => p.id === this._combatManeuverId)
const mod = Number(this.element.querySelector('[name="mod"]').value)
const penalty = (maneuver?.penalty ?? 0) + (maneuver?.mod?.(mod) ?? 0) ?? 0
const circumstance = Number(this.element.querySelector('[name="circumstance"]').value)
this.element.querySelector('[name="penalty"]').value = penalty + circumstance
const result = (at + circumstance + penalty) ?? false
if (result) {
target.textContent = `(${result})`
}
}
_onRender(context, options) {
this.#update(context)
this.element.querySelectorAll('[name="mod"], [name="malus"], [name="circumstance"]').forEach(e => e.addEventListener('change', (event) => {
this.#update(context)
}))
}

View File

@ -58,7 +58,14 @@ export class ActionManager {
cost: ActionManager.FREE,
type: ActionManager.INTERACTION,
source: ActionManager.SF,
eval: (options) => this.#hatSonderfertigkeit("Schnellziehen", options) && this.#evalSonderfertigkeitRequirements("Schnellziehen", options)
eval: (options) => {
const step1 = this.#hatSonderfertigkeit("Schnellziehen", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Schnellziehen", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
},
}
]
@ -90,7 +97,14 @@ export class ActionManager {
type: ActionManager.ATTACK,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: (options) => this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options) && this.#evalSonderfertigkeitRequirements("Scharfschütze", options),
eval: (options) => {
const step1 = this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Scharfschütze", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
},
mod: (value) => -value
},
{
@ -105,7 +119,14 @@ export class ActionManager {
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: (options) => this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options) && this.#evalSonderfertigkeitRequirements("Scharfschütze", options)
eval: (options) => {
const step1 = this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Scharfschütze", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Abwehraktion",
@ -134,11 +155,14 @@ export class ActionManager {
cost: ActionManager.REGULAR,
source: ActionManager.SF,
mod: (value) => value,
eval: (options) =>
this.#hatWaffeinHand() &&
this.#hatSonderfertigkeit("Finte", options) &&
this.#evalSonderfertigkeitRequirements("Finte", options)
eval: (options) => {
const step1 = this.#hatWaffeinHand() && this.#hatSonderfertigkeit("Finte", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Finte", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Wuchtschlag",
@ -154,16 +178,28 @@ export class ActionManager {
cost: ActionManager.REGULAR,
source: ActionManager.SF,
mod: (value) => -(value),
eval: (options) => !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Wuchtschlag", options)
&& this.#evalSonderfertigkeitRequirements("Wuchtschlag", options)
eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Wuchtschlag", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Wuchtschlag", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Betäubungsschlag",
type: ActionManager.ATTACK,
cost: ActionManager.REGULAR,
source: ActionManager.SF,
eval: (options) => !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Betäubungsschlag", options)
&& this.#evalSonderfertigkeitRequirements("Betäubungsschlag", options)
eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Betäubungsschlag", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Betäubungsschlag", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
}
]
@ -201,20 +237,32 @@ export class ActionManager {
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: (options) => this.#hatMunition()
eval: (options) => {
const step1 = this.#hatMunition()
&& this.#hatFernkampfWaffeinHand("Bogen", options)
&& this.#hatSonderfertigkeit("Schnellladen (Bogen)", options)
&& this.#evalSonderfertigkeitRequirements("Schnellladen (Bogen)", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Schnellladen (Bogen)", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Schnellladen (Armbrust)",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: (options) => this.#hatMunition()
&& this.#hatFernkampfWaffeinHand("Armbrust", options)
&& this.#hatSonderfertigkeit("Schnellladen (Armbrust)", options)
&& this.#evalSonderfertigkeitRequirements("Schnellladen (Armbrust)", options)
eval: (options) => {
const step1 = this.#hatMunition()
&& this.#hatFernkampfWaffeinHand("Armbrust", options)
&& this.#hatSonderfertigkeit("Schnellladen (Armbrust)", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Schnellladen (Armbrust)", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Nachladen",
@ -272,7 +320,7 @@ export class ActionManager {
#evalSonderfertigkeitRequirements(nameOfSF, options) {
const sf = this.actor.itemTypes["SpecialAbility"].find(p => p.name === nameOfSF)
return sf.system.isActive(options).passes
return sf?.system.isActive(options) ?? false
}
/**
@ -282,14 +330,15 @@ export class ActionManager {
evaluate(options) {
let actionArray = [...this.#freeActions, ...this.#regularActions, ...this.#continuingActions]
console.log(this.actor, actionArray.map((action) => {
return actionArray.filter(action => {
console.log(action.name, action.eval(options))
return action.eval(options)
}).map(action => {
return {
...action,
eval: action.eval(options)
}
}))
const validActions = actionArray.filter(action => action.eval())
return validActions
})
}
}

View File

@ -17,6 +17,7 @@
display: flex;
flex-direction: column;
height: 100%;
gap: 16px 0;
fieldset {
@ -33,6 +34,10 @@
padding: 0 16px;
}
&.modding {
flex: 0;
}
}
ul {
@ -41,6 +46,10 @@
padding: 0;
margin: 0;
text-indent: 0;
overflow: hidden;
overflow-y: auto;
margin: 0 -8px;
max-height: 120px;
li {
@ -49,7 +58,7 @@
line-height: 32px;
vertical-align: middle;
grid-template-columns: 32px 1fr 83px;
grid-template-columns: 32px 1fr 90px;
grid-template-rows: 1fr;
border: 1px transparent;
margin: 8px;
@ -69,9 +78,16 @@
.malus-and-mod {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr;
gap: 0 8px;
label {
span {
text-align: center;
}
}
}
.actions {

View File

@ -37,15 +37,18 @@
</ul>
</fieldset>
<fieldset>
<fieldset class="modding">
<legend>Erschwernisse und Ansagen</legend>
<div class="malus-and-mod">
<label>Umstände
<input name="malus" type="number">
<label><span>Umstände</span>
<input name="circumstance" type="number">
</label>
<label>Ansage
<label><span>Ansage</span>
<input name="mod" type="number" {{disabled (not canMod)}}>
</label>
<label><span>Erschwernis</span>
<input name="penalty" type="number" {{disabled true}}>
</label>
</div>
</fieldset>