457 lines
17 KiB
JavaScript
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)
|
|
}
|
|
})
|
|
}
|
|
|
|
}
|