rollHelpers updated for swade 5.2.0
This commit is contained in:
parent
ea705bc61c
commit
9a0599cf5c
12
CHANGELOG.md
12
CHANGELOG.md
@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [4.2.2]
|
||||
|
||||
### Changed
|
||||
|
||||
- Minimum SWADE version is now 5.2.0
|
||||
- Reworked Gang Up to still handle Formation Fighter along with the new system Gang Up improvements
|
||||
- BREAKING: Pack Tactics needs an effect added setting `system.stats.gangUpDamage` to `true`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Gang up calculation was double-counting the attacker if the attacker had formation fighter.
|
||||
|
||||
## [4.2.1]
|
||||
|
||||
### Added
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
}
|
||||
],
|
||||
"url": "https://git.bloy.org/foundryvtt/swade-mb-helpers",
|
||||
"version": "4.2.1",
|
||||
"version": "4.2.2",
|
||||
"compatibility": {
|
||||
"minimum": "13",
|
||||
"verified": "13"
|
||||
@ -111,8 +111,8 @@
|
||||
"type": "system",
|
||||
"manifest": "https://gitlab.com/api/v4/projects/16269883/packages/generic/swade/latest/system.json",
|
||||
"compatibility": {
|
||||
"minimum": "5.1.0",
|
||||
"verified": "5.1.0"
|
||||
"minimum": "5.2.0",
|
||||
"verified": "5.2.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
@ -21,9 +21,9 @@ function getEdgeToEdgeDistance(tokenA, tokenB) {
|
||||
return distance - combinedRadii * conversionFactor;
|
||||
}
|
||||
|
||||
function calcGangupBonus(sourceToken, targetToken) {
|
||||
const targetActor = targetToken.actor;
|
||||
function getGangupModifiers(sourceToken, targetToken, label = null) {
|
||||
const sourceActor = sourceToken.actor;
|
||||
const targetActor = targetToken.actor;
|
||||
const scene = targetToken.parent;
|
||||
const ignoreStatuses = ['defeated', 'incapacitated', 'stunned'];
|
||||
const attackerAllies = scene.tokens.filter((t) => {
|
||||
@ -34,9 +34,6 @@ function calcGangupBonus(sourceToken, targetToken) {
|
||||
let formationFighterBonus = attackerAllies.filter((t) =>
|
||||
t.actor.getSingleItemBySwid('formation-fighter', 'edge'),
|
||||
).length;
|
||||
if (sourceActor.getSingleItemBySwid('formation-fighter', 'edge')) {
|
||||
formationFighterBonus++;
|
||||
}
|
||||
let numAttackerAllies = attackerAllies.length;
|
||||
const numDefenderAllies = scene.tokens.filter((t) => {
|
||||
if (t.disposition !== targetToken.disposition) return false;
|
||||
@ -44,16 +41,49 @@ function calcGangupBonus(sourceToken, targetToken) {
|
||||
if (getEdgeToEdgeDistance(targetToken, t) >= 1) return false;
|
||||
return getEdgeToEdgeDistance(sourceToken, t) < 1;
|
||||
}).length;
|
||||
if (numAttackerAllies > 0) {
|
||||
if (numAttackerAllies > 1) {
|
||||
numAttackerAllies += formationFighterBonus;
|
||||
}
|
||||
let gangUpBonus = Math.min(4, numAttackerAllies - numDefenderAllies);
|
||||
if (targetActor?.getSingleItemBySwid('improved-block', 'edge')) {
|
||||
gangUpBonus -= 2;
|
||||
} else if (targetActor?.getSingleItemBySwid('block', 'edge')) {
|
||||
gangUpBonus -= 1;
|
||||
const attackerGlobalMods = foundry.utils.getProperty(sourceActor, 'system.stats.globalMods');
|
||||
if (attackerGlobalMods?.gangUp && Array.isArray(attackerGlobalMods.gangUp)) {
|
||||
attackerGlobalMods.gangUp.forEach((m) => (gangUpBonus += Number(m.value)));
|
||||
}
|
||||
return gangUpBonus;
|
||||
let targetGangUpMod = 0;
|
||||
const targetGangUpLabels = [];
|
||||
const targetGlobalMods = targetActor ? foundry.utils.getProperty(targetActor, 'system.stats.globalMods') : {};
|
||||
if (targetGlobalMods?.gangUp && Array.isArray(targetGlobalMods.gangUp)) {
|
||||
for (const m of targetGlobalMods.gangUp) {
|
||||
targetGangUpMod += Number(m.value);
|
||||
targetGangUpLabels.push(m.label);
|
||||
}
|
||||
}
|
||||
const improvedBlock = targetActor?.getSingleItemBySwid('improved-block', 'edge');
|
||||
if (improvedBlock) {
|
||||
targetGangUpMod -= 2;
|
||||
targetGangUpLabels.push(improvedBlock.name);
|
||||
} else {
|
||||
const block = targetActor?.getSingleItemBySwid('block', 'edge');
|
||||
if (block) {
|
||||
targetGangUpMod -= 1;
|
||||
targetGangUpLabels.push(block.name);
|
||||
}
|
||||
}
|
||||
const mods = [];
|
||||
if (gangUpBonus > 0) {
|
||||
mods.push({
|
||||
label: label || game.i18n.localize('SWADE.GangUp'),
|
||||
value: gangUpBonus,
|
||||
});
|
||||
if (targetGangUpMod !== 0) {
|
||||
const value = Math.max(targetGangUpMod, -gangUpBonus);
|
||||
mods.push({
|
||||
label: targetGangUpLabels.join(' + ') || 'SWADE.GlobalMod.TargetGangup',
|
||||
value,
|
||||
});
|
||||
}
|
||||
}
|
||||
return mods;
|
||||
}
|
||||
|
||||
export async function preAttackRollModifiers(
|
||||
@ -121,16 +151,21 @@ export async function preAttackRollModifiers(
|
||||
|
||||
// Gang Up correction
|
||||
if (isMeleeAttack) {
|
||||
const gangUpBonus = calcGangupBonus(sourceToken, targetToken);
|
||||
const gangUpModIndex = additionalMods.findIndex((m) => m.label === 'SWADE.GangUp');
|
||||
if (gangUpModIndex > -1) {
|
||||
additionalMods.splice(gangUpModIndex, 1);
|
||||
}
|
||||
if (gangUpBonus && gangUpBonus > 0) {
|
||||
additionalMods.push({
|
||||
label: 'SWADE.GangUp',
|
||||
value: gangUpBonus,
|
||||
});
|
||||
const gangUpMods = getGangupModifiers(sourceToken, targetToken);
|
||||
const titles = gangUpMods.map((mod) => mod.label);
|
||||
titles.push('SWADE.GangUp');
|
||||
titles.push('SWADE.GlobalMod.TargetGangUp');
|
||||
removeDuplicateMods(additionalMods, titles);
|
||||
additionalMods.push(...gangUpMods);
|
||||
}
|
||||
}
|
||||
|
||||
function removeDuplicateMods(additionalMods, replacementModTitles) {
|
||||
const translatedTitles = replacementModTitles.map((t) => game.i18n.localize(t));
|
||||
for (const title of [...replacementModTitles, ...translatedTitles]) {
|
||||
const modIndex = additionalMods.findIndex((m) => m.label === title);
|
||||
if (modIndex > -1) {
|
||||
additionalMods.splice(modIndex, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,11 +207,26 @@ export async function preDamageRollModifiers(actor, item, roll, modifiers, optio
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (token.actor.getSingleItemBySwid('pack-tactics', 'ability')) {
|
||||
const gangupBonus = calcGangupBonus(token, target);
|
||||
if (gangupBonus > 0) {
|
||||
modifiers.push({ label: 'Gang Up (Pack Tactics)', value: gangupBonus, ignore: false });
|
||||
if (
|
||||
item.isMeleeWeapon &&
|
||||
'stats' in token.actor.system &&
|
||||
token.actor.system.stats.gangUpDamage &&
|
||||
target &&
|
||||
token
|
||||
) {
|
||||
const effect = token.actor.effects.find(
|
||||
(e) => !e.disabled && e.changes.some((c) => c.key === 'system.stats.gangUpDamage'),
|
||||
);
|
||||
const gangUpMods = getGangupModifiers(token, target, effect?.name);
|
||||
const titles = gangUpMods.map((mod) => mod.label);
|
||||
titles.push('SWADE.GangUp');
|
||||
titles.push('SWADE.GlobalMod.TargetGangUp');
|
||||
removeDuplicateMods(modifiers, titles);
|
||||
const gangUpModIndex = modifiers.findIndex((m) => m.label === 'SWADE.GangUp');
|
||||
if (gangUpModIndex > -1) {
|
||||
modifiers.splice(gangUpModIndex, 1);
|
||||
}
|
||||
modifiers.push(...gangUpMods);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user