Compare commits

...

3 Commits

17 changed files with 200 additions and 46 deletions

View File

@ -1,6 +1,7 @@
import BaseItem from "./base-item.mjs";
const {
AnyField,
BooleanField,
NumberField,
SchemaField,
@ -15,14 +16,85 @@ export class SpecialAbilityDataModel extends BaseItem {
static defineSchema() {
return {
name: new StringField(),
value: new StringField(),
auswahl: new ArrayField(
new SchemaField({
name: new StringField(),
requirement: new ArrayField(
new SchemaField({
attribute: new StringField(),
minValue: new NumberField(),
maxValue: new NumberField(),
sonderfertigkeit: new StringField(),
talent: new StringField(),
})
),
mod: new ArrayField(new SchemaField({
name: new StringField(),
value: new NumberField(),
}))
}),
),
seite: new NumberField(),
aktionsText: new HTMLField(),
text: new HTMLField(),
requirements: new ObjectField(), // TODO something more meaningful with this data
requirement: new ArrayField(
new SchemaField({
attribute: new StringField(),
minValue: new NumberField(),
maxValue: new NumberField(),
sonderfertigkeit: new StringField(),
talent: new StringField(),
})
),
waffenLimit: new ArrayField(
new StringField(),
),
mod: new ArrayField(new SchemaField({
name: new StringField(),
value: new NumberField(),
})),
mehrereAktionen: new BooleanField(),
}
}
#getRequirements() {
if (this.value && this.auswahl.find(p => p.name === this.value)) {
const auswahl = this.auswahl.find(p => p.name === this.value)
return auswahl.requirement
} else {
return this.requirement
}
}
isActive() { // TODO also handle Waffenlimit
const requirements = this.#getRequirements()
let passes = false
const flatActor = foundry.utils.flattenObject(this.parent.actor.system)
for (let requirement of requirements) {
let targetField = null
if (requirement.attribute) {
targetField = flatActor?.[requirement.attribute.toLocaleLowerCase()]
}
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
}
if (!passes) {
break
}
}
return passes
}
}

View File

@ -6,4 +6,18 @@ export class SpecialAbility extends Item {
super.prepareData();
}
getRequirements() {
let requirements = []
if (this.system.value && this.system.auswahl.find(p => p.name === this.system.value)) {
requirements = this.system.auswahl[this.system.value].requirement
} else {
requirements = this.system.requirement
return requirements
}
}
isActive() {
return true
}
}

View File

