[Feature] 1766 - Group Attack (#1770)

* Implemented group attack logic

* Updated all minions in the SRD to use the group attack functionality

* .

* Renamed groupAttack.nr to groupAttack.numAttackers

* Moved the flag vs global setting logic to documents/scene

* .
This commit is contained in:
WBHarry 2026-04-09 22:07:51 +02:00 committed by GitHub
parent b505e15eb2
commit ae480157d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 1286 additions and 220 deletions

View file

@ -280,6 +280,26 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
}
};
if (this.damage) {
config.isDirect = this.damage.direct;
const groupAttackTokens = this.damage.groupAttack
? game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens(
this.actor.id,
this.damage.groupAttack
)
: null;
config.damageOptions = {
groupAttack: this.damage.groupAttack
? {
numAttackers: Math.max(groupAttackTokens.length, 1),
range: this.damage.groupAttack
}
: null
};
}
DHBaseAction.applyKeybindings(config);
return config;
}

View file

@ -48,6 +48,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
action: new fields.StringField()
}),
damage: new fields.ObjectField(),
damageOptions: new fields.ObjectField(),
costs: new fields.ArrayField(new fields.ObjectField()),
successConsumed: new fields.BooleanField({ initial: false })
};

View file

@ -18,7 +18,12 @@ export default class DamageField extends fields.SchemaField {
initial: false,
label: 'DAGGERHEART.ACTIONS.Settings.includeBase.label'
}),
direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' })
direct: new fields.BooleanField({ initial: false, label: 'DAGGERHEART.CONFIG.DamageType.direct.name' }),
groupAttack: new fields.StringField({
choices: CONFIG.DH.GENERAL.groupAttackRange,
blank: true,
label: 'DAGGERHEART.ACTIONS.Settings.groupAttack.label'
})
};
super(damageFields, options, context);
}
@ -224,6 +229,22 @@ export default class DamageField extends fields.SchemaField {
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).roll.damageApply.players)
);
}
static getGroupAttackTokens(actorId, range) {
if (!canvas.scene) return [];
const targets = Array.from(game.user.targets);
const rangeSettings = canvas.scene?.rangeSettings;
if (!rangeSettings) return [];
const maxDistance = rangeSettings[range];
return canvas.scene.tokens.filter(x => {
if (x.actor?.id !== actorId) return false;
if (targets.every(target => x.object.distanceTo(target) > maxDistance)) return false;
return true;
});
}
}
export class DHActionDiceData extends foundry.abstract.DataModel {