Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 3d793e84a3b3c5eae0b934e6f71ddd011442c2bf
Author: Eligarf <[email protected]>
Date:   Tue Apr 9 08:26:19 2024 -0700

    Simplified the patching logic

commit 7879b5ecd02bc95d6a03f3b00779dc915cc9ff1d
Author: Eligarf <[email protected]>
Date:   Mon Apr 8 13:02:36 2024 -0700

    Hidden doors work in pf2e

commit b80644a5483326b98d60f1474003916ed1f94bb3
Author: Eligarf <[email protected]>
Date:   Mon Apr 8 12:54:50 2024 -0700

    Fix merge error

commit e9b6d67f08bd1d11e943f935c1b950231e6e9661
Merge: b812810 36ac329
Author: Eligarf <[email protected]>
Date:   Mon Apr 8 12:50:01 2024 -0700

    Merge branch 'dev' into pf2e-5.15.0

commit b812810853ce2d433f183c3d3cf69646de230dd8
Author: Eligarf <[email protected]>
Date:   Sun Apr 7 10:55:12 2024 -0700

    small tweaks for logging

commit f3e86ed3298dc14f655121192ba438f45da92748
Author: Eligarf <[email protected]>
Date:   Sun Apr 7 10:32:12 2024 -0700

    Dnd5e adapted to new init phase

commit 8de038be253f42e019da3a8f1641ab170d54941b
Merge: c541c2d c65c1a3
Author: Eligarf <[email protected]>
Date:   Sun Apr 7 08:58:51 2024 -0700

    Merge branch 'dev' into pf2e-5.15.0

commit c541c2dd8c2677dd8168eb8a7974aff9a928d53e
Author: Eligarf <[email protected]>
Date:   Sat Apr 6 16:51:55 2024 -0700

    Moved the patching into init rather than setup

commit b7107110863baa35f347e6e17df896c622e2de50
Author: Eligarf <[email protected]>
Date:   Sat Apr 6 13:57:15 2024 -0700

    Handle CS/CF in perception roll

commit f995d122114dd8ba3fe5b32031c882f4dbfc1d14
Author: Eligarf <[email protected]>
Date:   Sat Apr 6 11:09:50 2024 -0700

    Handle create a diversion

commit 4741825fce6e4ada9ba9840ffce74f942dabd6d0
Author: Eligarf <[email protected]>
Date:   Sat Apr 6 10:56:12 2024 -0700

    Remove log line

commit c268bb98d678e6dd9d66a69fecf6d4436ad4c84d
Author: Eligarf <[email protected]>
Date:   Sat Apr 6 10:49:17 2024 -0700

    Better skill hooks

commit 8a9066fb3f2fd9d1b4672d0305ca63ab8484b665
Author: Eligarf <[email protected]>
Date:   Fri Apr 5 17:08:21 2024 -0700

    Hook pf2e back in
  • Loading branch information
Eligarf committed Apr 9, 2024
1 parent 36ac329 commit ff05451
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 94 deletions.
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# v3.17.0
* PF2e: Perception and Stealth roll capturing works again, but still no changes to token visibility based on stealth
* PF2e: Hidden doors work again

# v3.16.1
* Fixed a merge error that turned off skill roll hooks after the first one