@ -58,7 +58,7 @@ export class ActionManager {
cost: ActionManager.FREE,
type: ActionManager.INTERACTION,
source: ActionManager.SF,
eval: () => this.#hatSonderfertigkeit("Schnellziehen")
eval: () => this.#hatSonderfertigkeit("Schnellziehen") && this.#evalSonderfertigkeitRequirements("Schnellziehen")
}
]
@ -82,7 +82,7 @@ export class ActionManager {
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: () => this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze")
eval: () => this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Scharfschütze") && this.#evalSonderfertigkeitRequirements("Scharfschütze")
},
{
name: "Abwehraktion",
@ -110,7 +110,11 @@ export class ActionManager {
type: ActionManager.ATTACK,
cost: ActionManager.REGULAR,
source: ActionManager.SF,
eval: () => this.#hatFernkampfWaffeinHand() && this.#hatSonderfertigkeit("Finte")
eval: () =>
this.#hatWaffeinHand() &&
this.#hatSonderfertigkeit("Finte") &&
this.#evalSonderfertigkeitRequirements("Finte")
},
{
name: "Wuchtschlag",
@ -125,6 +129,7 @@ export class ActionManager {
cost: ActionManager.REGULAR,
source: ActionManager.SF,
eval: () => this.#hatSonderfertigkeit("Wuchtschlag")
&& this.#evalSonderfertigkeitRequirements("Wuchtschlag")
},
{
name: "Betäubungsschlag",
@ -132,6 +137,7 @@ export class ActionManager {
cost: ActionManager.REGULAR,
source: ActionManager.SF,
eval: () => this.#hatSonderfertigkeit("Betäubungsschlag")
&& this.#evalSonderfertigkeitRequirements("Betäubungsschlag")
}
]
@ -169,14 +175,20 @@ export class ActionManager {
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: () => this.#hatMunition() && this.#hatFernkampfWaffeinHand("Bogen") && this.#hatSonderfertigkeit("Schnellladen (Bogen)")
eval: () => this.#hatMunition()
&& this.#hatFernkampfWaffeinHand("Bogen")
&& this.#hatSonderfertigkeit("Schnellladen (Bogen)")
&& this.#evalSonderfertigkeitRequirements("Schnellladen (Bogen)")
},
{
name: "Schnellladen (Armbrust)",
type: ActionManager.INTERACTION,
cost: ActionManager.CONTINUING,
source: ActionManager.SF,
eval: () => this.#hatMunition() && this.#hatFernkampfWaffeinHand("Armbrust") && this.#hatSonderfertigkeit("Schnellladen (Armbrust)")
eval: () => this.#hatMunition()
&& this.#hatFernkampfWaffeinHand("Armbrust")
&& this.#hatSonderfertigkeit("Schnellladen (Armbrust)")
&& this.#evalSonderfertigkeitRequirements("Schnellladen (Armbrust)")
},
{
name: "Nachladen",
@ -211,31 +223,42 @@ export class ActionManager {
#hatWaffeinHand() {
const item = this.actor.findEquipmentOnSlot("links") ?? this.actor.findEquipmentOnSlot("rechts")
return item
return item != null
}
#hatMunition() {
const item = this.actor.findEquipmentOnSlot("munition")
const weapon = this.actor.findEquipmentOnSlot("fernkampf")
return item
return item != null
}
#hatFernkampfWaffeinHand(art) {
const item = this.actor.findEquipmentOnSlot("fernkampf")
return item
return item != null
}
#hatSonderfertigkeitBeginnendMit(name) {
return this.actor.system.sonderfertigkeiten?.find(p => p.name.startsWith(name)) != null
return this.actor.itemTypes["SpecialAbility"]?.find(p => p.name.startsWith(name)) != null
}
#hatSonderfertigkeit(name) {
return this.actor.system.sonderfertigkeiten?.find(p => p.name === name) != null
return this.actor.itemTypes["SpecialAbility"]?.find(p => p.name === name) != null
}
#evalSonderfertigkeitRequirements(nameOfSF) {
const sf = this.actor.itemTypes["SpecialAbility"].find(p => p.name === nameOfSF)
return sf.system.isActive()
}
evaluate() {
let actionArray = [...this.#freeActions, ...this.#regularActions, ...this.#continuingActions]
return actionArray.filter(action => action.eval());
console.log(this.actor, actionArray.map((action) => {
return {
...action,
eval: action.eval()
}
}))
const validActions = actionArray.filter(action => action.eval())
return validActions
}
}

View File

