Skip to content

Commit e8e1960

Browse files
committed
Add ability to use roll modifiers on attacks
1 parent 15bbb18 commit e8e1960

File tree

9 files changed

+191
-23
lines changed

9 files changed

+191
-23
lines changed

attributions.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ Icons / SVGs
2626
- <a href="https://www.flaticon.com/free-icons/poison" title="poison icons">Poison icons created by Freepik - Flaticon</a>
2727
- <a href="https://www.flaticon.com/free-icons/box" title="box icons">Box icons created by bqlqn - Flaticon</a>
2828
- <a href="https://www.flaticon.com/free-icons/destroyed-planet" title="destroyed planet icons">Destroyed planet icons created by Mayor Icons - Flaticon</a>
29-
- <a href="https://www.flaticon.com/free-icons/sharp" title="sharp icons">Sharp icons created by edt.im - Flaticon</a>
29+
- <a href="https://www.flaticon.com/free-icons/sharp" title="sharp icons">Sharp icons created by edt.im - Flaticon</a>
30+
- <a href="https://www.flaticon.com/free-icons/attack" title="attack icons">Attack icons created by Smashicons - Flaticon</a>

src/assets/ui/other-svg/attack.svg

+87
Loading

src/module/active-effects/sheets/active-effect-config.js

+8
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,14 @@ export class DLActiveEffectConfig extends ActiveEffectConfig {
9898
'system.bonuses.attack.boons.will': i18n('DL.TalentAttackBoonsBanes') + ' - ' + i18n('DL.AttributeWill'),
9999
'system.bonuses.attack.boons.perception': i18n('DL.TalentAttackBoonsBanes') + ' - ' + i18n('DL.AttributePerception'),
100100
'system.bonuses.attack.boons.all': i18n('DL.TalentAttackBoonsBanes') + ' - ' + i18n('DL.AllTitle'),
101+
'system.bonuses.attack.modifier.spell': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.MagicSpellsTitle'),
102+
'system.bonuses.attack.modifier.weapon': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.WeaponTitle'),
103+
'system.bonuses.attack.modifier.strength': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.AttributeStrength'),
104+
'system.bonuses.attack.modifier.agility': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.AttributeAgility'),
105+
'system.bonuses.attack.modifier.intellect': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.AttributeIntellect'),
106+
'system.bonuses.attack.modifier.will': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.AttributeWill'),
107+
'system.bonuses.attack.modifier.perception': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.AttributePerception'),
108+
'system.bonuses.attack.modifier.all': i18n('DL.AttackRollBonuses') + ' - ' + i18n('DL.AllTitle'),
101109
'system.bonuses.attack.damage.spell': i18n('DL.TalentExtraDamage') + ' - ' + i18n('DL.MagicSpellsTitle'),
102110
'system.bonuses.attack.damage.weapon': i18n('DL.TalentExtraDamage') + ' - ' + i18n('DL.WeaponTitle'),
103111
'system.bonuses.attack.damage.talent': i18n('DL.TalentExtraDamage') + ' - ' + i18n('DL.TalentTitle'),

src/module/actor/actor.js

+63-21
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,15 @@ export class DemonlordActor extends Actor {
414414
// if !target -> ui.notifications.warn(Please select target) ??
415415

416416
// Attack modifier and Boons/Banes
417-
const modifiers = [attacker.system?.attributes[attackAttribute]?.modifier || 0, parseInt(inputModifier) || 0]
417+
const modifiers = [
418+
item.system.action?.rollbonus || 0,
419+
attacker.system?.attributes[attackAttribute]?.modifier || 0,
420+
attacker.system?.bonuses.attack.modifier[attackAttribute] || 0,
421+
attacker.system?.bonuses.attack.modifier.all || 0,
422+
attacker.system?.bonuses.attack.modifier.weapon || 0,
423+
parseInt(inputModifier) || 0,
424+
]
425+
418426
let boons =
419427
(parseInt(item.system.action.boonsbanes) || 0) +
420428
(parseInt(inputBoons) || 0) +
@@ -451,19 +459,22 @@ export class DemonlordActor extends Actor {
451459
return attackRoll?.total >= targetNumber
452460
})
453461

454-
for (let effect of this.appliedEffects) {
455-
const specialDuration = foundry.utils.getProperty(effect, 'flags.specialDuration')
456-
// if (!(specialDuration?.length > 0)) continue
457-
if (specialDuration === 'NextD20Roll') {
458-
let nAttackAttribute = attackAttribute.length ? attackAttribute : 'None'
459-
if (
460-
effect.changes.find(e => e.key.includes('system.bonuses.attack.boons.all')) || !effect.changes.length ||
461-
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.${nAttackAttribute}`)) ||
462-
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.weapon`))
463-
)
464-
await effect?.delete()
465-
}
466-
}
462+
for (let effect of this.appliedEffects) {
463+
const specialDuration = foundry.utils.getProperty(effect, 'flags.specialDuration')
464+
// if (!(specialDuration?.length > 0)) continue
465+
if (specialDuration === 'NextD20Roll') {
466+
let nAttackAttribute = attackAttribute.length ? attackAttribute : 'None'
467+
if (
468+
effect.changes.find(e => e.key.includes('system.bonuses.attack.boons.all')) || !effect.changes.length ||
469+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.${nAttackAttribute}`)) ||
470+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.weapon`)) ||
471+
effect.changes.find(e => e.key.includes('system.bonuses.attack.modifier.all')) || !effect.changes.length ||
472+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.modifier.${nAttackAttribute}`)) ||
473+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.modifier.weapon`))
474+
)
475+
await effect?.delete()
476+
}
477+
}
467478