Expand Down
10 changes: 9 additions & 1 deletion module.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
"compatibility": {
"verified": "9.6"
}
},
{
"id": "pf2e",
"type": "system",
"compatibility": {
"verified": "5.15.0"
}
}
],
"requires": [
Expand All @@ -57,7 +64,8 @@
"scripts/hooks.js",
"scripts/systems/dnd4e.js",
"scripts/systems/dnd5e.js",
"scripts/systems/pf1.js"
"scripts/systems/pf1.js",
"scripts/systems/pf2e.js"
],
"styles": [
"styles/stealthy.css"
Expand Down
26 changes: 11 additions & 15 deletions scripts/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,17 @@ export default class Engine {
Stealthy.MODULE_ID,
'DetectionMode.prototype._canDetect',
function (wrapped, visionSource, target) {
switch (this.type) {
case DetectionMode.DETECTION_TYPES.SIGHT:
case DetectionMode.DETECTION_TYPES.SOUND:
const srcToken = visionSource.object.document;
const engine = stealthy.engine;
if (target instanceof DoorControl) {
if (!engine.canSpotDoor(target, visionSource)) return false;
}
else {
const tgtToken = target?.document;
if (tgtToken instanceof TokenDocument) {
if (engine.isHidden(visionSource, tgtToken, mode)) return false;
}
}
}
do {
const engine = stealthy.engine;
if (target instanceof DoorControl) {
if (!engine.canSpotDoor(target, visionSource)) return false;
break;
}
const tgtToken = target?.document;
if (tgtToken instanceof TokenDocument) {
if (engine.isHidden(visionSource, tgtToken, mode)) return false;
}
} while (false);
return wrapped(visionSource, target);
},
libWrapper.MIXED,
Expand Down
29 changes: 11 additions & 18 deletions scripts/systems/dnd5e.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,17 @@ class Engine5e extends Engine {
Stealthy.MODULE_ID,
`CONFIG.Canvas.detectionModes.${mode}._canDetect`,
function (wrapped, visionSource, target) {
switch (this.type) {
case DetectionMode.DETECTION_TYPES.SIGHT:
case DetectionMode.DETECTION_TYPES.SOUND:
const srcToken = visionSource.object.document;
const engine = stealthy.engine;
if (target instanceof DoorControl) {
if (!engine.canSpotDoor(target, srcToken)) return false;
}
else {
const tgtToken = target?.document;
if (tgtToken instanceof TokenDocument) {
if (engine.isHidden(visionSource, tgtToken, mode)) return false;
}
// else {
// Stealthy.log(`Don't know how to handle`, tgtToken);
// }
}
}
do {
const engine = stealthy.engine;
if (target instanceof DoorControl) {
if (!engine.canSpotDoor(target, visionSource)) return false;
break;
}
const tgtToken = target?.document;
if (tgtToken instanceof TokenDocument) {
if (engine.isHidden(visionSource, tgtToken, mode)) return false;
}
} while (false);
return wrapped(visionSource, target);
},
libWrapper.MIXED,
Expand Down
61 changes: 27 additions & 34 deletions scripts/systems/pf1.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,41 +39,34 @@ export class EnginePF1 extends Engine {

// Pick the sight modes in vision-5e that we want Stealthy to affect
// Hooks.once('setup', () => {
const sightModes = [
'basicSight',
'seeAll',
'seeInvisibility',
];
for (const mode of sightModes) {
console.log(`patching ${mode}`);
libWrapper.register(
Stealthy.MODULE_ID,
`CONFIG.Canvas.detectionModes.${mode}._canDetect`,
function (wrapped, visionSource, target) {
switch (this.type) {
case DetectionMode.DETECTION_TYPES.SIGHT:
case DetectionMode.DETECTION_TYPES.SOUND:
const srcToken = visionSource.object.document;
const engine = stealthy.engine;
if (target instanceof DoorControl) {
if (!engine.canSpotDoor(target, srcToken)) return false;
}
else {
const tgtToken = target?.document;
if (tgtToken instanceof TokenDocument) {
if (engine.isHidden(visionSource, tgtToken, mode)) return false;
}
// else {
// Stealthy.log(`Don't know how to handle`, tgtToken);
// }
}
const sightModes = [
'basicSight',
'seeAll',
'seeInvisibility',
];
for (const mode of sightModes) {
console.log(`patching ${mode}`);
libWrapper.register(
Stealthy.MODULE_ID,
`CONFIG.Canvas.detectionModes.${mode}._canDetect`,
function (wrapped, visionSource, target) {
do {
const engine = stealthy.engine;
if (target instanceof DoorControl) {
if (!engine.canSpotDoor(target, visionSource)) return false;
break;
}
return wrapped(visionSource, target);
},
libWrapper.MIXED,
{ perf_mode: libWrapper.PERF_FAST }
);
}
const tgtToken = target?.document;
if (tgtToken instanceof TokenDocument) {
if (engine.isHidden(visionSource, tgtToken, mode)) return false;
}
} while (false);
return wrapped(visionSource, target);
},
libWrapper.MIXED,
{ perf_mode: libWrapper.PERF_FAST }
);
}
// });
}

Expand Down
97 changes: 71 additions & 26 deletions scripts/systems/pf2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,66 @@ export class EnginePF2e extends Engine {
});
}

// There is probably a better practice for figuring out skill checks in PF2E, but this "works"
const stealthTags = [
`<strong>${game.i18n.localize('xdy-pf2e-workbench.macros.basicActionMacros.actions.Hide')}</strong>`,
`>${game.i18n.format("PF2E.InitiativeWithSkill", { skillName: game.i18n.localize('PF2E.StealthLabel') })}<`,
];
const perceptionTags = [
`<strong>${game.i18n.localize('xdy-pf2e-workbench.macros.basicActionMacros.actions.Seek')}</strong>`,
];
Stealthy.log('Localized Chat Tags', { stealthTags, perceptionTags });

Hooks.on('createChatMessage', async (message, options, id) => {
// Stealthy.log("createChatMessage", message);
if (stealthTags.some(t => message.flavor.includes(t))) {
await this.rollStealth(message, options, id);
}
else if (perceptionTags.some(t => message.flavor.includes(t))) {
await this.rollPerception(message, options, id);
// Stealthy.log('createChatMessage', message);
const pf2eContext = message.flags.pf2e.context;
switch (pf2eContext?.type) {
case 'perception-check':
if (pf2eContext?.options.includes('action:seek')) {
await this.rollPerception(message, options, id);
}
break;
case 'skill-check':
const hidden = ['action:hide', 'action:create-a-diversion', 'action:sneak'];
if (pf2eContext?.options.some((t) => hidden.includes(t))) {
await this.rollStealth(message, options, id);
}
break;
case 'initiative':
if (pf2eContext?.domains.includes('stealth')) {
await this.rollStealth(message, options, id);
}
break;
}
});
}

patchFoundry() {
// Generic Detection mode patching

const sightModes = [
'basicSight',
'feelTremor',
'hearing',
'seeAll',
'seeInvisibility',
];
for (const mode of sightModes) {
console.log(`Stealthy | patching ${mode}`);
libWrapper.register(
Stealthy.MODULE_ID,
`CONFIG.Canvas.detectionModes.${mode}._canDetect`,
function (wrapped, visionSource, target) {
Stealthy.log(`testing ${mode}`, { visionSource, target });
do {
const engine = stealthy.engine;
if (target instanceof DoorControl) {
if (!engine.canSpotDoor(target, visionSource)) return false;
break;
}
const tgtToken = target?.document;
if (tgtToken instanceof TokenDocument) {
if (engine.isHidden(visionSource, tgtToken, mode)) return false;
}
} while (false);
return wrapped(visionSource, target);
},
libWrapper.MIXED,
{ perf_mode: libWrapper.PERF_FAST }
);
}
}

findHiddenEffect(actor) {
return actor?.getCondition('hidden');
}
Expand All @@ -44,17 +83,13 @@ export class EnginePF2e extends Engine {
return actor?.items.find(i => i.name === 'Seeking');
}

canDetectHidden(visionSource, hiddenEffect, tgtToken) {
canDetectHidden(visionSource, hiddenEffect, tgtToken, detectionMode) {
const stealth = hiddenEffect?.flags?.stealthy?.hidden ?? (10 + tgtToken.actor.system.skills.ste.value);
const source = visionSource.object?.actor;
let seeking = this.findSpotEffect(source);
const seeking = this.findSpotEffect(source);
const perception = seeking?.flags?.stealthy?.spot ?? 10 + source.system.attributes.perception?.value;

if (perception < stealth) {
Stealthy.log(`${visionSource.object.name}'s ${perception} can't detect ${tgtToken.name}'s ${stealth}`);
return false;
}
return true;
return perception >= stealth;
}

makeHiddenEffectMaker(label) {
Expand Down Expand Up @@ -126,7 +161,7 @@ export class EnginePF2e extends Engine {
},
"unidentified": false
},
"img": "systems/pf2e/icons/spells/anticipate-peril.webp",
"img": game.settings.get(Stealthy.MODULE_ID, 'spotIcon'),
"flags": {
"stealthy": flag
},
Expand Down Expand Up @@ -154,7 +189,12 @@ export class EnginePF2e extends Engine {

async rollPerception(message, options, id) {
Stealthy.log('rollPerception', { message, options, id });
const check = Number(message.content);
let check = Number(message.content);

// Easier to track for Critical success/failure if we just bump the result by +/- 10
const die = message.rolls[0].dice[0];
if (die.total == 20) check += 10;
else if (die.total == 1) check -= 10;

const token = canvas.tokens.get(message.speaker.token);
const actor = token.actor;
Expand All @@ -176,5 +216,10 @@ export class EnginePF2e extends Engine {
}

Hooks.once('init', () => {
Stealthy.RegisterEngine('pf2e', () => new EnginePF2e());
if (game.system.id === 'pf2e') {
const systemEngine = new EnginePF2e();
if (systemEngine) {
window[Stealthy.MODULE_ID] = new Stealthy(systemEngine);
}
}
});

0 comments on commit ff05451

Please sign in to comment.