@ -495,7 +495,7 @@ export class XmlImport {
actor.items.get(e._id).delete()
})
}
held.gegenstände.gegenstand.forEach(e => {
held.gegenstände?.gegenstand?.forEach(e => {
const compendiumOfArmor = game.packs.get('DSA_4-1.Armor');
const compendiumOfWeapons = game.packs.get('DSA_4-1.Weapons');
const compendiumOfAmmunition = game.packs.get('DSA_4-1.Ammunition');

View File

@ -3,7 +3,7 @@
"seite": "54",
"requirement": [
{
"attribute": "IN",
"attribute": "attribute.in.aktuell",
"minValue": "12"
},
{

View File

@ -5,19 +5,22 @@
"sfPflicht": true,
"requirement": [
{
"attribute": "KO",
"attribute": "attribute.ko.aktuell",
"minValue": "12"
},
{
"sonderfertigkeit": "Finte"
},
{
"attribute": "BE",
"attribute": "be",
"maxValue": "4"
},
{
"attribute": "INI",
"minValue": ">Target"
"compare": {
"ownAttribute": "ini.aktuell",
"operation": "gt",
"targetAttribute": "ini.aktuell"
}
}
],
"waffenLimit": [

View File

@ -6,20 +6,25 @@
"name": "Ausweichen I",
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "10"
},
{
"sonderfertigkeit": ""
}
],
"ausweichMod": "+3"
"mod": [
{
"name": "ausweichen",
"value": 3
}
]
},
{
"name": "Ausweichen II",
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "12"
},
{
@ -29,13 +34,18 @@
"sonderfertigkeit": "Aufmerksamkeit"
}
],
"ausweichMod": "+6"
"mod": [
{
"name": "ausweichen",
"value": 6
}
]
},
{
"name": "Ausweichen III",
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "15"
},
{
@ -45,7 +55,12 @@
"sonderfertigkeit": "Kampfreflexe"
}
],
"ausweichMod": "+9"
"mod": [
{
"name": "ausweichen",
"value": 9
}
]
}
],
"aktionsText": "Dies bedeutet, sich aus der Reichweite eines gegnerischen Angriffs zu bringen, ohne groß vorauszuplanen (Seite 66). Die Aktion Ausweichen erfordert eine Probe auf den Ausweichen-Wert des Kämpfers.",

View File

@ -6,21 +6,33 @@
"name": "Beidhändiger Kampf I",
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "12"
},
{
"sonderfertigkeit": "Linkhand"
}
],
"linkhandMalus": "-3/-3",
"tpKKLinkhand": "true"
"mod": [
{
"name": "at.links.mod",
"value": -3
},
{
"name": "pa.links.mod",
"value": -3
},
{
"name": "tpkklinkhand",
"value": 1
}
]
},
{
"name": "Beidhändiger Kampf II",
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "12"
},
{
@ -30,9 +42,24 @@
"sonderfertigkeit": "Aufmerksamkeit"
}
],
"linkhandMalus": "-0/-0",
"tpKKLinkhand": "true",
"zusatzAktionMitLinkhand": "1"
"mod": [
{
"name": "at.links.mod",
"value": 0
},
{
"name": "pa.links.mod",
"value": 0
},
{
"name": "tpkklinkhand",
"value": 1
},
{
"name": "aktionenlinks",
"value": 1
}
]
}
],
"aktionsText": " (Angriffs- oder Abwehraktion) Üblicherweise verfügt eine menschlicher (oder menschenähnlicher) Kämpfer nur über eine Angriffs- und eine Abwehraktion pro Kampfrunde. Führt er jedoch in der linken Hand eine zweite Waffe und ist mit dieser entsprechend ausgebildet (hat die entsprechenden Sonderfertigkeiten erlernt), so stehen ihm mehr Möglichkeiten zur Verfügung: Ein Kämpfer, der die Sonderfertigkeit Beidhändiger Kampf I erlernt hat und zwei Waffen führt, kann ohne Einbußen eine Angriffs- in eine Abwehraktion umwandeln und umgekehrt und erleidet dabei nicht den üblichen Abzug von 4 Punkten für das Umwandeln (wohl aber den Abzug von 3 Punkten für das Benutzen der falschen Hand). Er kann bei Angriffen mit der falschen Hand seinen KKBonus bei der Schadensermittlung einrechnen. Ein Kämpfer, der Beidhändiger Kampf II beherrscht, hat eine zusätzliche Angriffs- oder Abwehraktion zur Verfügung, wenn er in der Linken eine Waffe führt. Diese zusätzliche Aktion ist ausschließlich eine Waffenaktion (keine Bewegungs-, Zauber- oder vergleichbare Aktion, auch kein Ausweichen-Manöver und kein Manöver zur DK-Änderung). In der zusätzlichen Aktion sind keine Manöver erlaubt, die einen höheren automatischen Zuschlag als +4 beinhalten, und es darf auch freiwillig nicht mehr als +4 angesagt werden. Eine zusätzliche Angriffsaktion findet frühestens 4 Initiativphasen nach der ersten Aktion statt, eine zusätzliche Abwehraktion bei Bedarf. Der Kämpfer muss sich nicht vorher entscheiden, ob er eine zusätzliche Angriffs- oder Abwehraktion ausführen will. Die SF stellt keine zusätzliche Freie Aktion zu Verfügung; im Ausfall gibt BK II keine zusätzliche Aktion, sondern erschwert die Paraden des Verteidigers um 2 Punkte. Die Führung beider Waffen ist je nach Unterschied der beiden Waffen wie folgt modifiziert: Bei zwei gleichen Waffen AT/PA +/0; bei zwei nicht gleichen Waffen gleichen Waffentalents AT/PA 1/1; bei zwei Waffen unterschiedlichen Waffentalents AT/PA 2/2. Beidhändig geführte Waffen (namentlich Anderthalbhänder, Infanteriewaffen, Speere und Stäbe aller Art, Zweihand-Hiebwaffen, -flegel, -säbel und -schwerter) eignen sich nicht zum Kampf mit zwei Waffen. Waffen, die üblicherweise zweihändig geführt werden und sich nur bei hoher KK für die Verwendung mit einer Hand eignen (z.B. Orknase oder Bastardschwert), können ebenfalls nicht als zweite Waffe eingesetzt werden. (Ausnahme ist der Nachtwind, der keine KK-, sondern eine GE-Schwelle zur einhändigen Benutzung besitzt.) Außerdem verbietet sich die gleichzeitige Handhabung von zwei Kettenwaffen oder Peitschen. Im Kampf mit einer Haupt- und einer Zweitwaffe gilt, dass ein Patzer mit einer der beiden Waffen auch automatisch die Angriffs- bzw. Abwehraktion der anderen Waffe ruiniert (also misslingen lässt, unabhängig von dem Würfelergebnis bei dieser Waffe) und dass der Prüfwurf nochmals um 4 Punkte erschwert ist. Sollte der Fall eintreten, dass eine Heldin bei einem Doppelangriff beidseitig patzt, dann steht ihr kein Prüfwurf zu. Sie würfelt zweimal auf der Patzertabelle und wählt das ungünstigere Ergebnis (im Zweifelsfall Meisterentscheidung).",