468479
Hooks.call('DL.RollAttack', {
469480
sourceToken: attacker.token || tokenManager.getTokenByActorId(attacker.id),
@@ -594,8 +605,15 @@ export class DemonlordActor extends Actor {
594605

595606
const attackAttribute = talentData.action.attack.toLowerCase()
596607
const defenseAttribute = talentData.action?.attack?.toLowerCase()
608+
const attacker = this
597609

598-
let modifiers = [parseInt(inputModifier), this.getAttribute(attackAttribute)?.modifier || 0]
610+
const modifiers = [
611+
talentData.action?.rollbonus || 0,
612+
attacker.system?.attributes[attackAttribute]?.modifier || 0,
613+
attacker.system?.bonuses.attack.modifier[attackAttribute] || 0,
614+
attacker.system?.bonuses.attack.modifier.all || 0,
615+
parseInt(inputModifier) || 0,
616+
]
599617

600618
let boons =
601619
(parseInt(inputBoons) || 0) +
@@ -623,7 +641,9 @@ export class DemonlordActor extends Actor {
623641
let nAttackAttribute = attackAttribute.length ? attackAttribute : 'None'
624642
if (
625643
effect.changes.find(e => e.key.includes('system.bonuses.attack.boons.all')) || !effect.changes.length ||
626-
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.${nAttackAttribute}`))
644+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.${nAttackAttribute}`))||
645+
effect.changes.find(e => e.key.includes('system.bonuses.attack.modifier.all')) || !effect.changes.length ||
646+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.modifier.${nAttackAttribute}`))
627647
)
628648
await effect?.delete()
629649
}
@@ -683,9 +703,20 @@ export class DemonlordActor extends Actor {
683703

684704
let attackRoll
685705
if (attackAttribute) {
706+
const attacker = this
707+
708+
const modifiers = [
709+
spellData.action?.rollbonus || 0,
710+
attacker.system?.attributes[attackAttribute]?.modifier || 0,
711+
attacker.system?.bonuses.attack.modifier[attackAttribute] || 0,
712+
attacker.system?.bonuses.attack.modifier.all || 0,
713+
attacker.system?.bonuses.attack.modifier.spell || 0,
714+
parseInt(inputModifier) || 0,
715+
]
716+
686717
let boons =
687718
(parseInt(inputBoons) || 0) +
688-
(parseInt(spellData.action.boonsbanes) || 0) +
719+
(parseInt(spellData.action?.boonsbanes) || 0) +
689720
(this.system.bonuses.attack.boons[attackAttribute] || 0) +
690721
(this.system.bonuses.attack.boons.all || 0) +
691722
(this.system.bonuses.attack.boons.spell || 0)
@@ -700,7 +731,6 @@ export class DemonlordActor extends Actor {
700731
(target?.actor?.system.bonuses.defense.boons.spell || 0) +
701732
(horrifyingBane && ignoreLevelDependentBane && !this.system.horrifying && !this.system.frightening && target?.actor?.system.horrifying && 1 || 0)
702733

703-
const modifiers = [parseInt(inputModifier) || 0, this.getAttribute(attackAttribute).modifier || 0]
704734
const boonsReroll = parseInt(this.system.bonuses.rerollBoon1Dice)
705735

706736
attackRoll = new Roll(this.rollFormula(modifiers, boons, boonsReroll), this.system)
@@ -724,7 +754,10 @@ export class DemonlordActor extends Actor {
724754
if (
725755
effect.changes.find(e => e.key.includes('system.bonuses.attack.boons.all')) || !effect.changes.length ||
726756
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.${nAttackAttribute}`)) ||
727-
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.spell`))
757+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.spell`)) ||
758+
effect.changes.find(e => e.key.includes('system.bonuses.attack.modifier.all')) || !effect.changes.length ||
759+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.modifier.${nAttackAttribute}`)) ||
760+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.modifier.spell`))
728761
)
729762
await effect?.delete()
730763
}
@@ -800,8 +833,15 @@ export class DemonlordActor extends Actor {
800833
} else {
801834
const attackAttribute = itemData.action.attack.toLowerCase()
802835
const defenseAttribute = itemData.action?.attack?.toLowerCase()
836+
const attacker = this
803837

804-
let modifiers = [parseInt(inputModifier), (this.getAttribute(attackAttribute)?.modifier || 0)]
838+
const modifiers = [
839+
item.system.action.rollbonus || 0,
840+
attacker.system?.attributes[attackAttribute]?.modifier || 0,
841+
attacker.system?.bonuses.attack.modifier[attackAttribute] || 0,
842+
attacker.system?.bonuses.attack.modifier.all || 0,
843+
parseInt(inputModifier) || 0,
844+
]
805845

806846
let boons =
807847
(parseInt(inputBoons) || 0) +
@@ -829,7 +869,9 @@ export class DemonlordActor extends Actor {
829869
let nAttackAttribute = attackAttribute.length ? attackAttribute : 'None'
830870
if (
831871
effect.changes.find(e => e.key.includes('system.bonuses.attack.boons.all')) || !effect.changes.length ||
832-
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.${nAttackAttribute}`))
872+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.boons.${nAttackAttribute}`)) ||
873+
effect.changes.find(e => e.key.includes('system.bonuses.attack.modifier.all')) || !effect.changes.length ||
874+
effect.changes.find(e => e.key.includes(`system.bonuses.attack.modifier.${nAttackAttribute}`))
833875
)
834876
await effect?.delete()
835877
}

