foundry-dsa41-game/src/module/sheets/actions/action-manager.mjs

457 lines
17 KiB
JavaScript

export class ActionManager {
static FREE = "free-action";
static REGULAR = "regular-action";
static CONTINUING = "continuing-action";
static MOVEMENT = "movement-action"
static DEFENSE = "defense-action"
static ATTACK = "attack-action"
static INTERACTION = "interaction";
static TALENT = "talent-action"
static SPELL = "spell";
static DEFAULT = "default"
static SF = "special-ability"
constructor(actor) {
this.actor = actor
}
#freeActions = [
{
name: "Ausweichen",
cost: ActionManager.FREE,
type: ActionManager.DEFENSE,
source: ActionManager.DEFAULT,
eval: (options) => {
if (options?.weapon && options.weapon === "Ausweichen") {
return true
}
return false
}
},
{
name: "Rufen",
cost: ActionManager.FREE,
type: ActionManager.INTERACTION,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Sich zu Boden fallen lassen",
cost: ActionManager.FREE,
type: ActionManager.MOVEMENT,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Waffe oder Gegenstand fallen lassen",
cost: ActionManager.FREE,
type: ActionManager.INTERACTION,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "getragenes Artefakt aktivieren",
cost: ActionManager.FREE,
type: ActionManager.INTERACTION,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Schnellziehen",
cost: ActionManager.FREE,
type: ActionManager.INTERACTION,
source: ActionManager.SF,
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
},
}
]
#regularActions = [
{
name: "Nahkampfangriff",
type: ActionManager.ATTACK,
cost: ActionManager.REGULAR,
source: ActionManager.DEFAULT,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => this.#hatWaffeinHand(options),
},
{
name: "Fernkampfangriff",
type: ActionManager.ATTACK,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
cooldown: (options) => 1,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => this.#hatFernkampfWaffeinHand(options),
},
{
name: "Angesagter Fernkampfangriff", // wird durch Scharfer Schuss aus SF ersetzt
type: ActionManager.ATTACK,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
cooldown: (options) => options.mod,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => {
const step1 = this.#hatFernkampfWaffeinHand(options)
const step2 = !this.#hatSonderfertigkeit("Scharfschütze", options)
const step3 = this.#hatSonderfertigkeit("Scharfschütze", options) && !this.#evalSonderfertigkeitRequirements("Scharfschütze", options)
if (step1 && (step2 || step3)) {
return true
} else
return false
},
modDescription: "erhöht TP vom Angriff um {}",
mod: (value) => -value * 2
},
{
name: "Scharfer Schuss",
type: ActionManager.ATTACK,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
cooldown: (options) => options.mod - 2,
activate: (queue, data) => {
console.log(queue, data)
data.actor.rollAttack(data)
return true
},
eval: (options) => {
const step1 = this.#hatFernkampfWaffeinHand(options) && this.#hatSonderfertigkeit("Scharfschütze", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Scharfschütze", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
},
modDescription: "erhöht TP vom Angriff um {}",
mod: (value) => -value
},
{
name: "Schnellschuss",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
cooldown: (options) => 1,
activate: (queue) => {
// get earliest rangedAttack and reduce its cooldown by 1 but also increases its difficulty by 2
return true
},
eval: (options) => this.#hatFernkampfWaffeinHand(options)
},
{
name: "Schnellschuss (Scharfschütze)",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
cooldown: (options) => 1,
activate: (queue) => {
// get earliest rangedAttack and reduce its cooldown by 1 but also increases its difficulty by 1
return true
},
eval: (options) => {
const step1 = this.#hatFernkampfWaffeinHand(options) && this.#hatSonderfertigkeit("Scharfschütze", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Scharfschütze", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Parade",
type: ActionManager.DEFENSE,
cost: ActionManager.REGULAR,
source: ActionManager.DEFAULT,
eval: (options) => {
if (options?.weapon && options.weapon !== "Ausweichen") {
return true
}
return false
}
},
{
name: "Meisterparade",
type: ActionManager.DEFENSE,
cost: ActionManager.REGULAR,
source: ActionManager.SF,
modDescription: "erschwert nächste AT vom Ziel um {}",
mod: (value) => -value,
eval: (options) => {
const step1 = this.#hatWaffeinHand(options) && this.#hatSonderfertigkeit("Meisterparade", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Meisterparade", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Bewegen",
type: ActionManager.MOVEMENT,
cost: ActionManager.REGULAR,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Position",
type: ActionManager.MOVEMENT,
cost: ActionManager.REGULAR,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Finte",
type: ActionManager.ATTACK,
cost: ActionManager.REGULAR,
source: ActionManager.SF,
modDescription: "verringert PA des Ziels um {}",
mod: (value) => value,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => {
const step1 = this.#hatWaffeinHand(options) && this.#hatSonderfertigkeit("Finte", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Finte", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
},
{
name: "Wuchtschlag", // wird durch Wuchtschlag aus SF ersetzt
type: ActionManager.ATTACK,
cost: ActionManager.REGULAR,
source: ActionManager.DEFAULT,
modDescription: "erhöht TP vom Angriff um {}",
mod: (value) => -(value * 2),
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand(options)
const step2 = !this.#hatSonderfertigkeit("Wuchtschlag", options)
const step3 = this.#hatSonderfertigkeit("Wuchtschlag", options) && !this.#evalSonderfertigkeitRequirements("Wuchtschlag", options)
if (step1 && (step2 || step3)) {
return true
} else
return false
}
},
{
name: "Wuchtschlag (Sonderfertigkeit)",
type: ActionManager.ATTACK,
cost: ActionManager.REGULAR,
source: ActionManager.SF,
modDescription: "erhöht TP vom Angriff um {}",
mod: (value) => -(value),
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand(options) && 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,
activate: (queue, data) => {
data.actor.rollAttack(data)
return true
},
eval: (options) => {
const step1 = !this.#hatFernkampfWaffeinHand(options) && this.#hatSonderfertigkeit("Betäubungsschlag", options)
const step2WithBenefits = this.#evalSonderfertigkeitRequirements("Betäubungsschlag", options)
if (step1 && step2WithBenefits ? step2WithBenefits.passes : false) {
return step2WithBenefits
} else
return false
}
}
]
#continuingActions = [
{
name: "Orientieren",
type: ActionManager.TALENT,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Waffe ziehen",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Sprinten",
type: ActionManager.MOVEMENT,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Gegenstand benutzen",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Schnellladen (Bogen)",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
cooldown: (options) => 1,
activate: (queue) => { // find earliest Reload Action and reduce it by 1
return true
},
eval: (options) => {
const step1 = this.#hatMunition()
&& this.#hatFernkampfWaffeinHand(options)
&& this.#hatSonderfertigkeit("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,
cooldown: (options) => 1,
activate: (queue) => {
return true // find earliest Reload Action and reduce it by 1
},
eval: (options) => {
const step1 = this.#hatMunition()
&& this.#hatFernkampfWaffeinHand(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",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
cooldown: (options) => 1, // get reload time of weapon
activate: (queue) => {
return true // get ammunition of actor and reduce the Qty by 1 or if its as magazine, reduce its fill by 1
},
eval: (options) => this.#hatMunition()
},
{
name: "Talenteinsatz",
type: ActionManager.TALENT,
cost: ActionManager.CONTINUING,
source: ActionManager.DEFAULT,
eval: (options) => true
},
{
name: "Zaubern",
type: ActionManager.SPELL,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: (options) => this.#hatSonderfertigkeitBeginnendMit("Repräsentation:", options)
},
{
name: "Liturgie wirken",
type: ActionManager.SPELL,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: (options) => this.#hatSonderfertigkeitBeginnendMit("Liturgiekenntnis", options)
}
]
#hatWaffeinHand(options) {
if (options) {
const item = this.actor.findEquipmentOnSlot("links") ?? this.actor.findEquipmentOnSlot("rechts")
return item == options.weapon
} else {
return this.actor.findEquipmentOnSlot("links") != null || this.actor.findEquipmentOnSlot("rechts") != null
}
}
#hatMunition() {
const item = this.actor.findEquipmentOnSlot("munition")
return item != null
}
#hatFernkampfWaffeinHand(options) {
if (options) {
const item = this.actor.findEquipmentOnSlot("fernkampf")
return item == options.weapon
} else {
return this.actor.findEquipmentOnSlot("fernkampf") != null
}
}
#hatSonderfertigkeitBeginnendMit(name, options) {
return this.actor.itemTypes["SpecialAbility"]?.find(p => p.name.startsWith(name)) != null
}
#hatSonderfertigkeit(name, options) {
return this.actor.itemTypes["SpecialAbility"]?.find(p => p.name === name) != null
}
#evalSonderfertigkeitRequirements(nameOfSF, options) {
const sf = this.actor.itemTypes["SpecialAbility"].find(p => p.name === nameOfSF)
return sf?.system.isActive(options) ?? false
}
/**
*
* @param {{target: String?}} options
*/
evaluate(options) {
let actionArray = [...this.#freeActions, ...this.#regularActions, ...this.#continuingActions]
return actionArray.filter(action => {
return action.eval(options)
}).map(action => {
return {
...action,
eval: action.eval(options)
}
})
}
}