View File

@ -3,11 +3,11 @@
"seite": "67",
"requirement": [
{
"attribute": "KK",
"attribute": "attribute.kk.aktuell",
"minValue": "15"
},
{
"attribute": "MU",
"attribute": "attribute.mu.aktuell",
"minValue": "12"
},
{

View File

@ -3,7 +3,7 @@
"seite": "67",
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "12"
},
{

View File

@ -3,7 +3,7 @@
"seite": "81",
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "12"
},
{

View File

@ -4,7 +4,7 @@
"sfPflicht": true,
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "12"
},
{

View File

@ -4,7 +4,7 @@
"sfPflicht": true,
"requirement": [
{
"attribute": "KK",
"attribute": "attribute.kk.aktuell",
"minValue": "12"
},
{

View File

@ -4,11 +4,11 @@
"sfPflicht": true,
"requirement": [
{
"attribute": "KK",
"attribute": "attribute.kk.aktuell",
"minValue": "13"
},
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "13"
}
],

View File

@ -4,15 +4,15 @@
"sfPflicht": true,
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuell",
"minValue": "12"
},
{
"attribute": "AT-Basis",
"attribute": "at.basis",
"minValue": "8"
},
{
"attribute": "BE",
"attribute": "be",
"maxValue": "4"
}
],

View File

@ -3,11 +3,11 @@
"seite": "",
"requirement": [
{
"attribute": "INI",
"attribute": "ini.aktuell",
"minValue": "10"
},
{
"attribute": "BE",
"attribute": "be",
"maxValue": "4"
},
{

View File

@ -4,7 +4,7 @@
"sfPflicht": true,
"requirement": [
{
"attribute": "GE",
"attribute": "attribute.ge.aktuellaktuell",
"minValue": "15"
},
{