src/module/data/common.js

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export function action() {
6464
damagetype: makeStringField(),
6565
boonsbanesactive: makeBoolField(true),
6666
boonsbanes: makeStringField(),
67+
rollbonus: makeStringField(),
6768
plus20active: makeBoolField(true),
6869
plus20: makeStringField(),
6970
plus20damage: makeStringField(),

src/module/utils/handlebars-helpers.js

+14
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export function registerHandlebarsHelpers() {
5858
// New Handlebars helpers
5959
Handlebars.registerHelper('Dropdown', (groupName, checkedKey, loc) => _buildDropdown(groupName, checkedKey, loc))
6060
Handlebars.registerHelper('BOBAButton', (_name, value, loc = undefined) => _buildBOBA(_name, value, loc))
61+
Handlebars.registerHelper('RollBonus', (_name, value, loc = undefined) => _buildRollBonus(_name, value, loc))
6162
Handlebars.registerHelper('Checkboxes', (groupName, checkedKey, data) => _buildCheckboxesV2(groupName, checkedKey, data))
6263
Handlebars.registerHelper('AvailabilityDropdown', (groupName, checkedKey) => _buildAvailabilityDropdown(groupName, checkedKey))
6364
Handlebars.registerHelper('DropdownValue', (groupName, checkedKey, valueName, valueKey) => _buildDropdownWithValue(groupName, checkedKey, valueName, valueKey))
@@ -550,6 +551,19 @@ function _buildBOBA(_name, value, loc) {
550551
return new Handlebars.SafeString(html)
551552
}
552553

554+
function _buildRollBonus(_name, value, loc) {
555+
loc = loc || "DL.AttackRollBonuses"
556+
const html = `
557+
<div class="item-group-rollbonus">
558+
<div class="input-group" data-tippy-content="${i18n(loc)}">
559+
<i class="icon-attack ${value ? '' : 'inactive'} themed-icon"></i>
560+
<span class="sep"></span>
561+
<input type="text" class="input-group-textbox" name="${_name}" value="${value}" placeholder="0"/>
562+
</div>
563+
</div>`
564+
return new Handlebars.SafeString(html)
565+
}
566+
553567
function _buildCheckboxesV2(groupName, checkedKey, data) {
554568
let html = ''
555569
if (groupName === 'talent-action-bonus') {

src/module/utils/utils.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ export function capitalize(string) {
55
}
66

77
export function plusify(x) {
8-
if ((typeof x === 'string' || x instanceof String) && x[0] === '+') return x // Ignore plusified strings
8+
if (typeof x === 'string' || x instanceof String) {
9+
return x[0] === '+' ? x : '+' + x
10+
}
911
if (x == 0) return ''
1012
return x > 0 ? '+' + x : x
1113
}

0 commit comments

Comments
 (0)