diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3c8e98f6..61e93824 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -18,8 +18,15 @@ jobs: - name: Set Release Notes for Github id: set-release-notes-github run: | + echo "- General:" >> release_notes.txt + echo " - 3rd Party Reactions: 3rd Party Reactions now support multiple GMs in the same world at the same time. After updating, the first active GM will be set as your Primary GM. This can then be modified in GPS Settings, which will give a list of GMs to choose from if more than one is present in a world. If this primary gm logs out or is no longer present in the world, the gm will fallback to the first active gm." >> release_notes.txt + echo " - 3rd Party Reactions: Item renaming is now possible as matching is done based on an ID stored on the item. This does mean the item needs to either be pulled from my compendiums or medkitted via cpr in order to work properly moving forward." >> release_notes.txt + echo " - Region Wrapping: Added setting (default true) for Region Wrapping. This wrapping is done to test additional points on a token when moving in/through a region (Foundry only tests the token center point). This was previously always on with my module in v12, you now have the ability to turn it off but I would not recommend it if trying to stay close to 5e rules." >> release_notes.txt + echo " - Cardinal Movement Helper: Added a return that will give the total movement that occurred." >> release_notes.txt + echo "- Updates:" >> release_notes.txt + echo " - Opportunity Attack: Add handling to temporarily disable Levels UI Picker on region deployment because it overrides default region handling" >> release_notes.txt echo "- Bugfixes:" >> release_notes.txt - echo " - Opportunity Attack: Additional turn end bugfix causing permissions errors" >> release_notes.txt + echo " - Vicious Mockery: Fix dialog not submitting with enter key correctly" >> release_notes.txt echo "release-notes-github<> $GITHUB_ENV cat release_notes.txt >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV diff --git a/packs/gps-3rd-party-features/001303.log b/packs/gps-3rd-party-features/001323.log similarity index 100% rename from packs/gps-3rd-party-features/001303.log rename to packs/gps-3rd-party-features/001323.log diff --git a/packs/gps-3rd-party-features/001070.ldb b/packs/gps-3rd-party-features/001325.ldb similarity index 80% rename from packs/gps-3rd-party-features/001070.ldb rename to packs/gps-3rd-party-features/001325.ldb index 4bac886d..38ca8fc0 100644 Binary files a/packs/gps-3rd-party-features/001070.ldb and b/packs/gps-3rd-party-features/001325.ldb differ diff --git a/packs/gps-3rd-party-features/CURRENT b/packs/gps-3rd-party-features/CURRENT index b1fdf267..3cd002ae 100644 --- a/packs/gps-3rd-party-features/CURRENT +++ b/packs/gps-3rd-party-features/CURRENT @@ -1 +1 @@ -MANIFEST-001301 +MANIFEST-001321 diff --git a/packs/gps-3rd-party-features/LOG b/packs/gps-3rd-party-features/LOG index 80e5ee4e..efc5be36 100644 --- a/packs/gps-3rd-party-features/LOG +++ b/packs/gps-3rd-party-features/LOG @@ -1,8 +1,15 @@ -2024/09/17-11:31:04.143 13054 Recovering log #1300 -2024/09/17-11:31:04.146 13054 Delete type=0 #1300 -2024/09/17-11:31:04.146 13054 Delete type=3 #1299 -2024/09/19-01:12:07.694 1147c Level-0 table #1304: started -2024/09/19-01:12:07.695 1147c Level-0 table #1304: 0 bytes OK -2024/09/19-01:12:07.697 1147c Delete type=0 #1302 -2024/09/19-01:12:07.699 1147c Manual compaction at level-0 from '!folders!4Ecsdk7k1FvMs9OF' @ 72057594037927935 : 1 .. '!items.effects!G2IDv711EWrOF7ef.kE7T0D7E6CnMvjvr' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.699 1147c Manual compaction at level-1 from '!folders!4Ecsdk7k1FvMs9OF' @ 72057594037927935 : 1 .. '!items.effects!G2IDv711EWrOF7ef.kE7T0D7E6CnMvjvr' @ 0 : 0; will stop at (end) +2024/09/21-16:17:32.994 13054 Recovering log #1319 +2024/09/21-16:17:32.998 13054 Delete type=0 #1319 +2024/09/21-16:17:32.998 13054 Delete type=3 #1317 +2024/09/21-21:27:43.277 1147c Level-0 table #1324: started +2024/09/21-21:27:43.279 1147c Level-0 table #1324: 11174 bytes OK +2024/09/21-21:27:43.281 1147c Delete type=0 #1322 +2024/09/21-21:27:43.281 1147c Manual compaction at level-0 from '!folders!4Ecsdk7k1FvMs9OF' @ 72057594037927935 : 1 .. '!items.effects!G2IDv711EWrOF7ef.kE7T0D7E6CnMvjvr' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.287 1147c Manual compaction at level-1 from '!folders!4Ecsdk7k1FvMs9OF' @ 72057594037927935 : 1 .. '!items.effects!G2IDv711EWrOF7ef.kE7T0D7E6CnMvjvr' @ 0 : 0; will stop at '!items!y6y7B3DSHbduxFDF' @ 68 : 1 +2024/09/21-21:27:43.288 1147c Compacting 1@1 + 1@2 files +2024/09/21-21:27:43.290 1147c Generated table #1325@1: 8 keys, 19424 bytes +2024/09/21-21:27:43.290 1147c Compacted 1@1 + 1@2 files => 19424 bytes +2024/09/21-21:27:43.291 1147c compacted to: files[ 0 0 1 0 0 0 0 ] +2024/09/21-21:27:43.292 1147c Delete type=2 #1070 +2024/09/21-21:27:43.292 1147c Delete type=2 #1324 +2024/09/21-21:27:43.298 1147c Manual compaction at level-1 from '!items!y6y7B3DSHbduxFDF' @ 68 : 1 .. '!items.effects!G2IDv711EWrOF7ef.kE7T0D7E6CnMvjvr' @ 0 : 0; will stop at (end) diff --git a/packs/gps-3rd-party-features/LOG.old b/packs/gps-3rd-party-features/LOG.old index a7a27c7c..8e497bb9 100644 --- a/packs/gps-3rd-party-features/LOG.old +++ b/packs/gps-3rd-party-features/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.661 19cc Recovering log #1297 -2024/09/17-10:53:01.666 19cc Delete type=0 #1297 -2024/09/17-10:53:01.666 19cc Delete type=3 #1295 +2024/09/21-16:06:48.807 1304c Recovering log #1315 +2024/09/21-16:06:48.811 1304c Delete type=0 #1315 +2024/09/21-16:06:48.811 1304c Delete type=3 #1313 +2024/09/21-16:14:51.133 1147c Level-0 table #1320: started +2024/09/21-16:14:51.133 1147c Level-0 table #1320: 0 bytes OK +2024/09/21-16:14:51.135 1147c Delete type=0 #1318 +2024/09/21-16:14:51.140 1147c Manual compaction at level-0 from '!folders!4Ecsdk7k1FvMs9OF' @ 72057594037927935 : 1 .. '!items.effects!G2IDv711EWrOF7ef.kE7T0D7E6CnMvjvr' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.140 1147c Manual compaction at level-1 from '!folders!4Ecsdk7k1FvMs9OF' @ 72057594037927935 : 1 .. '!items.effects!G2IDv711EWrOF7ef.kE7T0D7E6CnMvjvr' @ 0 : 0; will stop at (end) diff --git a/packs/gps-3rd-party-features/MANIFEST-001301 b/packs/gps-3rd-party-features/MANIFEST-001301 deleted file mode 100644 index 0e924f63..00000000 Binary files a/packs/gps-3rd-party-features/MANIFEST-001301 and /dev/null differ diff --git a/packs/gps-3rd-party-features/MANIFEST-001321 b/packs/gps-3rd-party-features/MANIFEST-001321 new file mode 100644 index 00000000..88f76a7f Binary files /dev/null and b/packs/gps-3rd-party-features/MANIFEST-001321 differ diff --git a/packs/gps-3rd-party-items/001307.log b/packs/gps-3rd-party-items/001327.log similarity index 100% rename from packs/gps-3rd-party-items/001307.log rename to packs/gps-3rd-party-items/001327.log diff --git a/packs/gps-3rd-party-items/CURRENT b/packs/gps-3rd-party-items/CURRENT index ea98df6c..7f93c213 100644 --- a/packs/gps-3rd-party-items/CURRENT +++ b/packs/gps-3rd-party-items/CURRENT @@ -1 +1 @@ -MANIFEST-001305 +MANIFEST-001325 diff --git a/packs/gps-3rd-party-items/LOG b/packs/gps-3rd-party-items/LOG index 5edabbf8..e84e0a6c 100644 --- a/packs/gps-3rd-party-items/LOG +++ b/packs/gps-3rd-party-items/LOG @@ -1,8 +1,8 @@ -2024/09/17-11:31:04.185 13050 Recovering log #1304 -2024/09/17-11:31:04.189 13050 Delete type=0 #1304 -2024/09/17-11:31:04.189 13050 Delete type=3 #1303 -2024/09/19-01:12:07.720 1147c Level-0 table #1308: started -2024/09/19-01:12:07.720 1147c Level-0 table #1308: 0 bytes OK -2024/09/19-01:12:07.723 1147c Delete type=0 #1306 -2024/09/19-01:12:07.728 1147c Manual compaction at level-0 from '!items!A4JIbc14vM5IKbuT' @ 72057594037927935 : 1 .. '!items.effects!qHY9RXV48OmvCrw1.UNiU6zoPTpbrxoIA' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.730 1147c Manual compaction at level-1 from '!items!A4JIbc14vM5IKbuT' @ 72057594037927935 : 1 .. '!items.effects!qHY9RXV48OmvCrw1.UNiU6zoPTpbrxoIA' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.033 13058 Recovering log #1323 +2024/09/21-16:17:33.037 13058 Delete type=0 #1323 +2024/09/21-16:17:33.037 13058 Delete type=3 #1321 +2024/09/21-21:27:43.314 1147c Level-0 table #1328: started +2024/09/21-21:27:43.314 1147c Level-0 table #1328: 0 bytes OK +2024/09/21-21:27:43.315 1147c Delete type=0 #1326 +2024/09/21-21:27:43.317 1147c Manual compaction at level-0 from '!items!A4JIbc14vM5IKbuT' @ 72057594037927935 : 1 .. '!items.effects!qHY9RXV48OmvCrw1.UNiU6zoPTpbrxoIA' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.321 1147c Manual compaction at level-1 from '!items!A4JIbc14vM5IKbuT' @ 72057594037927935 : 1 .. '!items.effects!qHY9RXV48OmvCrw1.UNiU6zoPTpbrxoIA' @ 0 : 0; will stop at (end) diff --git a/packs/gps-3rd-party-items/LOG.old b/packs/gps-3rd-party-items/LOG.old index a06c6089..edafbac0 100644 --- a/packs/gps-3rd-party-items/LOG.old +++ b/packs/gps-3rd-party-items/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.724 1df4 Recovering log #1301 -2024/09/17-10:53:01.732 1df4 Delete type=0 #1301 -2024/09/17-10:53:01.732 1df4 Delete type=3 #1299 +2024/09/21-16:06:48.849 13058 Recovering log #1319 +2024/09/21-16:06:48.852 13058 Delete type=0 #1319 +2024/09/21-16:06:48.852 13058 Delete type=3 #1317 +2024/09/21-16:14:51.156 1147c Level-0 table #1324: started +2024/09/21-16:14:51.156 1147c Level-0 table #1324: 0 bytes OK +2024/09/21-16:14:51.158 1147c Delete type=0 #1322 +2024/09/21-16:14:51.163 1147c Manual compaction at level-0 from '!items!A4JIbc14vM5IKbuT' @ 72057594037927935 : 1 .. '!items.effects!qHY9RXV48OmvCrw1.UNiU6zoPTpbrxoIA' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.163 1147c Manual compaction at level-1 from '!items!A4JIbc14vM5IKbuT' @ 72057594037927935 : 1 .. '!items.effects!qHY9RXV48OmvCrw1.UNiU6zoPTpbrxoIA' @ 0 : 0; will stop at (end) diff --git a/packs/gps-3rd-party-items/MANIFEST-001305 b/packs/gps-3rd-party-items/MANIFEST-001325 similarity index 76% rename from packs/gps-3rd-party-items/MANIFEST-001305 rename to packs/gps-3rd-party-items/MANIFEST-001325 index e7002cf5..d30bc39a 100644 Binary files a/packs/gps-3rd-party-items/MANIFEST-001305 and b/packs/gps-3rd-party-items/MANIFEST-001325 differ diff --git a/packs/gps-3rd-party-spells/001322.log b/packs/gps-3rd-party-spells/001342.log similarity index 100% rename from packs/gps-3rd-party-spells/001322.log rename to packs/gps-3rd-party-spells/001342.log diff --git a/packs/gps-3rd-party-spells/001295.ldb b/packs/gps-3rd-party-spells/001344.ldb similarity index 92% rename from packs/gps-3rd-party-spells/001295.ldb rename to packs/gps-3rd-party-spells/001344.ldb index e8db97e2..cf526814 100644 Binary files a/packs/gps-3rd-party-spells/001295.ldb and b/packs/gps-3rd-party-spells/001344.ldb differ diff --git a/packs/gps-3rd-party-spells/CURRENT b/packs/gps-3rd-party-spells/CURRENT index 4d7a8d6f..12770e7e 100644 --- a/packs/gps-3rd-party-spells/CURRENT +++ b/packs/gps-3rd-party-spells/CURRENT @@ -1 +1 @@ -MANIFEST-001320 +MANIFEST-001340 diff --git a/packs/gps-3rd-party-spells/LOG b/packs/gps-3rd-party-spells/LOG index d06b9362..f5b039c6 100644 --- a/packs/gps-3rd-party-spells/LOG +++ b/packs/gps-3rd-party-spells/LOG @@ -1,8 +1,15 @@ -2024/09/17-11:31:04.191 13054 Recovering log #1319 -2024/09/17-11:31:04.195 13054 Delete type=0 #1319 -2024/09/17-11:31:04.195 13054 Delete type=3 #1318 -2024/09/19-01:12:07.723 1147c Level-0 table #1323: started -2024/09/19-01:12:07.723 1147c Level-0 table #1323: 0 bytes OK -2024/09/19-01:12:07.725 1147c Delete type=0 #1321 -2024/09/19-01:12:07.728 1147c Manual compaction at level-0 from '!items!2YNbYocBRdEDgO4Q' @ 72057594037927935 : 1 .. '!items.effects!qBnx0VU4WBSLrGeK.zhzkM83QyjS4pBGp' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.730 1147c Manual compaction at level-1 from '!items!2YNbYocBRdEDgO4Q' @ 72057594037927935 : 1 .. '!items.effects!qBnx0VU4WBSLrGeK.zhzkM83QyjS4pBGp' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.040 13054 Recovering log #1338 +2024/09/21-16:17:33.045 13054 Delete type=0 #1338 +2024/09/21-16:17:33.045 13054 Delete type=3 #1336 +2024/09/21-21:27:43.311 1147c Level-0 table #1343: started +2024/09/21-21:27:43.312 1147c Level-0 table #1343: 2084 bytes OK +2024/09/21-21:27:43.313 1147c Delete type=0 #1341 +2024/09/21-21:27:43.317 1147c Manual compaction at level-0 from '!items!2YNbYocBRdEDgO4Q' @ 72057594037927935 : 1 .. '!items.effects!qBnx0VU4WBSLrGeK.zhzkM83QyjS4pBGp' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.317 1147c Manual compaction at level-1 from '!items!2YNbYocBRdEDgO4Q' @ 72057594037927935 : 1 .. '!items.effects!qBnx0VU4WBSLrGeK.zhzkM83QyjS4pBGp' @ 0 : 0; will stop at '!items!cd2wVsoS0pbfnbr5' @ 420 : 1 +2024/09/21-21:27:43.317 1147c Compacting 1@1 + 1@2 files +2024/09/21-21:27:43.320 1147c Generated table #1344@1: 34 keys, 80111 bytes +2024/09/21-21:27:43.320 1147c Compacted 1@1 + 1@2 files => 80111 bytes +2024/09/21-21:27:43.321 1147c compacted to: files[ 0 0 1 0 0 0 0 ] +2024/09/21-21:27:43.321 1147c Delete type=2 #1295 +2024/09/21-21:27:43.321 1147c Delete type=2 #1343 +2024/09/21-21:27:43.324 1147c Manual compaction at level-1 from '!items!cd2wVsoS0pbfnbr5' @ 420 : 1 .. '!items.effects!qBnx0VU4WBSLrGeK.zhzkM83QyjS4pBGp' @ 0 : 0; will stop at (end) diff --git a/packs/gps-3rd-party-spells/LOG.old b/packs/gps-3rd-party-spells/LOG.old index 78c360df..a90ed7c8 100644 --- a/packs/gps-3rd-party-spells/LOG.old +++ b/packs/gps-3rd-party-spells/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.742 19cc Recovering log #1316 -2024/09/17-10:53:01.751 19cc Delete type=0 #1316 -2024/09/17-10:53:01.752 19cc Delete type=3 #1314 +2024/09/21-16:06:48.854 1304c Recovering log #1334 +2024/09/21-16:06:48.858 1304c Delete type=0 #1334 +2024/09/21-16:06:48.858 1304c Delete type=3 #1332 +2024/09/21-16:14:51.153 1147c Level-0 table #1339: started +2024/09/21-16:14:51.153 1147c Level-0 table #1339: 0 bytes OK +2024/09/21-16:14:51.156 1147c Delete type=0 #1337 +2024/09/21-16:14:51.163 1147c Manual compaction at level-0 from '!items!2YNbYocBRdEDgO4Q' @ 72057594037927935 : 1 .. '!items.effects!qBnx0VU4WBSLrGeK.zhzkM83QyjS4pBGp' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.163 1147c Manual compaction at level-1 from '!items!2YNbYocBRdEDgO4Q' @ 72057594037927935 : 1 .. '!items.effects!qBnx0VU4WBSLrGeK.zhzkM83QyjS4pBGp' @ 0 : 0; will stop at (end) diff --git a/packs/gps-3rd-party-spells/MANIFEST-001320 b/packs/gps-3rd-party-spells/MANIFEST-001320 deleted file mode 100644 index e800e752..00000000 Binary files a/packs/gps-3rd-party-spells/MANIFEST-001320 and /dev/null differ diff --git a/packs/gps-3rd-party-spells/MANIFEST-001340 b/packs/gps-3rd-party-spells/MANIFEST-001340 new file mode 100644 index 00000000..f62d5478 Binary files /dev/null and b/packs/gps-3rd-party-spells/MANIFEST-001340 differ diff --git a/packs/gps-actors/001771.log b/packs/gps-actors/001791.log similarity index 100% rename from packs/gps-actors/001771.log rename to packs/gps-actors/001791.log diff --git a/packs/gps-actors/CURRENT b/packs/gps-actors/CURRENT index fefc654e..8bed4cfd 100644 --- a/packs/gps-actors/CURRENT +++ b/packs/gps-actors/CURRENT @@ -1 +1 @@ -MANIFEST-001769 +MANIFEST-001789 diff --git a/packs/gps-actors/LOG b/packs/gps-actors/LOG index 76f2d812..ffdba5f5 100644 --- a/packs/gps-actors/LOG +++ b/packs/gps-actors/LOG @@ -1,8 +1,8 @@ -2024/09/17-11:31:04.178 1304c Recovering log #1768 -2024/09/17-11:31:04.183 1304c Delete type=0 #1768 -2024/09/17-11:31:04.183 1304c Delete type=3 #1767 -2024/09/19-01:12:07.705 1147c Level-0 table #1772: started -2024/09/19-01:12:07.705 1147c Level-0 table #1772: 0 bytes OK -2024/09/19-01:12:07.707 1147c Delete type=0 #1770 -2024/09/19-01:12:07.714 1147c Manual compaction at level-0 from '!actors!2Q055cZ4Q4eMWCQT' @ 72057594037927935 : 1 .. '!actors.items.effects!2Q055cZ4Q4eMWCQT.icorevoMIkBVXL37.jFKhp34XZd32ryYT' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.714 1147c Manual compaction at level-1 from '!actors!2Q055cZ4Q4eMWCQT' @ 72057594037927935 : 1 .. '!actors.items.effects!2Q055cZ4Q4eMWCQT.icorevoMIkBVXL37.jFKhp34XZd32ryYT' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.027 13050 Recovering log #1787 +2024/09/21-16:17:33.030 13050 Delete type=0 #1787 +2024/09/21-16:17:33.030 13050 Delete type=3 #1785 +2024/09/21-21:27:43.308 1147c Level-0 table #1792: started +2024/09/21-21:27:43.308 1147c Level-0 table #1792: 0 bytes OK +2024/09/21-21:27:43.311 1147c Delete type=0 #1790 +2024/09/21-21:27:43.317 1147c Manual compaction at level-0 from '!actors!2Q055cZ4Q4eMWCQT' @ 72057594037927935 : 1 .. '!actors.items.effects!2Q055cZ4Q4eMWCQT.icorevoMIkBVXL37.jFKhp34XZd32ryYT' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.317 1147c Manual compaction at level-1 from '!actors!2Q055cZ4Q4eMWCQT' @ 72057594037927935 : 1 .. '!actors.items.effects!2Q055cZ4Q4eMWCQT.icorevoMIkBVXL37.jFKhp34XZd32ryYT' @ 0 : 0; will stop at (end) diff --git a/packs/gps-actors/LOG.old b/packs/gps-actors/LOG.old index 41071eaa..1f417550 100644 --- a/packs/gps-actors/LOG.old +++ b/packs/gps-actors/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.711 2468 Recovering log #1765 -2024/09/17-10:53:01.715 2468 Delete type=0 #1765 -2024/09/17-10:53:01.715 2468 Delete type=3 #1763 +2024/09/21-16:06:48.843 13054 Recovering log #1783 +2024/09/21-16:06:48.847 13054 Delete type=0 #1783 +2024/09/21-16:06:48.847 13054 Delete type=3 #1781 +2024/09/21-16:14:51.148 1147c Level-0 table #1788: started +2024/09/21-16:14:51.148 1147c Level-0 table #1788: 0 bytes OK +2024/09/21-16:14:51.150 1147c Delete type=0 #1786 +2024/09/21-16:14:51.151 1147c Manual compaction at level-0 from '!actors!2Q055cZ4Q4eMWCQT' @ 72057594037927935 : 1 .. '!actors.items.effects!2Q055cZ4Q4eMWCQT.icorevoMIkBVXL37.jFKhp34XZd32ryYT' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.151 1147c Manual compaction at level-1 from '!actors!2Q055cZ4Q4eMWCQT' @ 72057594037927935 : 1 .. '!actors.items.effects!2Q055cZ4Q4eMWCQT.icorevoMIkBVXL37.jFKhp34XZd32ryYT' @ 0 : 0; will stop at (end) diff --git a/packs/gps-actors/MANIFEST-001769 b/packs/gps-actors/MANIFEST-001789 similarity index 70% rename from packs/gps-actors/MANIFEST-001769 rename to packs/gps-actors/MANIFEST-001789 index b7ab0bd8..8142ebfd 100644 Binary files a/packs/gps-actors/MANIFEST-001769 and b/packs/gps-actors/MANIFEST-001789 differ diff --git a/packs/gps-class-features/002982.log b/packs/gps-class-features/003002.log similarity index 100% rename from packs/gps-class-features/002982.log rename to packs/gps-class-features/003002.log diff --git a/packs/gps-class-features/002973.ldb b/packs/gps-class-features/003004.ldb similarity index 60% rename from packs/gps-class-features/002973.ldb rename to packs/gps-class-features/003004.ldb index f535487d..a55495af 100644 Binary files a/packs/gps-class-features/002973.ldb and b/packs/gps-class-features/003004.ldb differ diff --git a/packs/gps-class-features/CURRENT b/packs/gps-class-features/CURRENT index f7a41738..691c9508 100644 --- a/packs/gps-class-features/CURRENT +++ b/packs/gps-class-features/CURRENT @@ -1 +1 @@ -MANIFEST-002980 +MANIFEST-003000 diff --git a/packs/gps-class-features/LOG b/packs/gps-class-features/LOG index e1750e1b..75330424 100644 --- a/packs/gps-class-features/LOG +++ b/packs/gps-class-features/LOG @@ -1,8 +1,15 @@ -2024/09/17-11:31:04.128 13050 Recovering log #2979 -2024/09/17-11:31:04.133 13050 Delete type=0 #2979 -2024/09/17-11:31:04.133 13050 Delete type=3 #2978 -2024/09/19-01:12:07.686 1147c Level-0 table #2983: started -2024/09/19-01:12:07.687 1147c Level-0 table #2983: 0 bytes OK -2024/09/19-01:12:07.688 1147c Delete type=0 #2981 -2024/09/19-01:12:07.688 1147c Manual compaction at level-0 from '!folders!89rvrtGjpBsZz1Tr' @ 72057594037927935 : 1 .. '!items.effects!ugNmjDFbPNnpG0CG.Z6aK5JHacSpklffP' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.689 1147c Manual compaction at level-1 from '!folders!89rvrtGjpBsZz1Tr' @ 72057594037927935 : 1 .. '!items.effects!ugNmjDFbPNnpG0CG.Z6aK5JHacSpklffP' @ 0 : 0; will stop at (end) +2024/09/21-16:17:32.981 13050 Recovering log #2998 +2024/09/21-16:17:32.985 13050 Delete type=0 #2998 +2024/09/21-16:17:32.985 13050 Delete type=3 #2996 +2024/09/21-21:27:43.271 1147c Level-0 table #3003: started +2024/09/21-21:27:43.273 1147c Level-0 table #3003: 30022 bytes OK +2024/09/21-21:27:43.275 1147c Delete type=0 #3001 +2024/09/21-21:27:43.281 1147c Manual compaction at level-0 from '!folders!89rvrtGjpBsZz1Tr' @ 72057594037927935 : 1 .. '!items.effects!ugNmjDFbPNnpG0CG.Z6aK5JHacSpklffP' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.281 1147c Manual compaction at level-1 from '!folders!89rvrtGjpBsZz1Tr' @ 72057594037927935 : 1 .. '!items.effects!ugNmjDFbPNnpG0CG.Z6aK5JHacSpklffP' @ 0 : 0; will stop at '!items!ncM5DuaY4k9S3pII' @ 983 : 1 +2024/09/21-21:27:43.281 1147c Compacting 1@1 + 1@2 files +2024/09/21-21:27:43.286 1147c Generated table #3004@1: 69 keys, 112294 bytes +2024/09/21-21:27:43.286 1147c Compacted 1@1 + 1@2 files => 112294 bytes +2024/09/21-21:27:43.287 1147c compacted to: files[ 0 0 1 0 0 0 0 ] +2024/09/21-21:27:43.287 1147c Delete type=2 #2973 +2024/09/21-21:27:43.287 1147c Delete type=2 #3003 +2024/09/21-21:27:43.294 1147c Manual compaction at level-1 from '!items!ncM5DuaY4k9S3pII' @ 983 : 1 .. '!items.effects!ugNmjDFbPNnpG0CG.Z6aK5JHacSpklffP' @ 0 : 0; will stop at (end) diff --git a/packs/gps-class-features/LOG.old b/packs/gps-class-features/LOG.old index 66da3f3d..8798a756 100644 --- a/packs/gps-class-features/LOG.old +++ b/packs/gps-class-features/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.645 2468 Recovering log #2976 -2024/09/17-10:53:01.650 2468 Delete type=0 #2976 -2024/09/17-10:53:01.650 2468 Delete type=3 #2974 +2024/09/21-16:06:48.791 13054 Recovering log #2994 +2024/09/21-16:06:48.798 13054 Delete type=0 #2994 +2024/09/21-16:06:48.798 13054 Delete type=3 #2992 +2024/09/21-16:14:51.122 1147c Level-0 table #2999: started +2024/09/21-16:14:51.123 1147c Level-0 table #2999: 0 bytes OK +2024/09/21-16:14:51.124 1147c Delete type=0 #2997 +2024/09/21-16:14:51.128 1147c Manual compaction at level-0 from '!folders!89rvrtGjpBsZz1Tr' @ 72057594037927935 : 1 .. '!items.effects!ugNmjDFbPNnpG0CG.Z6aK5JHacSpklffP' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.129 1147c Manual compaction at level-1 from '!folders!89rvrtGjpBsZz1Tr' @ 72057594037927935 : 1 .. '!items.effects!ugNmjDFbPNnpG0CG.Z6aK5JHacSpklffP' @ 0 : 0; will stop at (end) diff --git a/packs/gps-class-features/MANIFEST-002980 b/packs/gps-class-features/MANIFEST-002980 deleted file mode 100644 index 702d43d1..00000000 Binary files a/packs/gps-class-features/MANIFEST-002980 and /dev/null differ diff --git a/packs/gps-class-features/MANIFEST-003000 b/packs/gps-class-features/MANIFEST-003000 new file mode 100644 index 00000000..a0c3ac61 Binary files /dev/null and b/packs/gps-class-features/MANIFEST-003000 differ diff --git a/packs/gps-generic-features/003034.log b/packs/gps-generic-features/003054.log similarity index 100% rename from packs/gps-generic-features/003034.log rename to packs/gps-generic-features/003054.log diff --git a/packs/gps-generic-features/003025.ldb b/packs/gps-generic-features/003056.ldb similarity index 85% rename from packs/gps-generic-features/003025.ldb rename to packs/gps-generic-features/003056.ldb index be1ea62a..056f569c 100644 Binary files a/packs/gps-generic-features/003025.ldb and b/packs/gps-generic-features/003056.ldb differ diff --git a/packs/gps-generic-features/CURRENT b/packs/gps-generic-features/CURRENT index dc420445..20fde705 100644 --- a/packs/gps-generic-features/CURRENT +++ b/packs/gps-generic-features/CURRENT @@ -1 +1 @@ -MANIFEST-003032 +MANIFEST-003052 diff --git a/packs/gps-generic-features/LOG b/packs/gps-generic-features/LOG index 6263508a..58b0b150 100644 --- a/packs/gps-generic-features/LOG +++ b/packs/gps-generic-features/LOG @@ -1,8 +1,15 @@ -2024/09/17-11:31:04.154 13058 Recovering log #3031 -2024/09/17-11:31:04.159 13058 Delete type=0 #3031 -2024/09/17-11:31:04.159 13058 Delete type=3 #3030 -2024/09/19-01:12:07.692 1147c Level-0 table #3035: started -2024/09/19-01:12:07.693 1147c Level-0 table #3035: 0 bytes OK -2024/09/19-01:12:07.694 1147c Delete type=0 #3033 -2024/09/19-01:12:07.699 1147c Manual compaction at level-0 from '!items!0XoQ7lGPSwjM8Gw4' @ 72057594037927935 : 1 .. '!items.effects!svKaRfNtOXMOXoW6.NcYMpQ7B3RwBuLC7' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.699 1147c Manual compaction at level-1 from '!items!0XoQ7lGPSwjM8Gw4' @ 72057594037927935 : 1 .. '!items.effects!svKaRfNtOXMOXoW6.NcYMpQ7B3RwBuLC7' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.005 1304c Recovering log #3050 +2024/09/21-16:17:33.009 1304c Delete type=0 #3050 +2024/09/21-16:17:33.009 1304c Delete type=3 #3048 +2024/09/21-21:27:43.294 1147c Level-0 table #3055: started +2024/09/21-21:27:43.296 1147c Level-0 table #3055: 5912 bytes OK +2024/09/21-21:27:43.298 1147c Delete type=0 #3053 +2024/09/21-21:27:43.300 1147c Manual compaction at level-0 from '!items!0XoQ7lGPSwjM8Gw4' @ 72057594037927935 : 1 .. '!items.effects!svKaRfNtOXMOXoW6.NcYMpQ7B3RwBuLC7' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.302 1147c Manual compaction at level-1 from '!items!0XoQ7lGPSwjM8Gw4' @ 72057594037927935 : 1 .. '!items.effects!svKaRfNtOXMOXoW6.NcYMpQ7B3RwBuLC7' @ 0 : 0; will stop at '!items!iuUGS62pqYBuo1U0' @ 656 : 1 +2024/09/21-21:27:43.302 1147c Compacting 1@1 + 1@2 files +2024/09/21-21:27:43.304 1147c Generated table #3056@1: 14 keys, 18975 bytes +2024/09/21-21:27:43.304 1147c Compacted 1@1 + 1@2 files => 18975 bytes +2024/09/21-21:27:43.306 1147c compacted to: files[ 0 0 1 0 0 0 0 ] +2024/09/21-21:27:43.306 1147c Delete type=2 #3025 +2024/09/21-21:27:43.306 1147c Delete type=2 #3055 +2024/09/21-21:27:43.307 1147c Manual compaction at level-1 from '!items!iuUGS62pqYBuo1U0' @ 656 : 1 .. '!items.effects!svKaRfNtOXMOXoW6.NcYMpQ7B3RwBuLC7' @ 0 : 0; will stop at (end) diff --git a/packs/gps-generic-features/LOG.old b/packs/gps-generic-features/LOG.old index b55e0230..d1f2855f 100644 --- a/packs/gps-generic-features/LOG.old +++ b/packs/gps-generic-features/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.677 60f8 Recovering log #3028 -2024/09/17-10:53:01.682 60f8 Delete type=0 #3028 -2024/09/17-10:53:01.682 60f8 Delete type=3 #3026 +2024/09/21-16:06:48.819 13050 Recovering log #3046 +2024/09/21-16:06:48.823 13050 Delete type=0 #3046 +2024/09/21-16:06:48.823 13050 Delete type=3 #3044 +2024/09/21-16:14:51.137 1147c Level-0 table #3051: started +2024/09/21-16:14:51.137 1147c Level-0 table #3051: 0 bytes OK +2024/09/21-16:14:51.139 1147c Delete type=0 #3049 +2024/09/21-16:14:51.140 1147c Manual compaction at level-0 from '!items!0XoQ7lGPSwjM8Gw4' @ 72057594037927935 : 1 .. '!items.effects!svKaRfNtOXMOXoW6.NcYMpQ7B3RwBuLC7' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.140 1147c Manual compaction at level-1 from '!items!0XoQ7lGPSwjM8Gw4' @ 72057594037927935 : 1 .. '!items.effects!svKaRfNtOXMOXoW6.NcYMpQ7B3RwBuLC7' @ 0 : 0; will stop at (end) diff --git a/packs/gps-generic-features/MANIFEST-003032 b/packs/gps-generic-features/MANIFEST-003032 deleted file mode 100644 index 0ba14ea3..00000000 Binary files a/packs/gps-generic-features/MANIFEST-003032 and /dev/null differ diff --git a/packs/gps-generic-features/MANIFEST-003052 b/packs/gps-generic-features/MANIFEST-003052 new file mode 100644 index 00000000..7084d16c Binary files /dev/null and b/packs/gps-generic-features/MANIFEST-003052 differ diff --git a/packs/gps-homebrew-features/002938.log b/packs/gps-homebrew-features/002958.log similarity index 100% rename from packs/gps-homebrew-features/002938.log rename to packs/gps-homebrew-features/002958.log diff --git a/packs/gps-homebrew-features/CURRENT b/packs/gps-homebrew-features/CURRENT index 2cd0cae6..7440e6ed 100644 --- a/packs/gps-homebrew-features/CURRENT +++ b/packs/gps-homebrew-features/CURRENT @@ -1 +1 @@ -MANIFEST-002936 +MANIFEST-002956 diff --git a/packs/gps-homebrew-features/LOG b/packs/gps-homebrew-features/LOG index 179446e4..ebf682f0 100644 --- a/packs/gps-homebrew-features/LOG +++ b/packs/gps-homebrew-features/LOG @@ -1,8 +1,8 @@ -2024/09/17-11:31:04.160 1304c Recovering log #2935 -2024/09/17-11:31:04.164 1304c Delete type=0 #2935 -2024/09/17-11:31:04.164 1304c Delete type=3 #2934 -2024/09/19-01:12:07.700 1147c Level-0 table #2939: started -2024/09/19-01:12:07.700 1147c Level-0 table #2939: 0 bytes OK -2024/09/19-01:12:07.705 1147c Delete type=0 #2937 -2024/09/19-01:12:07.714 1147c Manual compaction at level-0 from '!folders!4OzV9QdsPgTyK99q' @ 72057594037927935 : 1 .. '!items.effects!fwJjg1xtQFZupjbV.vhj7xJmCiTIagALN' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.714 1147c Manual compaction at level-1 from '!folders!4OzV9QdsPgTyK99q' @ 72057594037927935 : 1 .. '!items.effects!fwJjg1xtQFZupjbV.vhj7xJmCiTIagALN' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.010 13054 Recovering log #2954 +2024/09/21-16:17:33.014 13054 Delete type=0 #2954 +2024/09/21-16:17:33.014 13054 Delete type=3 #2952 +2024/09/21-21:27:43.298 1147c Level-0 table #2959: started +2024/09/21-21:27:43.298 1147c Level-0 table #2959: 0 bytes OK +2024/09/21-21:27:43.300 1147c Delete type=0 #2957 +2024/09/21-21:27:43.302 1147c Manual compaction at level-0 from '!folders!4OzV9QdsPgTyK99q' @ 72057594037927935 : 1 .. '!items.effects!fwJjg1xtQFZupjbV.vhj7xJmCiTIagALN' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.307 1147c Manual compaction at level-1 from '!folders!4OzV9QdsPgTyK99q' @ 72057594037927935 : 1 .. '!items.effects!fwJjg1xtQFZupjbV.vhj7xJmCiTIagALN' @ 0 : 0; will stop at (end) diff --git a/packs/gps-homebrew-features/LOG.old b/packs/gps-homebrew-features/LOG.old index 19bd70d1..0d5d8354 100644 --- a/packs/gps-homebrew-features/LOG.old +++ b/packs/gps-homebrew-features/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.685 19cc Recovering log #2932 -2024/09/17-10:53:01.690 19cc Delete type=0 #2932 -2024/09/17-10:53:01.690 19cc Delete type=3 #2930 +2024/09/21-16:06:48.824 1304c Recovering log #2950 +2024/09/21-16:06:48.828 1304c Delete type=0 #2950 +2024/09/21-16:06:48.828 1304c Delete type=3 #2948 +2024/09/21-16:14:51.143 1147c Level-0 table #2955: started +2024/09/21-16:14:51.143 1147c Level-0 table #2955: 0 bytes OK +2024/09/21-16:14:51.145 1147c Delete type=0 #2953 +2024/09/21-16:14:51.151 1147c Manual compaction at level-0 from '!folders!4OzV9QdsPgTyK99q' @ 72057594037927935 : 1 .. '!items.effects!fwJjg1xtQFZupjbV.vhj7xJmCiTIagALN' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.151 1147c Manual compaction at level-1 from '!folders!4OzV9QdsPgTyK99q' @ 72057594037927935 : 1 .. '!items.effects!fwJjg1xtQFZupjbV.vhj7xJmCiTIagALN' @ 0 : 0; will stop at (end) diff --git a/packs/gps-homebrew-features/MANIFEST-002936 b/packs/gps-homebrew-features/MANIFEST-002956 similarity index 66% rename from packs/gps-homebrew-features/MANIFEST-002936 rename to packs/gps-homebrew-features/MANIFEST-002956 index bdc7949f..28e0b858 100644 Binary files a/packs/gps-homebrew-features/MANIFEST-002936 and b/packs/gps-homebrew-features/MANIFEST-002956 differ diff --git a/packs/gps-homebrew-items/002944.log b/packs/gps-homebrew-items/002965.log similarity index 100% rename from packs/gps-homebrew-items/002944.log rename to packs/gps-homebrew-items/002965.log diff --git a/packs/gps-homebrew-items/CURRENT b/packs/gps-homebrew-items/CURRENT index 37e0c8f4..2ae4cb05 100644 --- a/packs/gps-homebrew-items/CURRENT +++ b/packs/gps-homebrew-items/CURRENT @@ -1 +1 @@ -MANIFEST-002942 +MANIFEST-002963 diff --git a/packs/gps-homebrew-items/LOG b/packs/gps-homebrew-items/LOG index ec7b7220..32dabca4 100644 --- a/packs/gps-homebrew-items/LOG +++ b/packs/gps-homebrew-items/LOG @@ -1,15 +1,8 @@ -2024/09/17-11:31:04.166 13050 Recovering log #2941 -2024/09/17-11:31:04.170 13050 Delete type=0 #2941 -2024/09/17-11:31:04.170 13050 Delete type=3 #2940 -2024/09/19-01:12:07.707 1147c Level-0 table #2945: started -2024/09/19-01:12:07.709 1147c Level-0 table #2945: 12973 bytes OK -2024/09/19-01:12:07.711 1147c Delete type=0 #2943 -2024/09/19-01:12:07.714 1147c Manual compaction at level-0 from '!items!1WSJjnpLJhilXEgO' @ 72057594037927935 : 1 .. '!items.effects!zEXJxqsAmVM7Pohu.v3j3orDGcbQyk7ZI' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.714 1147c Manual compaction at level-1 from '!items!1WSJjnpLJhilXEgO' @ 72057594037927935 : 1 .. '!items.effects!zEXJxqsAmVM7Pohu.v3j3orDGcbQyk7ZI' @ 0 : 0; will stop at '!items.effects!CoYpAaVmu8WymKah.fRzfKB7OFT8zJ2aH' @ 513 : 1 -2024/09/19-01:12:07.714 1147c Compacting 1@1 + 1@2 files -2024/09/19-01:12:07.717 1147c Generated table #2946@1: 25 keys, 42455 bytes -2024/09/19-01:12:07.717 1147c Compacted 1@1 + 1@2 files => 42455 bytes -2024/09/19-01:12:07.719 1147c compacted to: files[ 0 0 1 0 0 0 0 ] -2024/09/19-01:12:07.719 1147c Delete type=2 #2921 -2024/09/19-01:12:07.720 1147c Delete type=2 #2945 -2024/09/19-01:12:07.725 1147c Manual compaction at level-1 from '!items.effects!CoYpAaVmu8WymKah.fRzfKB7OFT8zJ2aH' @ 513 : 1 .. '!items.effects!zEXJxqsAmVM7Pohu.v3j3orDGcbQyk7ZI' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.016 13058 Recovering log #2961 +2024/09/21-16:17:33.020 13058 Delete type=0 #2961 +2024/09/21-16:17:33.020 13058 Delete type=3 #2959 +2024/09/21-21:27:43.300 1147c Level-0 table #2966: started +2024/09/21-21:27:43.300 1147c Level-0 table #2966: 0 bytes OK +2024/09/21-21:27:43.302 1147c Delete type=0 #2964 +2024/09/21-21:27:43.307 1147c Manual compaction at level-0 from '!items!1WSJjnpLJhilXEgO' @ 72057594037927935 : 1 .. '!items.effects!zEXJxqsAmVM7Pohu.v3j3orDGcbQyk7ZI' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.307 1147c Manual compaction at level-1 from '!items!1WSJjnpLJhilXEgO' @ 72057594037927935 : 1 .. '!items.effects!zEXJxqsAmVM7Pohu.v3j3orDGcbQyk7ZI' @ 0 : 0; will stop at (end) diff --git a/packs/gps-homebrew-items/LOG.old b/packs/gps-homebrew-items/LOG.old index 4dea24af..a8037b14 100644 --- a/packs/gps-homebrew-items/LOG.old +++ b/packs/gps-homebrew-items/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.693 1df4 Recovering log #2938 -2024/09/17-10:53:01.698 1df4 Delete type=0 #2938 -2024/09/17-10:53:01.698 1df4 Delete type=3 #2936 +2024/09/21-16:06:48.830 13058 Recovering log #2957 +2024/09/21-16:06:48.834 13058 Delete type=0 #2957 +2024/09/21-16:06:48.834 13058 Delete type=3 #2955 +2024/09/21-16:14:51.141 1147c Level-0 table #2962: started +2024/09/21-16:14:51.141 1147c Level-0 table #2962: 0 bytes OK +2024/09/21-16:14:51.143 1147c Delete type=0 #2960 +2024/09/21-16:14:51.151 1147c Manual compaction at level-0 from '!items!1WSJjnpLJhilXEgO' @ 72057594037927935 : 1 .. '!items.effects!zEXJxqsAmVM7Pohu.v3j3orDGcbQyk7ZI' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.151 1147c Manual compaction at level-1 from '!items!1WSJjnpLJhilXEgO' @ 72057594037927935 : 1 .. '!items.effects!zEXJxqsAmVM7Pohu.v3j3orDGcbQyk7ZI' @ 0 : 0; will stop at (end) diff --git a/packs/gps-homebrew-items/MANIFEST-002942 b/packs/gps-homebrew-items/MANIFEST-002942 deleted file mode 100644 index e42c04d0..00000000 Binary files a/packs/gps-homebrew-items/MANIFEST-002942 and /dev/null differ diff --git a/packs/gps-homebrew-items/MANIFEST-002963 b/packs/gps-homebrew-items/MANIFEST-002963 new file mode 100644 index 00000000..467c0fb0 Binary files /dev/null and b/packs/gps-homebrew-items/MANIFEST-002963 differ diff --git a/packs/gps-homebrew-spells/002605.log b/packs/gps-homebrew-spells/002625.log similarity index 100% rename from packs/gps-homebrew-spells/002605.log rename to packs/gps-homebrew-spells/002625.log diff --git a/packs/gps-homebrew-spells/CURRENT b/packs/gps-homebrew-spells/CURRENT index 0bae93e2..0b50b321 100644 --- a/packs/gps-homebrew-spells/CURRENT +++ b/packs/gps-homebrew-spells/CURRENT @@ -1 +1 @@ -MANIFEST-002603 +MANIFEST-002623 diff --git a/packs/gps-homebrew-spells/LOG b/packs/gps-homebrew-spells/LOG index 8318016c..33d7f163 100644 --- a/packs/gps-homebrew-spells/LOG +++ b/packs/gps-homebrew-spells/LOG @@ -1,8 +1,8 @@ -2024/09/17-11:31:04.172 13054 Recovering log #2602 -2024/09/17-11:31:04.176 13054 Delete type=0 #2602 -2024/09/17-11:31:04.176 13054 Delete type=3 #2601 -2024/09/19-01:12:07.711 1147c Level-0 table #2606: started -2024/09/19-01:12:07.712 1147c Level-0 table #2606: 0 bytes OK -2024/09/19-01:12:07.713 1147c Delete type=0 #2604 -2024/09/19-01:12:07.714 1147c Manual compaction at level-0 from '!items!iVqgFn89rGOnPTK4' @ 72057594037927935 : 1 .. '!items.effects!iVqgFn89rGOnPTK4.Ka4crf96KPf0p7Uc' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.720 1147c Manual compaction at level-1 from '!items!iVqgFn89rGOnPTK4' @ 72057594037927935 : 1 .. '!items.effects!iVqgFn89rGOnPTK4.Ka4crf96KPf0p7Uc' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.022 1304c Recovering log #2621 +2024/09/21-16:17:33.025 1304c Delete type=0 #2621 +2024/09/21-16:17:33.025 1304c Delete type=3 #2619 +2024/09/21-21:27:43.306 1147c Level-0 table #2626: started +2024/09/21-21:27:43.306 1147c Level-0 table #2626: 0 bytes OK +2024/09/21-21:27:43.307 1147c Delete type=0 #2624 +2024/09/21-21:27:43.307 1147c Manual compaction at level-0 from '!items!iVqgFn89rGOnPTK4' @ 72057594037927935 : 1 .. '!items.effects!iVqgFn89rGOnPTK4.Ka4crf96KPf0p7Uc' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.307 1147c Manual compaction at level-1 from '!items!iVqgFn89rGOnPTK4' @ 72057594037927935 : 1 .. '!items.effects!iVqgFn89rGOnPTK4.Ka4crf96KPf0p7Uc' @ 0 : 0; will stop at (end) diff --git a/packs/gps-homebrew-spells/LOG.old b/packs/gps-homebrew-spells/LOG.old index 40fa57dd..63326428 100644 --- a/packs/gps-homebrew-spells/LOG.old +++ b/packs/gps-homebrew-spells/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.701 60f8 Recovering log #2599 -2024/09/17-10:53:01.708 60f8 Delete type=0 #2599 -2024/09/17-10:53:01.708 60f8 Delete type=3 #2597 +2024/09/21-16:06:48.836 13050 Recovering log #2617 +2024/09/21-16:06:48.841 13050 Delete type=0 #2617 +2024/09/21-16:06:48.841 13050 Delete type=3 #2615 +2024/09/21-16:14:51.146 1147c Level-0 table #2622: started +2024/09/21-16:14:51.146 1147c Level-0 table #2622: 0 bytes OK +2024/09/21-16:14:51.148 1147c Delete type=0 #2620 +2024/09/21-16:14:51.151 1147c Manual compaction at level-0 from '!items!iVqgFn89rGOnPTK4' @ 72057594037927935 : 1 .. '!items.effects!iVqgFn89rGOnPTK4.Ka4crf96KPf0p7Uc' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.151 1147c Manual compaction at level-1 from '!items!iVqgFn89rGOnPTK4' @ 72057594037927935 : 1 .. '!items.effects!iVqgFn89rGOnPTK4.Ka4crf96KPf0p7Uc' @ 0 : 0; will stop at (end) diff --git a/packs/gps-homebrew-spells/MANIFEST-002603 b/packs/gps-homebrew-spells/MANIFEST-002623 similarity index 56% rename from packs/gps-homebrew-spells/MANIFEST-002603 rename to packs/gps-homebrew-spells/MANIFEST-002623 index e64513bf..b18c2523 100644 Binary files a/packs/gps-homebrew-spells/MANIFEST-002603 and b/packs/gps-homebrew-spells/MANIFEST-002623 differ diff --git a/packs/gps-items/002943.log b/packs/gps-items/002963.log similarity index 100% rename from packs/gps-items/002943.log rename to packs/gps-items/002963.log diff --git a/packs/gps-items/CURRENT b/packs/gps-items/CURRENT index 6cf77b28..788ee915 100644 --- a/packs/gps-items/CURRENT +++ b/packs/gps-items/CURRENT @@ -1 +1 @@ -MANIFEST-002941 +MANIFEST-002961 diff --git a/packs/gps-items/LOG b/packs/gps-items/LOG index bf506110..5a3568ae 100644 --- a/packs/gps-items/LOG +++ b/packs/gps-items/LOG @@ -1,8 +1,8 @@ -2024/09/17-11:31:04.136 13058 Recovering log #2940 -2024/09/17-11:31:04.140 13058 Delete type=0 #2940 -2024/09/17-11:31:04.140 13058 Delete type=3 #2939 -2024/09/19-01:12:07.690 1147c Level-0 table #2944: started -2024/09/19-01:12:07.690 1147c Level-0 table #2944: 0 bytes OK -2024/09/19-01:12:07.692 1147c Delete type=0 #2942 -2024/09/19-01:12:07.699 1147c Manual compaction at level-0 from '!items!0qTQDQ2Cipf15JGW' @ 72057594037927935 : 1 .. '!items.effects!wds22ulA8PSTvYWP.ZrTNMwai89gqFKJo' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.699 1147c Manual compaction at level-1 from '!items!0qTQDQ2Cipf15JGW' @ 72057594037927935 : 1 .. '!items.effects!wds22ulA8PSTvYWP.ZrTNMwai89gqFKJo' @ 0 : 0; will stop at (end) +2024/09/21-16:17:32.988 13058 Recovering log #2959 +2024/09/21-16:17:32.992 13058 Delete type=0 #2959 +2024/09/21-16:17:32.992 13058 Delete type=3 #2957 +2024/09/21-21:27:43.275 1147c Level-0 table #2964: started +2024/09/21-21:27:43.275 1147c Level-0 table #2964: 0 bytes OK +2024/09/21-21:27:43.277 1147c Delete type=0 #2962 +2024/09/21-21:27:43.281 1147c Manual compaction at level-0 from '!items!0qTQDQ2Cipf15JGW' @ 72057594037927935 : 1 .. '!items.effects!wds22ulA8PSTvYWP.ZrTNMwai89gqFKJo' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.287 1147c Manual compaction at level-1 from '!items!0qTQDQ2Cipf15JGW' @ 72057594037927935 : 1 .. '!items.effects!wds22ulA8PSTvYWP.ZrTNMwai89gqFKJo' @ 0 : 0; will stop at (end) diff --git a/packs/gps-items/LOG.old b/packs/gps-items/LOG.old index 2e2fd15d..4f29c959 100644 --- a/packs/gps-items/LOG.old +++ b/packs/gps-items/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.653 60f8 Recovering log #2937 -2024/09/17-10:53:01.658 60f8 Delete type=0 #2937 -2024/09/17-10:53:01.658 60f8 Delete type=3 #2935 +2024/09/21-16:06:48.802 13058 Recovering log #2955 +2024/09/21-16:06:48.805 13058 Delete type=0 #2955 +2024/09/21-16:06:48.806 13058 Delete type=3 #2953 +2024/09/21-16:14:51.130 1147c Level-0 table #2960: started +2024/09/21-16:14:51.130 1147c Level-0 table #2960: 0 bytes OK +2024/09/21-16:14:51.133 1147c Delete type=0 #2958 +2024/09/21-16:14:51.140 1147c Manual compaction at level-0 from '!items!0qTQDQ2Cipf15JGW' @ 72057594037927935 : 1 .. '!items.effects!wds22ulA8PSTvYWP.ZrTNMwai89gqFKJo' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.140 1147c Manual compaction at level-1 from '!items!0qTQDQ2Cipf15JGW' @ 72057594037927935 : 1 .. '!items.effects!wds22ulA8PSTvYWP.ZrTNMwai89gqFKJo' @ 0 : 0; will stop at (end) diff --git a/packs/gps-items/MANIFEST-002941 b/packs/gps-items/MANIFEST-002961 similarity index 63% rename from packs/gps-items/MANIFEST-002941 rename to packs/gps-items/MANIFEST-002961 index 64080efa..f197d23e 100644 Binary files a/packs/gps-items/MANIFEST-002941 and b/packs/gps-items/MANIFEST-002961 differ diff --git a/packs/gps-monster-features/002937.log b/packs/gps-monster-features/002957.log similarity index 100% rename from packs/gps-monster-features/002937.log rename to packs/gps-monster-features/002957.log diff --git a/packs/gps-monster-features/CURRENT b/packs/gps-monster-features/CURRENT index 8c0950dc..449eea24 100644 --- a/packs/gps-monster-features/CURRENT +++ b/packs/gps-monster-features/CURRENT @@ -1 +1 @@ -MANIFEST-002935 +MANIFEST-002955 diff --git a/packs/gps-monster-features/LOG b/packs/gps-monster-features/LOG index 792b47cd..0de0aa8e 100644 --- a/packs/gps-monster-features/LOG +++ b/packs/gps-monster-features/LOG @@ -1,8 +1,8 @@ -2024/09/17-11:31:04.149 13050 Recovering log #2934 -2024/09/17-11:31:04.152 13050 Delete type=0 #2934 -2024/09/17-11:31:04.152 13050 Delete type=3 #2933 -2024/09/19-01:12:07.697 1147c Level-0 table #2938: started -2024/09/19-01:12:07.697 1147c Level-0 table #2938: 0 bytes OK -2024/09/19-01:12:07.699 1147c Delete type=0 #2936 -2024/09/19-01:12:07.699 1147c Manual compaction at level-0 from '!folders!44lJ4L7xySVYZzED' @ 72057594037927935 : 1 .. '!items.effects!yp0IIuvsEkJd6KKW.WlySPDKKWMIOowHi' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.699 1147c Manual compaction at level-1 from '!folders!44lJ4L7xySVYZzED' @ 72057594037927935 : 1 .. '!items.effects!yp0IIuvsEkJd6KKW.WlySPDKKWMIOowHi' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.000 13050 Recovering log #2953 +2024/09/21-16:17:33.003 13050 Delete type=0 #2953 +2024/09/21-16:17:33.003 13050 Delete type=3 #2951 +2024/09/21-21:27:43.292 1147c Level-0 table #2958: started +2024/09/21-21:27:43.292 1147c Level-0 table #2958: 0 bytes OK +2024/09/21-21:27:43.293 1147c Delete type=0 #2956 +2024/09/21-21:27:43.298 1147c Manual compaction at level-0 from '!folders!44lJ4L7xySVYZzED' @ 72057594037927935 : 1 .. '!items.effects!yp0IIuvsEkJd6KKW.WlySPDKKWMIOowHi' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.300 1147c Manual compaction at level-1 from '!folders!44lJ4L7xySVYZzED' @ 72057594037927935 : 1 .. '!items.effects!yp0IIuvsEkJd6KKW.WlySPDKKWMIOowHi' @ 0 : 0; will stop at (end) diff --git a/packs/gps-monster-features/LOG.old b/packs/gps-monster-features/LOG.old index d94c69a1..c2e3f5ea 100644 --- a/packs/gps-monster-features/LOG.old +++ b/packs/gps-monster-features/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.668 1df4 Recovering log #2931 -2024/09/17-10:53:01.674 1df4 Delete type=0 #2931 -2024/09/17-10:53:01.674 1df4 Delete type=3 #2929 +2024/09/21-16:06:48.813 13054 Recovering log #2949 +2024/09/21-16:06:48.817 13054 Delete type=0 #2949 +2024/09/21-16:06:48.817 13054 Delete type=3 #2947 +2024/09/21-16:14:51.135 1147c Level-0 table #2954: started +2024/09/21-16:14:51.135 1147c Level-0 table #2954: 0 bytes OK +2024/09/21-16:14:51.137 1147c Delete type=0 #2952 +2024/09/21-16:14:51.140 1147c Manual compaction at level-0 from '!folders!44lJ4L7xySVYZzED' @ 72057594037927935 : 1 .. '!items.effects!yp0IIuvsEkJd6KKW.WlySPDKKWMIOowHi' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.140 1147c Manual compaction at level-1 from '!folders!44lJ4L7xySVYZzED' @ 72057594037927935 : 1 .. '!items.effects!yp0IIuvsEkJd6KKW.WlySPDKKWMIOowHi' @ 0 : 0; will stop at (end) diff --git a/packs/gps-monster-features/MANIFEST-002935 b/packs/gps-monster-features/MANIFEST-002955 similarity index 66% rename from packs/gps-monster-features/MANIFEST-002935 rename to packs/gps-monster-features/MANIFEST-002955 index ec23af0d..8c9da18a 100644 Binary files a/packs/gps-monster-features/MANIFEST-002935 and b/packs/gps-monster-features/MANIFEST-002955 differ diff --git a/packs/gps-race-features/000641.log b/packs/gps-race-features/000661.log similarity index 100% rename from packs/gps-race-features/000641.log rename to packs/gps-race-features/000661.log diff --git a/packs/gps-race-features/CURRENT b/packs/gps-race-features/CURRENT index 948a2c2b..66197ad1 100644 --- a/packs/gps-race-features/CURRENT +++ b/packs/gps-race-features/CURRENT @@ -1 +1 @@ -MANIFEST-000639 +MANIFEST-000659 diff --git a/packs/gps-race-features/LOG b/packs/gps-race-features/LOG index f022b3d4..47ea3b02 100644 --- a/packs/gps-race-features/LOG +++ b/packs/gps-race-features/LOG @@ -1,8 +1,8 @@ -2024/09/17-11:31:04.197 1304c Recovering log #638 -2024/09/17-11:31:04.201 1304c Delete type=0 #638 -2024/09/17-11:31:04.201 1304c Delete type=3 #637 -2024/09/19-01:12:07.725 1147c Level-0 table #642: started -2024/09/19-01:12:07.726 1147c Level-0 table #642: 0 bytes OK -2024/09/19-01:12:07.727 1147c Delete type=0 #640 -2024/09/19-01:12:07.730 1147c Manual compaction at level-0 from '!folders!62e2gLQ8cttarHZ8' @ 72057594037927935 : 1 .. '!items.effects!wNuwXPqCsshIcO2V.nGhKXGlzLbZGIsKu' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.730 1147c Manual compaction at level-1 from '!folders!62e2gLQ8cttarHZ8' @ 72057594037927935 : 1 .. '!items.effects!wNuwXPqCsshIcO2V.nGhKXGlzLbZGIsKu' @ 0 : 0; will stop at (end) +2024/09/21-16:17:33.048 13050 Recovering log #657 +2024/09/21-16:17:33.052 13050 Delete type=0 #657 +2024/09/21-16:17:33.052 13050 Delete type=3 #655 +2024/09/21-21:27:43.315 1147c Level-0 table #662: started +2024/09/21-21:27:43.315 1147c Level-0 table #662: 0 bytes OK +2024/09/21-21:27:43.317 1147c Delete type=0 #660 +2024/09/21-21:27:43.317 1147c Manual compaction at level-0 from '!folders!62e2gLQ8cttarHZ8' @ 72057594037927935 : 1 .. '!items.effects!wNuwXPqCsshIcO2V.nGhKXGlzLbZGIsKu' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.321 1147c Manual compaction at level-1 from '!folders!62e2gLQ8cttarHZ8' @ 72057594037927935 : 1 .. '!items.effects!wNuwXPqCsshIcO2V.nGhKXGlzLbZGIsKu' @ 0 : 0; will stop at (end) diff --git a/packs/gps-race-features/LOG.old b/packs/gps-race-features/LOG.old index 5209448c..28d5e868 100644 --- a/packs/gps-race-features/LOG.old +++ b/packs/gps-race-features/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.768 2468 Recovering log #635 -2024/09/17-10:53:01.776 2468 Delete type=0 #635 -2024/09/17-10:53:01.776 2468 Delete type=3 #633 +2024/09/21-16:06:48.861 13054 Recovering log #653 +2024/09/21-16:06:48.865 13054 Delete type=0 #653 +2024/09/21-16:06:48.865 13054 Delete type=3 #651 +2024/09/21-16:14:51.158 1147c Level-0 table #658: started +2024/09/21-16:14:51.158 1147c Level-0 table #658: 0 bytes OK +2024/09/21-16:14:51.160 1147c Delete type=0 #656 +2024/09/21-16:14:51.163 1147c Manual compaction at level-0 from '!folders!62e2gLQ8cttarHZ8' @ 72057594037927935 : 1 .. '!items.effects!wNuwXPqCsshIcO2V.nGhKXGlzLbZGIsKu' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.163 1147c Manual compaction at level-1 from '!folders!62e2gLQ8cttarHZ8' @ 72057594037927935 : 1 .. '!items.effects!wNuwXPqCsshIcO2V.nGhKXGlzLbZGIsKu' @ 0 : 0; will stop at (end) diff --git a/packs/gps-race-features/MANIFEST-000639 b/packs/gps-race-features/MANIFEST-000659 similarity index 56% rename from packs/gps-race-features/MANIFEST-000639 rename to packs/gps-race-features/MANIFEST-000659 index ab53192f..c41fc11d 100644 Binary files a/packs/gps-race-features/MANIFEST-000639 and b/packs/gps-race-features/MANIFEST-000659 differ diff --git a/packs/gps-spells/003026.log b/packs/gps-spells/003047.log similarity index 100% rename from packs/gps-spells/003026.log rename to packs/gps-spells/003047.log diff --git a/packs/gps-spells/003003.ldb b/packs/gps-spells/003049.ldb similarity index 91% rename from packs/gps-spells/003003.ldb rename to packs/gps-spells/003049.ldb index 6bcd0499..895044ff 100644 Binary files a/packs/gps-spells/003003.ldb and b/packs/gps-spells/003049.ldb differ diff --git a/packs/gps-spells/CURRENT b/packs/gps-spells/CURRENT index fada3407..f697631c 100644 --- a/packs/gps-spells/CURRENT +++ b/packs/gps-spells/CURRENT @@ -1 +1 @@ -MANIFEST-003024 +MANIFEST-003045 diff --git a/packs/gps-spells/LOG b/packs/gps-spells/LOG index 227e4dcb..aefa910f 100644 --- a/packs/gps-spells/LOG +++ b/packs/gps-spells/LOG @@ -1,8 +1,15 @@ -2024/09/17-11:31:04.123 13054 Recovering log #3023 -2024/09/17-11:31:04.126 13054 Delete type=0 #3023 -2024/09/17-11:31:04.126 13054 Delete type=3 #3022 -2024/09/19-01:12:07.683 1147c Level-0 table #3027: started -2024/09/19-01:12:07.683 1147c Level-0 table #3027: 0 bytes OK -2024/09/19-01:12:07.684 1147c Delete type=0 #3025 -2024/09/19-01:12:07.688 1147c Manual compaction at level-0 from '!items!0gEfNrgZuAxvnL5H' @ 72057594037927935 : 1 .. '!items.effects!zb0bHX95fRFILazJ.2TVoFB98ZtniR8Z7' @ 0 : 0; will stop at (end) -2024/09/19-01:12:07.689 1147c Manual compaction at level-1 from '!items!0gEfNrgZuAxvnL5H' @ 72057594037927935 : 1 .. '!items.effects!zb0bHX95fRFILazJ.2TVoFB98ZtniR8Z7' @ 0 : 0; will stop at (end) +2024/09/21-16:17:32.976 1304c Recovering log #3043 +2024/09/21-16:17:32.979 1304c Delete type=0 #3043 +2024/09/21-16:17:32.979 1304c Delete type=3 #3041 +2024/09/21-21:27:43.259 1147c Level-0 table #3048: started +2024/09/21-21:27:43.261 1147c Level-0 table #3048: 4528 bytes OK +2024/09/21-21:27:43.264 1147c Delete type=0 #3046 +2024/09/21-21:27:43.264 1147c Manual compaction at level-0 from '!items!0gEfNrgZuAxvnL5H' @ 72057594037927935 : 1 .. '!items.effects!zb0bHX95fRFILazJ.2TVoFB98ZtniR8Z7' @ 0 : 0; will stop at (end) +2024/09/21-21:27:43.264 1147c Manual compaction at level-1 from '!items!0gEfNrgZuAxvnL5H' @ 72057594037927935 : 1 .. '!items.effects!zb0bHX95fRFILazJ.2TVoFB98ZtniR8Z7' @ 0 : 0; will stop at '!items!U9ZIV2vqOstvPzUo' @ 1750 : 1 +2024/09/21-21:27:43.265 1147c Compacting 1@1 + 1@2 files +2024/09/21-21:27:43.270 1147c Generated table #3049@1: 53 keys, 154092 bytes +2024/09/21-21:27:43.270 1147c Compacted 1@1 + 1@2 files => 154092 bytes +2024/09/21-21:27:43.271 1147c compacted to: files[ 0 0 1 0 0 0 0 ] +2024/09/21-21:27:43.271 1147c Delete type=2 #3036 +2024/09/21-21:27:43.271 1147c Delete type=2 #3048 +2024/09/21-21:27:43.281 1147c Manual compaction at level-1 from '!items!U9ZIV2vqOstvPzUo' @ 1750 : 1 .. '!items.effects!zb0bHX95fRFILazJ.2TVoFB98ZtniR8Z7' @ 0 : 0; will stop at (end) diff --git a/packs/gps-spells/LOG.old b/packs/gps-spells/LOG.old index 423777a9..91ebc99b 100644 --- a/packs/gps-spells/LOG.old +++ b/packs/gps-spells/LOG.old @@ -1,3 +1,8 @@ -2024/09/17-10:53:01.635 19cc Recovering log #3020 -2024/09/17-10:53:01.640 19cc Delete type=0 #3020 -2024/09/17-10:53:01.640 19cc Delete type=3 #3018 +2024/09/21-16:06:48.780 13050 Recovering log #3039 +2024/09/21-16:06:48.785 13050 Delete type=0 #3039 +2024/09/21-16:06:48.785 13050 Delete type=3 #3037 +2024/09/21-16:14:51.124 1147c Level-0 table #3044: started +2024/09/21-16:14:51.124 1147c Level-0 table #3044: 0 bytes OK +2024/09/21-16:14:51.126 1147c Delete type=0 #3042 +2024/09/21-16:14:51.128 1147c Manual compaction at level-0 from '!items!0gEfNrgZuAxvnL5H' @ 72057594037927935 : 1 .. '!items.effects!zb0bHX95fRFILazJ.2TVoFB98ZtniR8Z7' @ 0 : 0; will stop at (end) +2024/09/21-16:14:51.129 1147c Manual compaction at level-1 from '!items!0gEfNrgZuAxvnL5H' @ 72057594037927935 : 1 .. '!items.effects!zb0bHX95fRFILazJ.2TVoFB98ZtniR8Z7' @ 0 : 0; will stop at (end) diff --git a/packs/gps-spells/MANIFEST-003024 b/packs/gps-spells/MANIFEST-003024 deleted file mode 100644 index 174219da..00000000 Binary files a/packs/gps-spells/MANIFEST-003024 and /dev/null differ diff --git a/packs/gps-spells/MANIFEST-003045 b/packs/gps-spells/MANIFEST-003045 new file mode 100644 index 00000000..6905531d Binary files /dev/null and b/packs/gps-spells/MANIFEST-003045 differ diff --git a/scripts/helpers.js b/scripts/helpers.js index f5434542..64ec8ba6 100644 --- a/scripts/helpers.js +++ b/scripts/helpers.js @@ -174,12 +174,14 @@ export function convertFromFeet({ range }) { return range * conversionFactor; } -export async function handleDialogPromises(userDialogArgs, gmDialogArgs) { +export async function handleDialogPromises({userDialogArgs, gmDialogArgs}) { if(!userDialogArgs || !gmDialogArgs) return; + console.log(userDialogArgs) + console.log(gmDialogArgs) const module = await import('./module.js'); const socket = module.socket; let userDialogPromise = socket.executeAsUser("process3rdPartyReactionDialog", userDialogArgs.browserUser, userDialogArgs); - let gmDialogPromise = process3rdPartyReactionDialog(gmDialogArgs); + let gmDialogPromise = socket.executeAsUser("process3rdPartyReactionDialog", getPrimaryGM(), gmDialogArgs); return new Promise((resolve, reject) => { let userResolved = false; @@ -232,7 +234,7 @@ export function findValidTokens({initiatingToken, targetedToken, itemName, itemT } let checkItem; if(gpsUuid) checkItem = t?.actor?.items?.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); - else checkItem = t?.actor?.items?.find(i => i.name.toLowerCase() === itemName); + else checkItem = t?.actor?.items?.find(i => i.name.toLowerCase() === itemName.toLowerCase()); const effectNamesOrigin = ["Confusion", "Arms of Hadar", "Shocking Grasp", "Slow", "Staggering Smite"]; let hasEffectOrigin = t?.actor?.appliedEffects.some(effect => effectNamesOrigin.includes(effect.name)); let measuredDistance = (dispositionCheckType === "ally" || dispositionCheckType === "enemyAlly") ? MidiQOL.computeDistance(targetedToken,t,true) : MidiQOL.computeDistance(initiatingToken,t,true); @@ -352,12 +354,13 @@ export function findValidTokens({initiatingToken, targetedToken, itemName, itemT return validTokens; } -export async function process3rdPartyReactionDialog({ dialogTitle, dialogContent, dialogId, initialTimeLeft, validTokenPrimaryUuid, source, type }) { +export async function process3rdPartyReactionDialog({ dialogTitle, dialogContent, dialogId, initialTimeLeft, validTokenPrimaryUuid, source, type, notificationId }) { + console.log("made it to 3rd party dialog") const module = await import('./module.js'); const socket = module.socket; let validTokenPrimary = await fromUuid(validTokenPrimaryUuid); - let browserUser = MidiQOL.playerForActor(validTokenPrimary?.actor); - if (!browserUser.active) browserUser = game.users?.activeGM; + let browserUser = getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); + console.log(browserUser, "3rd party dialog browseruser") let dialogState = { interacted: false, decision: null, programmaticallyClosed: false, dialogId: dialogId }; let result = null; @@ -396,9 +399,9 @@ export async function process3rdPartyReactionDialog({ dialogTitle, dialogContent const pauseState = { dialogId: dialogId, timeLeft: dialog.timeLeft, isPaused: dialog.isPaused }; if (source === "user" && type === "multiDialog") { - socket.executeAsGM("pauseDialogById", pauseState); + socket.executeAsUser("pauseDialogById", getPrimaryGM(), pauseState); } else if (source === "gm" && type === "multiDialog") { - socket.executeAsUser("pauseDialogById", browserUser.id, pauseState); + socket.executeAsUser("pauseDialogById", browserUser, pauseState); } } @@ -495,10 +498,11 @@ export async function process3rdPartyReactionDialog({ dialogTitle, dialogContent action: "yes", label: "Yes", callback: async (event, button, dialog) => { + await socket.executeAsUser("deleteChatMessage", getPrimaryGM(), {chatId: notificationId}); dialogState.interacted = true; dialogState.decision = "yes"; - if (source && source === "user" && type === "multiDialog") await socket.executeAsGM("closeDialogById", { dialogId: dialogId }); - else if (source && source === "gm" && type === "multiDialog") await socket.executeAsUser("closeDialogById", browserUser.id, { dialogId: dialogId }); + if (source && source === "user" && type === "multiDialog") await socket.executeAsUser("closeDialogById", getPrimaryGM(), { dialogId: dialogId }); + else if (source && source === "gm" && type === "multiDialog") await socket.executeAsUser("closeDialogById", browserUser, { dialogId: dialogId }); let enemyTokenUuid = button.form?.elements["enemy-token"]?.value ?? false; let allyTokenUuid = button.form?.elements["ally-token"]?.value ?? false; @@ -529,10 +533,11 @@ export async function process3rdPartyReactionDialog({ dialogTitle, dialogContent label: `No`, default: true, callback: async (event, button, dialog) => { + await socket.executeAsUser("deleteChatMessage", getPrimaryGM(), {chatId: notificationId}); dialogState.interacted = true; dialogState.decision = "no"; - if(source && source === "user" && type === "multiDialog") await socket.executeAsGM("closeDialogById", { dialogId: dialogId }); - else if(source && source === "gm" && type === "multiDialog") await socket.executeAsUser("closeDialogById", browserUser.id, { dialogId: dialogId }); + if(source && source === "user" && type === "multiDialog") await socket.executeAsUser("closeDialogById", getPrimaryGM(), { dialogId: dialogId }); + else if(source && source === "gm" && type === "multiDialog") await socket.executeAsUser("closeDialogById", browserUser, { dialogId: dialogId }); let enemyTokenUuid = button.form?.elements["enemy-token"]?.value ?? false; @@ -626,8 +631,8 @@ export async function process3rdPartyReactionDialog({ dialogTitle, dialogContent if (dialog.dialogState.programmaticallyClosed) result = ({ userDecision: false, programmaticallyClosed: true, source, type }); else if (!dialog.dialogState.interacted) result = ({ userDecision: false, programmaticallyClosed: false, source, type }); - if(source && source === "user" && type === "multiDialog" && !dialog.dialogState.programmaticallyClosed) await socket.executeAsGM("closeDialogById", { dialogId: dialogId }); - else if(source && source === "gm" && type === "multiDialog" && !dialog.dialogState.programmaticallyClosed) await socket.executeAsUser("closeDialogById", browserUser.id, { dialogId: dialogId }); + if(source && source === "user" && type === "multiDialog" && !dialog.dialogState.programmaticallyClosed) await socket.executeAsUser("closeDialogById", getPrimaryGM(), { dialogId: dialogId }); + else if(source && source === "gm" && type === "multiDialog" && !dialog.dialogState.programmaticallyClosed) await socket.executeAsUser("closeDialogById", browserUser, { dialogId: dialogId }); }, rejectClose:false }); return result; @@ -774,6 +779,9 @@ export async function moveTokenByCardinal({ targetUuid, distance, direction }) { let moveX = 0; let moveY = 0; + const initialX = target.x; + const initialY = target.y; + switch (direction) { case "North": moveY = -moveDistancePixels; @@ -841,20 +849,20 @@ export async function moveTokenByCardinal({ targetUuid, distance, direction }) { break; } - let newX = target.x + moveX; - let newY = target.y + moveY; + let finalX = target.x + moveX; + let finalY = target.y + moveY; if (canvas.scene.grid.type === 1) { - const snapped = canvas.scene.grid.getSnappedPoint({ x: newX, y: newY }, { mode: 0xFF0, resolution: 1 }); - newX = snapped.x; - newY = snapped.y; + const snapped = canvas.scene.grid.getSnappedPoint({ x: finalX, y: finalY }, { mode: 0xFF0, resolution: 1 }); + finalX = snapped.x; + finalY = snapped.y; } - let endPoint = new PIXI.Point(newX, newY); + let endPoint = new PIXI.Point(finalX, finalY); let collisionDetected = CONFIG.Canvas.polygonBackends.move.testCollision(target.center, endPoint, { type: "move", mode: "any" }); if (!collisionDetected) { - await target.document.update({ x: newX, y: newY }); + await target.document.update({ x: finalX, y: finalY }); } else { let directionVector = { x: moveX, y: moveY }; let magnitude = Math.hypot(directionVector.x, directionVector.y); @@ -882,8 +890,8 @@ export async function moveTokenByCardinal({ targetUuid, distance, direction }) { stepCounter = step; } - let finalX = target.x + directionVector.x * (canvas.scene.grid.size / 10) * stepCounter; - let finalY = target.y + directionVector.y * (canvas.scene.grid.size / 10) * stepCounter; + finalX = target.x + directionVector.x * (canvas.scene.grid.size / 10) * stepCounter; + finalY = target.y + directionVector.y * (canvas.scene.grid.size / 10) * stepCounter; if (stepCounter > 0) { if (canvas.scene.grid.type === 1) { @@ -894,6 +902,38 @@ export async function moveTokenByCardinal({ targetUuid, distance, direction }) { await target.document.update({ x: finalX, y: finalY }); } } + + let totalDistanceMoved; + + const dx = Math.abs(finalX - initialX) / canvas.grid.size; + const dy = Math.abs(finalY - initialY) / canvas.grid.size; + const diagonalSteps = Math.min(dx, dy); + const straightSteps = Math.abs(dx - dy); + + switch (gridDiagonals) { + case 0: // Equidistant + totalDistanceMoved = (diagonalSteps + straightSteps) * gridDistance; + break; + case 1: // Exact + totalDistanceMoved = Math.hypot(finalX - initialX, finalY - initialY) / pixelsPerFoot; + break; + case 2: // 1.5x cost for diagonals + totalDistanceMoved = (diagonalSteps * 1.5 + straightSteps) * gridDistance; + break; + case 3: // 2x cost for diagonals + totalDistanceMoved = (diagonalSteps * 2 + straightSteps) * gridDistance; + break; + case 4: // Alternating (1/2/1) + totalDistanceMoved = ((diagonalSteps % 2 === 0 ? diagonalSteps * 1 : diagonalSteps * 2) + straightSteps) * gridDistance; + break; + case 5: // Alternating (2/1/2) + totalDistanceMoved = ((diagonalSteps % 2 === 0 ? diagonalSteps * 2 : diagonalSteps * 1) + straightSteps) * gridDistance; + break; + default: + totalDistanceMoved = (diagonalSteps + straightSteps) * gridDistance; + } + + return totalDistanceMoved; } export async function replaceChatCard({ actorUuid, itemUuid, chatContent, rollData }) { @@ -1045,11 +1085,11 @@ export async function ritualSpellUse({ workflowUuid }) { let content = ` ${workflow.actor.name} cast ${workflow.item.name} ritually.` let chatData = { - user: game.users.find(u => u.isGM).id, + user: getPrimaryGM(), content: content, - whisper: game.users.find(u => u.isGM).id + whisper: getPrimaryGM() }; - await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + await MidiQOL.socket().executeAsUser("createChatMessage", getPrimaryGM(), { chatData }); return; } }, @@ -1062,4 +1102,34 @@ export async function ritualSpellUse({ workflowUuid }) { return; }, rejectClose:false }); -} \ No newline at end of file +} + +export function getBrowserUser({ actorUuid }) { + if(!actorUuid) return; + + let actor = fromUuidSync(actorUuid); + let player = MidiQOL.playerForActor(actor); + let playerId; + + if(!player.active) playerId = getPrimaryGM(); + else playerId = player.id; + return playerId; +} + +export function getPrimaryGM() { + const primaryGMId = game.settings.get("gambits-premades", "primaryGM"); + const primaryGM = game.users.find(user => user.id === primaryGMId && user.active && user.isGM); + + if (!primaryGM) { + const activeGM = game.users.activeGM; + + if (!activeGM) { + console.warn("No active GM found."); + return false; + } + + return activeGM.id; + } + + return primaryGMId; + } \ No newline at end of file diff --git a/scripts/macros/ballBearings.js b/scripts/macros/ballBearings.js index 4aaf5ec1..30bc37b6 100644 --- a/scripts/macros/ballBearings.js +++ b/scripts/macros/ballBearings.js @@ -4,6 +4,7 @@ export async function ballBearings({tokenUuid, regionUuid, regionScenario, origi const socket = module.socket; const helpers = await import('../helpers.js'); let region = await fromUuid(regionUuid); + let gmUser = helpers.getPrimaryGM(); let tokenDocument = await fromUuid(tokenUuid); let token = tokenDocument?.object; @@ -20,10 +21,6 @@ export async function ballBearings({tokenUuid, regionUuid, regionScenario, origi let itemProperName = chosenItem.name; let dialogId = "ballbearings"; let dialogTitlePrimary = `${token.actor.name} | ${itemProperName}`; - let browserUser = MidiQOL.playerForActor(token.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } const effectOriginActor = await fromUuid(region.flags["region-attacher"].actorUuid); @@ -49,7 +46,7 @@ export async function ballBearings({tokenUuid, regionUuid, regionScenario, origi `; - let result = await socket.executeAsGM("process3rdPartyReactionDialog", {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: "gm",type: "singleDialog"}); + let result = await socket.executeAsUser("process3rdPartyReactionDialog", gmUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: "gm",type: "singleDialog"}); const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, abilityCheck, source, type } = result; @@ -95,7 +92,7 @@ export async function ballBearings({tokenUuid, regionUuid, regionScenario, origi const hasEffectApplied = tokenDocument.hasStatusEffect("prone"); if (!hasEffectApplied) { - await game.gps.socket.executeAsGM("gmToggleStatus", {tokenUuid: `${token.document.uuid}`, status: "prone", active: true }); + await game.gps.socket.executeAsUser("gmToggleStatus", gmUser, {tokenUuid: `${token.document.uuid}`, status: "prone", active: true }); } } } diff --git a/scripts/macros/biohazard.js b/scripts/macros/biohazard.js index 2ffbe76e..a2f0a5c4 100644 --- a/scripts/macros/biohazard.js +++ b/scripts/macros/biohazard.js @@ -1,6 +1,7 @@ export async function biohazard({tokenUuid, regionUuid, regionScenario, regionStatus}) { const helpers = await import('../helpers.js'); let region = await fromUuid(regionUuid); + let gmUser = helpers.getPrimaryGM(); let template; if(region?.flags["region-attacher"]?.attachedTemplate) { @@ -21,11 +22,6 @@ export async function biohazard({tokenUuid, regionUuid, regionScenario, regionSt let chosenItem = await fromUuid(region.flags["region-attacher"].itemUuid); let itemProperName = chosenItem?.name; - - let browserUser = MidiQOL.playerForActor(token.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } const effectOriginActor = await fromUuid(region.flags["region-attacher"].actorUuid); @@ -89,7 +85,7 @@ export async function biohazard({tokenUuid, regionUuid, regionScenario, regionSt } }]; - await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: token.actor.uuid, effects: effectData }); + await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: token.actor.uuid, effects: effectData }); } if(saveResult) { diff --git a/scripts/macros/blackTentacles.js b/scripts/macros/blackTentacles.js index 35dfbcf2..b6ad8cad 100644 --- a/scripts/macros/blackTentacles.js +++ b/scripts/macros/blackTentacles.js @@ -3,6 +3,7 @@ export async function blackTentacles({tokenUuid, regionUuid, regionScenario, ori const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); + let gmUser = helpers.getPrimaryGM(); let region = await fromUuid(regionUuid); let tokenDocument = await fromUuid(tokenUuid); @@ -27,10 +28,7 @@ export async function blackTentacles({tokenUuid, regionUuid, regionScenario, ori let dialogId = "blacktentacles"; let dialogTitlePrimary = `${token.actor.name} | ${itemProperName}`; - let browserUser = MidiQOL.playerForActor(token.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + let browserUser = helpers.getBrowserUser({ actorUuid: token.actor.uuid }); const effectOriginActor = await fromUuid(region.flags["region-attacher"].actorUuid); @@ -97,7 +95,7 @@ export async function blackTentacles({tokenUuid, regionUuid, regionScenario, ori `; - let result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + let result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog"}); const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, abilityCheck, source, type } = result; @@ -109,7 +107,7 @@ export async function blackTentacles({tokenUuid, regionUuid, regionScenario, ori if (abilityCheck) { const skillCheck = await token.actor.rollAbilityTest(abilityCheck); if (skillCheck.total >= spellDC) { - await game.gps.socket.executeAsGM("gmToggleStatus", {tokenUuid: `${token.document.uuid}`, status: "restrained", active: false }); + await game.gps.socket.executeAsUser("gmToggleStatus", gmUser, {tokenUuid: `${token.document.uuid}`, status: "restrained", active: false }); let chatData = { user: browserUser.id, speaker: ChatMessage.getSpeaker({ token: token }), @@ -167,7 +165,7 @@ export async function blackTentacles({tokenUuid, regionUuid, regionScenario, ori const hasEffectApplied = token.document.hasStatusEffect("restrained"); if (!hasEffectApplied) { - await game.gps.socket.executeAsGM("gmToggleStatus", {tokenUuid: `${token.document.uuid}`, status: "restrained", active: true }); + await game.gps.socket.executeAsUser("gmToggleStatus", gmUser, {tokenUuid: `${token.document.uuid}`, status: "restrained", active: true }); } let dialogContent = ` @@ -193,7 +191,7 @@ export async function blackTentacles({tokenUuid, regionUuid, regionScenario, ori `; - let result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + let result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog"}); const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, abilityCheck, source, type } = result; @@ -210,7 +208,7 @@ export async function blackTentacles({tokenUuid, regionUuid, regionScenario, ori if (abilityCheck) { const skillCheck = await token.actor.rollAbilityTest(abilityCheck); if (skillCheck.total >= spellDC) { - await game.gps.socket.executeAsGM("gmToggleStatus", {tokenUuid: `${token.document.uuid}`, status: "restrained", active: false }); + await game.gps.socket.executeAsUser("gmToggleStatus", gmUser, {tokenUuid: `${token.document.uuid}`, status: "restrained", active: false }); let chatData = { user: browserUser.id, speaker: ChatMessage.getSpeaker({ token: token }), diff --git a/scripts/macros/caltrops.js b/scripts/macros/caltrops.js index ea4a167a..03057769 100644 --- a/scripts/macros/caltrops.js +++ b/scripts/macros/caltrops.js @@ -2,6 +2,7 @@ export async function caltrops({tokenUuid, regionUuid, regionScenario, originX, const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); + let gmUser = helpers.getPrimaryGM(); let region = await fromUuid(regionUuid); let tokenDocument = await fromUuid(tokenUuid); @@ -19,10 +20,6 @@ export async function caltrops({tokenUuid, regionUuid, regionScenario, originX, let itemProperName = chosenItem.name; let dialogId = "caltrops"; let dialogTitlePrimary = `${token.actor.name} | ${itemProperName}`; - let browserUser = MidiQOL.playerForActor(token.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } const effectOriginActor = await fromUuid(region.flags["region-attacher"].actorUuid); @@ -48,7 +45,7 @@ export async function caltrops({tokenUuid, regionUuid, regionScenario, originX, `; - let result = await socket.executeAsGM("process3rdPartyReactionDialog", {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: "gm",type: "singleDialog"}); + let result = await socket.executeAsUser("process3rdPartyReactionDialog", gmUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: "gm",type: "singleDialog"}); const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, abilityCheck, source, type } = result; @@ -117,7 +114,7 @@ export async function caltrops({tokenUuid, regionUuid, regionScenario, originX, } ]; - await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: token.actor.uuid, effects: effectData }); + await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: token.actor.uuid, effects: effectData }); let actorPlayer = MidiQOL.playerForActor(token.actor); let chatData = { diff --git a/scripts/macros/caltropsFeyGlass.js b/scripts/macros/caltropsFeyGlass.js index 9771a265..c415f141 100644 --- a/scripts/macros/caltropsFeyGlass.js +++ b/scripts/macros/caltropsFeyGlass.js @@ -2,6 +2,7 @@ export async function caltropsFeyGlass({tokenUuid, regionUuid, regionScenario, o const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); + let gmUser = helpers.getPrimaryGM(); let region = await fromUuid(regionUuid); let tokenDocument = await fromUuid(tokenUuid); @@ -19,10 +20,6 @@ export async function caltropsFeyGlass({tokenUuid, regionUuid, regionScenario, o let itemProperName = chosenItem.name; let dialogId = "feyglasscaltrops"; let dialogTitlePrimary = `${token.actor.name} | ${itemProperName}`; - let browserUser = MidiQOL.playerForActor(token.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } const effectOriginActor = await fromUuid(region.flags["region-attacher"].actorUuid); @@ -48,7 +45,7 @@ export async function caltropsFeyGlass({tokenUuid, regionUuid, regionScenario, o `; - let result = await socket.executeAsGM("process3rdPartyReactionDialog", {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: "gm",type: "singleDialog"}); + let result = await socket.executeAsUser("process3rdPartyReactionDialog", gmUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft: 30,validTokenPrimaryUuid: token.document.uuid,source: "gm",type: "singleDialog"}); const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, abilityCheck, source, type } = result; @@ -117,7 +114,7 @@ export async function caltropsFeyGlass({tokenUuid, regionUuid, regionScenario, o } ]; - await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: token.actor.uuid, effects: effectData }); + await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: token.actor.uuid, effects: effectData }); let actorPlayer = MidiQOL.playerForActor(token.actor); let chatData = { diff --git a/scripts/macros/cloudRune.js b/scripts/macros/cloudRune.js index cb062844..585dfe76 100644 --- a/scripts/macros/cloudRune.js +++ b/scripts/macros/cloudRune.js @@ -2,27 +2,27 @@ export async function cloudRune({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "cloud rune"; - let itemProperName = "Cloud Rune"; - let dialogId = "cloudrune"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - - if(workflow.item.name.toLowerCase() === itemName) return; + const gpsUuid = "8b8a1e0a-54b8-4b11-9247-5e16e4d92b4b"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Cloud Rune"; + let dialogId = gpsUuid; let target = workflow.targets.first(); + let gmUser = helpers.getPrimaryGM(); if(workflow.attackTotal < target.actor.system.attributes.ac.value) return; if(workflow.targets.size > 1) return; - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: [itemName], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 30, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: [itemName], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 30, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; for (const validTokenPrimary of findValidTokens) { const nearbyTokens = MidiQOL.findNearby(null, validTokenPrimary, 30, { includeToken: false }); let targets = nearbyTokens.filter(token => token.document.disposition !== validTokenPrimary.document.disposition && MidiQOL.canSee(validTokenPrimary.document.uuid,token.document.uuid) && token.document.uuid !== workflow.token.document.uuid); - + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const targetUuids = targets.map(t => t.document.uuid); const targetNames = targets.map(t => t.actor.name); if(targetUuids.length === 0) continue; @@ -33,120 +33,116 @@ export async function cloudRune({workflowData,workflowType,workflowCombat}) { const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } - - if(workflowType === "attack") { - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); - let chosenItem = await validTokenPrimary.actor.items.find(i => i.name === itemProperName); - - const optionBackground = (document.body.classList.contains("theme-dark")) ? 'black' : 'var(--color-bg)'; - - let dialogContent = ` -
-
-
-

Would you like to use your reaction to initiate ${itemProperName} and re-direct this attack?

-
-
- - ${targetNames.length >= 1 ? - `` : '
No valid enemies in range.
' - } -
- -
+ browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); + + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); + + const optionBackground = (document.body.classList.contains("theme-dark")) ? 'black' : 'var(--color-bg)'; + + let dialogContent = ` +
+
+
+

Would you like to use your reaction to initiate ${itemProperName} and re-direct this attack?

+
+
+ + ${targetNames.length >= 1 ? + `` : '
No valid enemies in range.
' + } +
+
-
- -
- `; +
+ +
+
+ `; - let result; + let content = ` ${validTokenPrimary.actor.name} has an option available for an attack triggering ${itemProperName}.` + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; - - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let result; + + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); - } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); - } - - const { userDecision, enemyTokenUuid, source, type } = result; - - if (!userDecision) { - if(source && source === "user" && type === "multiDialog") await socket.executeAsGM("closeDialogById", { dialogId: dialogId }); - if(source && source === "gm" && type === "multiDialog") await socket.executeAsUser("closeDialogById", browserUser.id, { dialogId: dialogId }); - continue; - } - else if (userDecision) { - chosenItem.prepareData(); - chosenItem.prepareFinalAttributes(); - chosenItem.applyActiveEffects(); - - const optionsChosenItem = { - showFullCard: false, - createWorkflow: true, - versatile: false, - configureDialog: true, - targetUuids: [validTokenPrimary.document.uuid] - }; - - let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: optionsChosenItem }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: optionsChosenItem }); - if(itemRoll.aborted === true) continue; - - await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; + + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); + } else { + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); + } - let rerollNew = await new Roll(`${workflow.attackRoll.result}`).evaluate(); - let newItemData = workflow.item; - - newItemData = newItemData.clone({ - system: { - "range": { - "value": null, - "long": null, - "units": "" - } + const { userDecision, enemyTokenUuid, source, type } = result; + + if (!userDecision) { + continue; + } + else if (userDecision) { + chosenItem.prepareData(); + chosenItem.prepareFinalAttributes(); + chosenItem.applyActiveEffects(); + + const optionsChosenItem = { + showFullCard: false, + createWorkflow: true, + versatile: false, + configureDialog: true, + targetUuids: [validTokenPrimary.document.uuid] + }; + + let itemRoll; + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: optionsChosenItem }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: optionsChosenItem }); + if(itemRoll.aborted === true) continue; + + await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); + + let rerollNew = await new Roll(`${workflow.attackRoll.result}`).evaluate(); + let newItemData = workflow.item; + + newItemData = newItemData.clone({ + system: { + "range": { + "value": null, + "long": null, + "units": "" } - }, { keepId: true }); + } + }, { keepId: true }); - newItemData.prepareData(); - newItemData.prepareFinalAttributes(); - newItemData.applyActiveEffects(); - - const options = { - showFullCard: false, - createWorkflow: true, - versatile: false, - configureDialog: true, - targetUuids: [enemyTokenUuid], - workflowOptions: {autoFastForward: "on", autoRollAttack: true, attackRollDSN: false} - }; - - workflow.aborted = true; - - const hookid = Hooks.once("midi-qol.preAttackRollComplete", async (workflow) => { - await workflow.setAttackRoll(rerollNew); - }); - - await MidiQOL.completeItemUse(newItemData, {}, options); - - Hooks.off('', hookid); - } + newItemData.prepareData(); + newItemData.prepareFinalAttributes(); + newItemData.applyActiveEffects(); + + const options = { + showFullCard: false, + createWorkflow: true, + versatile: false, + configureDialog: true, + targetUuids: [enemyTokenUuid], + workflowOptions: {autoFastForward: "on", autoRollAttack: true, attackRollDSN: false} + }; + + workflow.aborted = true; + + const hookid = Hooks.once("midi-qol.preAttackRollComplete", async (workflow) => { + await workflow.setAttackRoll(rerollNew); + }); + + await MidiQOL.completeItemUse(newItemData, {}, options); + + Hooks.off('', hookid); } } } \ No newline at end of file diff --git a/scripts/macros/counterspell.js b/scripts/macros/counterspell.js index ddd8f4ca..10525a26 100644 --- a/scripts/macros/counterspell.js +++ b/scripts/macros/counterspell.js @@ -2,15 +2,14 @@ export async function counterspell({ workflowData,workflowType,workflowCombat }) const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(`${workflowUuid}`); - let itemName = "counterspell"; - let itemProperName = "Counterspell"; - let dialogId = "counterspell"; + const workflow = await MidiQOL.Workflow.getWorkflow(`${workflowData}`); if(!workflow) return; - if(workflow.item.type !== "spell" || workflow.item.name === itemProperName) return; + const gpsUuid = "a3992a10-f36a-4416-a995-f83d444c3c0a"; + if(workflow.item.type !== "spell" || workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Counterspell"; + let dialogId = gpsUuid; const lastMessage = game.messages.contents[game.messages.contents.length - 1]; // Use to hide initial spell message - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + let gmUser = helpers.getPrimaryGM(); const castProperties = ["vocal", "somatic", "material"]; let hasVSMProperty = castProperties.some(prop => workflow.item.system.properties.has(prop)); @@ -18,6 +17,7 @@ export async function counterspell({ workflowData,workflowType,workflowCombat }) let hasDeafenedStatus; if (!hasVSMProperty) return; + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); let selectedToken = workflow.token; let castLevel = false; let browserUser; @@ -26,26 +26,23 @@ export async function counterspell({ workflowData,workflowType,workflowCombat }) async function initialCounterspellProcess(workflow, lastMessage, castLevel, selectedToken) { - let findValidTokens = helpers.findValidTokens({initiatingToken: selectedToken, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: selectedToken, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); if(findValidTokens.length === 0 || !findValidTokens) return; for (const validTokenPrimary of findValidTokens) { - if(lastMessage && validTokenPrimary.actor.type === "character") lastMessage.update({ whisper: [game.users.find((u) => u.isGM && u.active).id] }); - let workflowStatus = workflow.aborted; - if(workflowStatus === true) return; + if(lastMessage && validTokenPrimary.actor.type === "character") lastMessage.update({ whisper: gmUser }); + if(workflow.aborted === true) return; if(!castLevel) { hasDeafenedStatus = validTokenPrimary.document.hasStatusEffect("deafened"); if (isVocalOnly && hasDeafenedStatus) continue; } + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); castLevel = !castLevel ? workflow.castData.castLevel : castLevel; - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); const currentIndex = findValidTokens.indexOf(validTokenPrimary); const isLastToken = currentIndex === findValidTokens.length - 1; @@ -72,42 +69,34 @@ export async function counterspell({ workflowData,workflowType,workflowCombat })
`; - let content = ` ${validTokenPrimary.actor.name} has a reaction available for a spell triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - roll: false, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let content = ` ${validTokenPrimary.actor.name} has a reaction available for a spell triggering ${itemProperName}.`; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision && isLastToken) { if(lastMessage && validTokenPrimary.actor.type === "character") lastMessage.update({ whisper: [] }); - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); return workflow.aborted = false; } else if (!userDecision) { if(lastMessage && validTokenPrimary.actor.type === "character") lastMessage.update({ whisper: [] }); - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { if(lastMessage && validTokenPrimary.actor.type === "character") lastMessage.update({ whisper: [] }); - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); let chosenSpell = validTokenPrimary.actor.items.find(i => i.name === itemProperName); @@ -131,8 +120,8 @@ export async function counterspell({ workflowData,workflowType,workflowCombat }) }); let itemRoll = false; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenSpell, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenSpell, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenSpell, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenSpell, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(!itemRoll) continue; @@ -196,18 +185,16 @@ export async function counterspell({ workflowData,workflowType,workflowCombat }) async function secondaryCounterspellProcess(workflow, lastMessage, castLevel, validTokenPrimary) { - let findValidTokens = helpers.findValidTokens({initiatingToken: validTokenPrimary, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: validTokenPrimary, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); if(findValidTokens.length === 0 || !findValidTokens) return workflow.aborted = true; for (const validTokenSecondary of findValidTokens) { + let chosenItem = validTokenSecondary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenSecondary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenSecondary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenSecondary.actor.items.find(i => i.name === itemProperName); - browserUser = MidiQOL.playerForActor(validTokenSecondary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + browserUser = helpers.getBrowserUser({ actorUuid: validTokenSecondary.actor.uuid }); const currentIndex = findValidTokens.indexOf(validTokenSecondary); const isLastToken = currentIndex === findValidTokens.length - 1; @@ -234,42 +221,34 @@ export async function counterspell({ workflowData,workflowType,workflowCombat })
`; - let content = ` ${validTokenSecondary.actor.name} has a reaction available for a spell triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - roll: false, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessageSecondary = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let content = ` ${validTokenSecondary.actor.name} has a reaction available for a spell triggering ${itemProperName}.`; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessageSecondary = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenSecondary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenSecondary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessageSecondary._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenSecondary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenSecondary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessageSecondary._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenSecondary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenSecondary.document.uuid,source:gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessageSecondary._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision && isLastToken) { if(lastMessage && validTokenPrimary.actor.type === "character") lastMessage.update({ whisper: [] }); - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessageSecondary._id }); return workflow.aborted = true; } else if (!userDecision) { if(lastMessage) lastMessage.update({ whisper: [] }); - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessageSecondary._id }); continue; } else if (userDecision) { if(lastMessage && validTokenPrimary.actor.type === "character") lastMessage.update({ whisper: [] }); - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessageSecondary._id }); let chosenSpell = validTokenSecondary.actor.items.find(i => i.name === itemProperName); @@ -293,8 +272,8 @@ export async function counterspell({ workflowData,workflowType,workflowCombat }) }); let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenSpell, actorUuid: validTokenSecondary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenSpell, actorUuid: validTokenSecondary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenSpell, actorUuid: validTokenSecondary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenSpell, actorUuid: validTokenSecondary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; diff --git a/scripts/macros/cuttingWords.js b/scripts/macros/cuttingWords.js index 3a254ad5..aaee4464 100644 --- a/scripts/macros/cuttingWords.js +++ b/scripts/macros/cuttingWords.js @@ -2,35 +2,33 @@ export async function cuttingWords({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "cutting words"; - let itemProperName = "Cutting Words"; - let dialogId = "cuttingwords"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name === itemProperName) return; + const gpsUuid = "b352241e-5042-44a4-b632-3168ded51946"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Cutting Words"; + let dialogId = gpsUuid; + let gmUser = helpers.getPrimaryGM(); - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: ["bardic inspiration"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: ["bardic inspiration"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; for (const validTokenPrimary of findValidTokens) { + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); let bardicDie = validTokenPrimary.actor.system.scale?.bard["bardic-inspiration"]?.die; if(!bardicDie) { ui.notifications.error("You must have a Bard scale for this actor named 'bardic-inspiration'") continue; } - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); let dialogContent; const rollDetailSetting = MidiQOL.safeGetGameSetting('midi-qol', 'ConfigSettings').hideRollDetails; - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); if(workflowType === "damage") { if (workflow.token.document.disposition === validTokenPrimary.document.disposition) continue; @@ -95,36 +93,28 @@ export async function cuttingWords({workflowData,workflowType,workflowCombat}) { `; } - let content = ` ${validTokenPrimary.actor.name} has a reaction available for a save triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - roll: false, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let content = ` ${validTokenPrimary.actor.name} has a reaction available for a save triggering ${itemProperName}.`; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } - else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - + else if (userDecision) { chosenItem.prepareData(); chosenItem.prepareFinalAttributes(); chosenItem.applyActiveEffects(); @@ -138,8 +128,8 @@ export async function cuttingWords({workflowData,workflowType,workflowCombat}) { }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; let chatContent; @@ -167,8 +157,8 @@ export async function cuttingWords({workflowData,workflowType,workflowCombat}) { const saveSetting = workflow.options.noOnUseMacro; workflow.options.noOnUseMacro = true; let reroll; - if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser.id, { rollParams: `1${bardicDie}`, type: workflowType }); - if(source && source === "gm") reroll = await socket.executeAsGM("rollAsUser", { rollParams: `1${bardicDie}`, type: workflowType }); + if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser, { rollParams: `1${bardicDie}`, type: workflowType }); + if(source && source === "gm") reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `1${bardicDie}`, type: workflowType }); let remainingReduction = reroll.total; let updatedRolls = []; @@ -217,8 +207,8 @@ export async function cuttingWords({workflowData,workflowType,workflowCombat}) { const saveSetting = workflow.options.noOnUseMacro; workflow.options.noOnUseMacro = true; let reroll; - if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser.id, { rollParams: `1${bardicDie}`, type: workflowType }); - if(source && source === "gm") reroll = await socket.executeAsGM("rollAsUser", { rollParams: `1${bardicDie}`, type: workflowType }); + if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser, { rollParams: `1${bardicDie}`, type: workflowType }); + if(source && source === "gm") reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `1${bardicDie}`, type: workflowType }); let rerollNew = await new Roll(`${workflow.attackRoll.result} - ${reroll.total}`).evaluate(); await workflow.setAttackRoll(rerollNew); diff --git a/scripts/macros/indomitable.js b/scripts/macros/indomitable.js index 375c209a..95c77469 100644 --- a/scripts/macros/indomitable.js +++ b/scripts/macros/indomitable.js @@ -2,32 +2,31 @@ export async function indomitable({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "indomitable"; - let itemProperName = "Indomitable"; - let dialogId = "indomitable"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name === itemProperName) return; + const gpsUuid = "75e0633f-3973-4ea7-9246-da3e6d0da457"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Indomitable"; + let dialogId = gpsUuid; + let gmUser = helpers.getPrimaryGM(); // Check if there is a save success if(workflowType === "save" && workflow.failedSaves.size === 0) return; - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: ["indomitable"], reactionCheck: false, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: false, dispositionCheckType: null, workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: ["indomitable"], reactionCheck: false, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: false, dispositionCheckType: null, workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; for (const validTokenPrimary of findValidTokens) { let targetUuids = Array.from(workflow.failedSaves).filter(t => t.document.uuid === validTokenPrimary.document.uuid).map(t => t.document.uuid); if(targetUuids.length === 0) continue; - + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) browserUser = game.users?.activeGM; + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); let indomitableHomebrew = MidiQOL.safeGetGameSetting('gambits-premades', 'enableAutoSucceedIndomitable'); let contentQuestion; @@ -58,32 +57,25 @@ export async function indomitable({workflowData,workflowType,workflowCombat}) { let result; let content = ` ${validTokenPrimary.actor.name} has an option available for a save triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); - - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); + + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - chosenItem.prepareData(); chosenItem.prepareFinalAttributes(); chosenItem.applyActiveEffects(); @@ -97,8 +89,8 @@ export async function indomitable({workflowData,workflowType,workflowCombat}) { }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; let chatContent; @@ -107,8 +99,8 @@ export async function indomitable({workflowData,workflowType,workflowCombat}) { let saveAbility = workflow.saveItem.system.save.ability; let targetSaveBonus = validTokenPrimary.actor.system.abilities[`${saveAbility}`].save + validTokenPrimary.actor.system.abilities[`${saveAbility}`].saveBonus; let reroll; - if(source && source === "user" && !indomitableHomebrew) reroll = await socket.executeAsUser("rollAsUser", browserUser.id, { rollParams: `1d20 + ${targetSaveBonus}` }); - if(source && source === "gm" && !indomitableHomebrew) reroll = await socket.executeAsGM("rollAsUser", { rollParams: `1d20 + ${targetSaveBonus}` }); + if(source && source === "user" && !indomitableHomebrew) reroll = await socket.executeAsUser("rollAsUser", browserUser, { rollParams: `1d20 + ${targetSaveBonus}` }); + if(source && source === "gm" && !indomitableHomebrew) reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `1d20 + ${targetSaveBonus}` }); if((reroll?.total >= saveDC) || indomitableHomebrew) { workflow.saves.add(validTokenPrimary); diff --git a/scripts/macros/instinctiveCharm.js b/scripts/macros/instinctiveCharm.js index e3881731..8732b054 100644 --- a/scripts/macros/instinctiveCharm.js +++ b/scripts/macros/instinctiveCharm.js @@ -2,18 +2,17 @@ export async function instinctiveCharm({workflowData,workflowType,workflowCombat const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "instinctive charm"; - let itemProperName = "Instinctive Charm"; - let dialogId = "instinctivecharm"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name === itemProperName) return; + const gpsUuid = "b9a797f2-3262-4a89-9b32-d8482a0c5f29"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Instinctive Charm"; + let dialogId = gpsUuid; let target = workflow.token; - if(target.actor.appliedEffects.some(e => e.name === `${itemProperName} - Immunity`)) return; let debugEnabled = MidiQOL.safeGetGameSetting('gambits-premades', 'debugEnabled'); + let gmUser = helpers.getPrimaryGM(); - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 30, dispositionCheck: false, dispositionCheckType: null, workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 30, dispositionCheck: false, dispositionCheckType: null, workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; @@ -32,14 +31,15 @@ export async function instinctiveCharm({workflowData,workflowType,workflowCombat `` ).join(''); + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; + if(target.actor.appliedEffects.some(e => e.name === `${itemProperName} - Immunity`)) return; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) browserUser = game.users?.activeGM; + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); const optionBackground = (document.body.classList.contains("theme-dark")) ? 'black' : 'var(--color-bg)'; - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); let dialogContent = `
@@ -63,33 +63,28 @@ export async function instinctiveCharm({workflowData,workflowType,workflowCombat
`; - let result; let content = ` ${validTokenPrimary.actor.name} has an option available for an attack triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); - - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); + + let result; + + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); chosenItem.prepareData(); chosenItem.prepareFinalAttributes(); chosenItem.applyActiveEffects(); @@ -103,16 +98,15 @@ export async function instinctiveCharm({workflowData,workflowType,workflowCombat }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); let dialogIdTarget = "instinctivecharmtarget"; - let browserUserTarget = MidiQOL.playerForActor(target.actor); - if (!browserUserTarget.active) browserUserTarget = game.users?.activeGM; + let browserUserTarget = helpers.getBrowserUser({ actorUuid: target.actor.uuid }); const spellDC = validTokenPrimary.actor.system.attributes.spelldc; let saveAbility = "wis"; @@ -179,14 +173,14 @@ export async function instinctiveCharm({workflowData,workflowType,workflowCombat let resultTarget; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUserTarget.id !== game.users?.activeGM.id) { - let userDialogPromise = socket.executeAsUser("process3rdPartyReactionDialog", browserUserTarget.id, {dialogTitle:dialogTitlePrimary,dialogContent: dialogContentTarget,dialogId: dialogIdTarget,initialTimeLeft,validTokenPrimaryUuid: target.document.uuid,source: "user",type: "multiDialog"}); + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUserTarget !== gmUser) { + let userDialogArgsTarget = { dialogTitle:dialogTitlePrimary,dialogContent: dialogContentTarget,dialogId: dialogIdTarget,initialTimeLeft,validTokenPrimaryUuid: target.document.uuid,source: "user",type: "multiDialog", browserUser: browserUserTarget, notificationId: notificationMessage._id }; - let gmDialogPromise = socket.executeAsGM("process3rdPartyReactionDialog", {dialogTitle:dialogTitleGM,dialogContent: dialogContentTarget,dialogId: dialogIdTarget,initialTimeLeft,validTokenPrimaryUuid: target.document.uuid,source: "gm",type: "multiDialog"}); + let gmDialogArgsTarget = { dialogTitle:dialogTitleGM,dialogContent: dialogContentTarget,dialogId: dialogIdTarget,initialTimeLeft,validTokenPrimaryUuid: target.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - resultTarget = await socket.executeAsGM("handleDialogPromises", userDialogPromise, gmDialogPromise); + resultTarget = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgsTarget, gmDialogArgsTarget}); } else { - resultTarget = await socket.executeAsUser("process3rdPartyReactionDialog", browserUserTarget.id, {dialogTitle:dialogTitlePrimary,dialogContent: dialogContentTarget,dialogId: dialogIdTarget,initialTimeLeft,validTokenPrimaryUuid: target.document.uuid,source:browserUserTarget.isGM ? "gm" : "user",type:"singleDialog"}); + resultTarget = await socket.executeAsUser("process3rdPartyReactionDialog", browserUserTarget.id, {dialogTitle:dialogTitlePrimary,dialogContent: dialogContentTarget,dialogId: dialogIdTarget,initialTimeLeft,validTokenPrimaryUuid: target.document.uuid,source: gmUser === browserUserTarget ? "gm" : "user",type:"singleDialog"}); } const { enemyTokenUuid } = resultTarget; @@ -214,7 +208,7 @@ export async function instinctiveCharm({workflowData,workflowType,workflowCombat } } ]; - await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: target.actor.uuid, effects: effectData }); + await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: target.actor.uuid, effects: effectData }); continue; } diff --git a/scripts/macros/interception.js b/scripts/macros/interception.js index 5d95cded..5eeca5e8 100644 --- a/scripts/macros/interception.js +++ b/scripts/macros/interception.js @@ -2,44 +2,38 @@ export async function interception({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "fighting style: interception"; - let itemProperName = "Interception"; - let dialogId = "interception"; - let target = workflow.hitTargets.first(); + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name.toLowerCase() === itemName) return; + const gpsUuid = "411b0d88-a483-4d85-97d9-2bd8dbd4ef70"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Fighting Style: Interception"; + let dialogId = gpsUuid; + let target = workflow.hitTargets.first(); const actionTypes = ["mwak", "rwak", "msak", "rsak"]; if (!actionTypes.some(type => workflow.item.system.actionType?.includes(type))) return; + let gmUser = helpers.getPrimaryGM(); - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "item", itemChecked: ["mwak", "shield"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemyAlly", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "item", itemChecked: ["mwak", "shield"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemyAlly", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; for (const validTokenPrimary of findValidTokens) { if (target.document.uuid === validTokenPrimary.document.uuid) continue; + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name.toLowerCase() === itemName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); let damageTypes = workflow.damageRolls.map(roll => roll.options.type); let hasHealing = damageTypes.some(type => type === "healing"); if (hasHealing) return; let damageTotals = workflow.damageRolls.map(roll => roll.total); - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `Interception Timeout`)); let content = ` ${validTokenPrimary.actor.name} has a reaction available for a roll triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); const rollDetailSetting = MidiQOL.safeGetGameSetting('midi-qol', 'ConfigSettings').hideRollDetails; @@ -74,25 +68,22 @@ export async function interception({workflowData,workflowType,workflowCombat}) { let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); let primaryFile = "jb2a.spiritual_weapon.sword.spectral.orange"; @@ -123,8 +114,8 @@ export async function interception({workflowData,workflowType,workflowCombat}) { numDice = `${dieNumber}d${dieFace}`; } - if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser.id, { rollParams: `${numDice} + ${actorProf}`, type: workflowType }); - if(source && source === "gm") reroll = await socket.executeAsGM("rollAsUser", { rollParams: `${numDice} + ${actorProf}`, type: workflowType }); + if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser, { rollParams: `${numDice} + ${actorProf}`, type: workflowType }); + if(source && source === "gm") reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `${numDice} + ${actorProf}`, type: workflowType }); let remainingReduction = reroll.total; let updatedRolls = []; diff --git a/scripts/macros/mageSlayer.js b/scripts/macros/mageSlayer.js index 2f5fa1d8..5762f5d5 100644 --- a/scripts/macros/mageSlayer.js +++ b/scripts/macros/mageSlayer.js @@ -2,18 +2,19 @@ export async function mageSlayer({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "mage slayer"; - let itemProperName = "Mage Slayer"; - let dialogId = "mageslayer"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name.toLowerCase() === itemName) return; + const gpsUuid = "fc0e0473-038b-4e68-abd5-538b8fbbb4a5"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Mage Slayer"; + let dialogId = gpsUuid; + let gmUser = helpers.getPrimaryGM(); - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: workflow.token, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: workflow.token, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); for (const validTokenPrimary of findValidTokens) { - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; if(workflowType === "save") { let target = Array.from(workflow.targets).filter(t => t.document.uuid === validTokenPrimary.document.uuid); @@ -43,20 +44,17 @@ export async function mageSlayer({workflowData,workflowType,workflowCombat}) { } }]; - await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: validTokenPrimary.actor.uuid, effects: effectData }); + await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: validTokenPrimary.actor.uuid, effects: effectData }); continue; } } else { const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + let browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); const optionBackground = (document.body.classList.contains("theme-dark")) ? 'black' : 'var(--color-bg)'; - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); // Check valid weapons let validWeapons = validTokenPrimary.actor.items.filter(item => { @@ -142,34 +140,27 @@ export async function mageSlayer({workflowData,workflowType,workflowCombat}) { `; let content = ` ${validTokenPrimary.actor.name} has a reaction available for an attack triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, selectedItemUuid, favoriteCheck, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - if (!selectedItemUuid) { console.log("No weapon selected"); continue; @@ -221,8 +212,8 @@ export async function mageSlayer({workflowData,workflowType,workflowCombat}) { }); let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); diff --git a/scripts/macros/opportunityAttack.js b/scripts/macros/opportunityAttack.js index 85e3257a..1814a86c 100644 --- a/scripts/macros/opportunityAttack.js +++ b/scripts/macros/opportunityAttack.js @@ -1,9 +1,10 @@ const regionTokenStates = new Map(); export async function opportunityAttackScenarios({tokenUuid, regionUuid, regionScenario, originX, originY, isTeleport}) { - if(!game.user.isGM) return; - const module = await import('../module.js'); const helpers = await import('../helpers.js'); + let gmUser = helpers.getPrimaryGM(); + if(game.user.id !== gmUser) return; + const module = await import('../module.js'); const socket = module.socket; //async function wait(ms) { return new Promise(resolve => { setTimeout(resolve, ms); }); } let region = await fromUuid(regionUuid); @@ -33,10 +34,7 @@ export async function opportunityAttackScenarios({tokenUuid, regionUuid, regionS let hasPolearmReaction = effectOriginActor.items.find(i => i.name.toLowerCase() === "polearm master"); let hasDeadlyReachReaction = effectOriginActor.items.find(i => i.name.toLowerCase() === "deadly reach"); - let browserUser = MidiQOL.playerForActor(effectOriginActor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + let browserUser = helpers.getBrowserUser({ actorUuid: effectOriginActor.uuid }); let result; let dialogTitle; @@ -311,34 +309,27 @@ export async function opportunityAttackScenarios({tokenUuid, regionUuid, regionS let dialogTitleGM = `Waiting for ${effectOriginActor.name}'s selection | ${dialogTitle}`; let content = ` ${effectOriginToken.actor.name} has a reaction available for an Opportunity Attack.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); - - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: effectOriginToken.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); + + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: effectOriginToken.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: effectOriginToken.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: effectOriginToken.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: effectOriginToken.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: effectOriginToken.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, selectedItemUuid, favoriteCheck, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); await effectOriginActor.unsetFlag("gambits-premades", "dragonTurtleShieldOA"); //if(hasSentinel) await effectOriginActor.setFlag("gambits-premades", "sentinelDeclined", true); return; } else if (userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - if (braceItemUuid) { let braceItem = await fromUuid(braceItemUuid); const braceRoll = await braceItem.use(); @@ -380,8 +371,8 @@ export async function opportunityAttackScenarios({tokenUuid, regionUuid, regionS chosenWeapon.applyActiveEffects(); let userSelect = undefined; - if(source && source === "user") userSelect = browserUser.id; - else if(source && source === "gm") userSelect = game.users?.activeGM.id; + if(source && source === "user") userSelect = browserUser; + else if(source && source === "gm") userSelect = gmUser; const options = { showFullCard: false, @@ -405,8 +396,8 @@ export async function opportunityAttackScenarios({tokenUuid, regionUuid, regionS }); let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenWeapon, actorUuid: effectOriginActor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenWeapon, actorUuid: effectOriginActor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenWeapon, actorUuid: effectOriginActor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenWeapon, actorUuid: effectOriginActor.uuid, options: options }); await effectOriginActor.unsetFlag("gambits-premades", "dragonTurtleShieldOA"); @@ -438,7 +429,7 @@ export async function opportunityAttackScenarios({tokenUuid, regionUuid, regionS } ]; - await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: token.actor.uuid, effects: effectData }); + await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: token.actor.uuid, effects: effectData }); } //else if(hasSentinel && !checkHits) await effectOriginActor.setFlag("gambits-premades", "sentinelDeclined", true); } @@ -586,7 +577,7 @@ export async function enableOpportunityAttack(combat, combatEvent) { disabled: false, system: { source: ` - if(!game.user.isGM) return; + if(game.user.id !== game.gps.getPrimaryGM()) return; if(event.data.token.uuid !== region.flags["gambits-premades"].tokenUuid) return; let token = await fromUuid(region.flags["gambits-premades"].tokenUuid); let actor = await fromUuid(region.flags["gambits-premades"].actorUuid); @@ -758,14 +749,24 @@ export async function enableOpportunityAttack(combat, combatEvent) { } if(combatEvent === "startCombat") { + let levelsUI = CONFIG.Levels?.UI?.stairEnabled; + if(levelsUI) CONFIG.Levels.UI.stairEnabled = false; + for (let combatant of combat.combatants.values()) { await processCombatant(combatant); } + + if(levelsUI) CONFIG.Levels.UI.stairEnabled = true; } if(combatEvent === "enterCombat") { + let levelsUI = CONFIG.Levels?.UI?.stairEnabled; + if(levelsUI) CONFIG.Levels.UI.stairEnabled = false; + let combatant = combat; await processCombatant(combatant); + + if(levelsUI) CONFIG.Levels.UI.stairEnabled = true; } }; diff --git a/scripts/macros/poetryInMisery.js b/scripts/macros/poetryInMisery.js index 452b1289..63267a61 100644 --- a/scripts/macros/poetryInMisery.js +++ b/scripts/macros/poetryInMisery.js @@ -2,17 +2,17 @@ export async function poetryInMisery({workflowData,workflowType,workflowCombat}) const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid) ?? null; - let itemName = "poetry in misery"; - let itemProperName = "Poetry in Misery"; - let dialogId = "poetryinmisery"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData) ?? null; if(!workflow && workflowCombat === true) return; - if(workflow?.item?.name.toLowerCase() === itemName) return; + const gpsUuid = "f4b6923a-eda4-4c29-a6fb-a1728f6e71e3"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Poetry in Misery"; + let dialogId = gpsUuid; let initiatingToken; (workflow) ? initiatingToken = workflow.token : initiatingToken = await MidiQOL.tokenForActor(workflowData.actor.uuid); + let gmUser = helpers.getPrimaryGM(); - let findValidTokens = helpers.findValidTokens({initiatingToken: initiatingToken, targetedToken: initiatingToken, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: true, rangeTotal: 30, dispositionCheck: true, dispositionCheckType: "ally", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: initiatingToken, targetedToken: initiatingToken, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: true, rangeTotal: 30, dispositionCheck: true, dispositionCheckType: "ally", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; @@ -32,15 +32,13 @@ export async function poetryInMisery({workflowData,workflowType,workflowCombat}) } else continue; + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); let chatActor; - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); if (workflowType === "attack") { if(initiatingToken.document.disposition !== validTokenPrimary.document.disposition) continue; @@ -88,32 +86,25 @@ export async function poetryInMisery({workflowData,workflowType,workflowCombat}) let result; let content = ` ${validTokenPrimary.actor.name} has a reaction available for a roll triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); if (resourceKey) { diff --git a/scripts/macros/powerWordRebound.js b/scripts/macros/powerWordRebound.js index bab70306..14071d73 100644 --- a/scripts/macros/powerWordRebound.js +++ b/scripts/macros/powerWordRebound.js @@ -2,34 +2,31 @@ export async function powerWordRebound({workflowData,workflowType,workflowCombat const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "power word rebound"; - let itemProperName = "Power Word Rebound"; - let dialogId = "powerwordrebound"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name.toLowerCase() === itemName) return; + const gpsUuid = "b8949110-fd25-4d67-a65f-1bdc3d03b36e"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Power Word Rebound"; + let dialogId = gpsUuid; let target = workflow.targets.first(); + let gmUser = helpers.getPrimaryGM(); if(target.actor.system.attributes.hp.value >= Math.floor(target.actor.system.attributes.hp.max / 2)) return; if(workflow.attackTotal < target.actor.system.attributes.ac.value) return; if(workflow.targets.size > 1) return; - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; for (const validTokenPrimary of findValidTokens) { + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } - + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); let dialogContent = `
@@ -56,32 +53,25 @@ export async function powerWordRebound({workflowData,workflowType,workflowCombat let result; let content = ` ${validTokenPrimary.actor.name} has a reaction available for a roll triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); - - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); + + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - chosenItem.prepareData(); chosenItem.prepareFinalAttributes(); chosenItem.applyActiveEffects(); @@ -95,8 +85,8 @@ export async function powerWordRebound({workflowData,workflowType,workflowCombat }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); diff --git a/scripts/macros/protection.js b/scripts/macros/protection.js index 512f4117..f9acab49 100644 --- a/scripts/macros/protection.js +++ b/scripts/macros/protection.js @@ -2,33 +2,33 @@ export async function protection({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "fighting style: protection"; - let itemProperName = "Protection"; - let dialogId = "protection"; - let target = workflow.targets.first(); + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name.toLowerCase() === itemName) return; + const gpsUuid = "82548541-757a-4d56-961a-3f86bb8a14e6"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Fighting Style: Protection"; + let dialogId = gpsUuid; + let target = workflow.targets.first(); let enableProtectionOnSuccess = MidiQOL.safeGetGameSetting('gambits-premades', 'enableProtectionOnSuccess'); if ((enableProtectionOnSuccess && workflow.attackRoll.formula.includes("kl")) || (!enableProtectionOnSuccess && workflow.disadvantage === true)) return; + let gmUser = helpers.getPrimaryGM(); if(enableProtectionOnSuccess && (workflow.attackTotal < target.actor.system.attributes.ac.value)) return; - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "item", itemChecked: ["shield"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemyAlly", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "item", itemChecked: ["shield"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemyAlly", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; for (const validTokenPrimary of findValidTokens) { + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name.toLowerCase() === itemName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) browserUser = game.users?.activeGM; + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); if (target.document.uuid === validTokenPrimary.document.uuid) continue; - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `Protection Timeout`)); let dialogContent = `
@@ -53,33 +53,26 @@ export async function protection({workflowData,workflowType,workflowCombat}) { `; let content = ` ${validTokenPrimary.actor.name} has a reaction available for an attack triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); let primaryFile = "jaamod.condition.magic_shield"; diff --git a/scripts/macros/rainOfCinders.js b/scripts/macros/rainOfCinders.js index 6a9894ba..20d54a05 100644 --- a/scripts/macros/rainOfCinders.js +++ b/scripts/macros/rainOfCinders.js @@ -2,19 +2,19 @@ export async function rainOfCinders({workflowData,workflowType,workflowCombat}) const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "rain of cinders"; - let itemProperName = "Rain of Cinders"; - let dialogId = "rainofcinders"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name.toLowerCase() === itemName) return; + const gspUuid = "a95f3926-ba77-45ab-90d9-c0cf3cca10aa"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Rain of Cinders"; + let dialogId = gspUuid; let target = workflow.targets.first(); let debugEnabled = MidiQOL.safeGetGameSetting('gambits-premades', 'debugEnabled'); + let gmUser = helpers.getPrimaryGM(); if(workflow.targets.size > 1) return; - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: ["drawing the hearth"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: ["drawing the hearth"], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; @@ -23,16 +23,14 @@ export async function rainOfCinders({workflowData,workflowType,workflowCombat}) if(debugEnabled) console.error(`${itemName} for ${validTokenPrimary.actor.name} failed at parent effect active`); continue; } + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); let baseItem = validTokenPrimary.actor.items.find(i => i.name === "Drawing the Hearth"); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); let dialogContent = `
@@ -59,32 +57,25 @@ export async function rainOfCinders({workflowData,workflowType,workflowCombat}) let result; let content = ` ${validTokenPrimary.actor.name} has a reaction available for an attack triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); - - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); + + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - chosenItem.prepareData(); chosenItem.prepareFinalAttributes(); chosenItem.applyActiveEffects(); @@ -98,8 +89,8 @@ export async function rainOfCinders({workflowData,workflowType,workflowCombat}) }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); diff --git a/scripts/macros/riposte.js b/scripts/macros/riposte.js index 79bbaa7c..63917cc6 100644 --- a/scripts/macros/riposte.js +++ b/scripts/macros/riposte.js @@ -1,42 +1,38 @@ -//done export async function riposte({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "maneuvers: riposte"; - let itemProperName = "Riposte"; - let dialogId = "riposte"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name.toLowerCase() === itemName) return; + const gpsUuid = "73ae66c4-4bd4-41cd-b75a-0056ef8b670c"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Maneuvers: Riposte"; + let dialogId = gpsUuid; const actionTypes = ["mwak"]; if (!actionTypes.some(type => workflow.item.system.actionType?.includes(type))) { return; } let target = workflow.targets.first(); + let gmUser = helpers.getPrimaryGM(); let targetAC = target.actor.system.attributes.ac.value; let attackTotal = workflow.attackTotal; if (attackTotal >= targetAC) return; - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: ["superiority dice", "superiority die"], reactionCheck: true, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: ["superiority dice", "superiority die"], reactionCheck: true, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; for (const validTokenPrimary of findValidTokens) { if(validTokenPrimary.id !== target.id) continue; - + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === "Maneuvers: Riposte"); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); const optionBackground = (document.body.classList.contains("theme-dark")) ? 'black' : 'var(--color-bg)'; - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `Riposte Timeout`)); // Check valid weapons let validWeapons = validTokenPrimary.actor.items.filter(item => { @@ -122,33 +118,26 @@ export async function riposte({workflowData,workflowType,workflowCombat}) { `; let content = ` ${validTokenPrimary.actor.name} has a reaction available for an attack triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, selectedItemUuid, favoriteCheck, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - const riposteOptions = { showFullCard: false, createWorkflow: true, @@ -158,8 +147,8 @@ export async function riposte({workflowData,workflowType,workflowCombat}) { }; let riposteRoll; - if(source && source === "user") riposteRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: riposteOptions }); - else if(source && source === "gm") riposteRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: riposteOptions }); + if(source && source === "user") riposteRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: riposteOptions }); + else if(source && source === "gm") riposteRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: riposteOptions }); if(riposteRoll.aborted === true) continue; if (!selectedItemUuid) { @@ -210,8 +199,8 @@ export async function riposte({workflowData,workflowType,workflowCombat}) { }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; const hasEffectAppliedReaction = MidiQOL.hasUsedReaction(validTokenPrimary.actor); diff --git a/scripts/macros/runicShield.js b/scripts/macros/runicShield.js index 4da4e926..f1a2adec 100644 --- a/scripts/macros/runicShield.js +++ b/scripts/macros/runicShield.js @@ -2,35 +2,33 @@ export async function runicShield({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "runic shield"; - let itemProperName = "Runic Shield"; - let dialogId = "runicshield"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name === itemProperName) return; + const gpsUuid = "088a34cd-f8c0-42d0-be77-ccaac97ba913"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Runic Shield"; + let dialogId = gpsUuid; + let gmUser = helpers.getPrimaryGM(); let target = workflow.targets.first(); if(workflow.attackTotal < target.actor.system.attributes.ac.value) return; - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: ["runic shield"], reactionCheck: true, sightCheck: true, sightCheckType: "ally", rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemyAlly", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: "feature", itemChecked: ["runic shield"], reactionCheck: true, sightCheck: true, sightCheckType: "ally", rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemyAlly", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); let browserUser; let browserUserEnemy; for (const validTokenPrimary of findValidTokens) { if(validTokenPrimary.id === target.id) continue; - + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) browserUser = game.users?.activeGM; - browserUserEnemy = MidiQOL.playerForActor(workflow.token.actor); - if (!browserUserEnemy.active) browserUserEnemy = game.users?.activeGM; + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); + browserUserEnemy = helpers.getBrowserUser({ actorUuid: workflow.token.actor.uuid }); - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); let dialogContent = `
@@ -56,32 +54,25 @@ export async function runicShield({workflowData,workflowType,workflowCombat}) { let result; let content = ` ${validTokenPrimary.actor.name} has a reaction available for an attack triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); - - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); + + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - chosenItem.prepareData(); chosenItem.prepareFinalAttributes(); chosenItem.applyActiveEffects(); @@ -95,8 +86,8 @@ export async function runicShield({workflowData,workflowType,workflowCombat}) { }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; @@ -118,7 +109,7 @@ export async function runicShield({workflowData,workflowType,workflowCombat}) { newItemData.prepareFinalAttributes(); newItemData.applyActiveEffects(); - await MidiQOL.socket().executeAsUser("completeItemUse", browserUserEnemy?.id, { itemData: newItemData, actorUuid: workflow.token.actor.uuid, options: optionsEnemy }); + await MidiQOL.socket().executeAsUser("completeItemUse", browserUserEnemy, { itemData: newItemData, actorUuid: workflow.token.actor.uuid, options: optionsEnemy }); } } } \ No newline at end of file diff --git a/scripts/macros/sentinel.js b/scripts/macros/sentinel.js index 216a65cb..b6501beb 100644 --- a/scripts/macros/sentinel.js +++ b/scripts/macros/sentinel.js @@ -3,16 +3,16 @@ export async function sentinel({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const helpers = await import('../helpers.js'); const socket = module.socket; - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "sentinel"; - let itemProperName = "Sentinel"; - let dialogId = "sentinel"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name.toLowerCase() === itemName) return; + const gpsUuid = "f7c0b8c6-a36a-4f29-8adc-38ada0ac186c"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Sentinel"; + let dialogId = gpsUuid; let target = workflow.hitTargets.first(); + let gmUser = helpers.getPrimaryGM(); - let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + let findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: target, itemName: itemName, itemType: null, itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: true, rangeTotal: 5, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); for (const validTokenPrimary of findValidTokens) { if (target.document.uuid === validTokenPrimary.document.uuid || workflow.token.document.disposition === target.document.disposition) continue; @@ -21,16 +21,14 @@ export async function sentinel({workflowData,workflowType,workflowCombat}) { if(target.actor.items.find(i => i.name === itemProperName)) return; + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); - let browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + let browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); const optionBackground = (document.body.classList.contains("theme-dark")) ? 'black' : 'var(--color-bg)'; - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); // Check valid weapons let validWeapons = validTokenPrimary.actor.items.filter(item => { @@ -116,34 +114,27 @@ export async function sentinel({workflowData,workflowType,workflowCombat}) { `; let content = ` ${validTokenPrimary.actor.name} has a reaction available for an attack triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog",browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog",browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, selectedItemUuid, favoriteCheck, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - if (!selectedItemUuid) { console.log("No weapon selected"); continue; @@ -196,8 +187,8 @@ export async function sentinel({workflowData,workflowType,workflowCombat}) { }); let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenWeapon, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; if(checkHits) { @@ -222,7 +213,7 @@ export async function sentinel({workflowData,workflowType,workflowCombat}) { } ]; - await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: target.actor.uuid, effects: effectData }); + await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: target.actor.uuid, effects: effectData }); } await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); diff --git a/scripts/macros/silveryBarbs.js b/scripts/macros/silveryBarbs.js index 1c3eedf9..834e612d 100644 --- a/scripts/macros/silveryBarbs.js +++ b/scripts/macros/silveryBarbs.js @@ -3,13 +3,13 @@ export async function silveryBarbs({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "silvery barbs"; - let itemProperName = "Silvery Barbs"; - let dialogId = "silverybarbs"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name === itemProperName) return; + const gpsUuid = "548b5cab-f870-47b6-828a-8de7549debeb"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Silvery Barbs"; + let dialogId = gpsUuid; + let gmUser = helpers.getPrimaryGM(); // Check if attack hits if(workflowType === "attack" && workflow.attackTotal < workflow.targets.first().actor.system.attributes.ac.value) return; @@ -19,22 +19,22 @@ export async function silveryBarbs({workflowData,workflowType,workflowCombat}) { let findValidTokens; if(workflowType === "attack") { - findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); } else if(workflowType === "save") { - findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: true, dispositionCheckType: "ally", workflowType: workflowType, workflowCombat: workflowCombat}); + findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "spell", itemChecked: null, reactionCheck: true, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: true, dispositionCheckType: "ally", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); } let browserUser; for (const validTokenPrimary of findValidTokens) { - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; - const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; + const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemName}`; + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) browserUser = game.users?.activeGM; + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); let dialogContent; const rollDetailSetting = MidiQOL.safeGetGameSetting('midi-qol', 'ConfigSettings').hideRollDetails; @@ -124,33 +124,27 @@ export async function silveryBarbs({workflowData,workflowType,workflowCombat}) { } let content = ` ${validTokenPrimary.actor.name} has a reaction available for a save triggering ${itemProperName}.` - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle: dialogTitlePrimary, dialogContent, dialogId, initialTimeLeft, validTokenPrimaryUuid: validTokenPrimary.document.uuid, source: "user", type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle: dialogTitlePrimary, dialogContent, dialogId, initialTimeLeft, validTokenPrimaryUuid: validTokenPrimary.document.uuid, source: "user", type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle: dialogTitleGM, dialogContent, dialogId, initialTimeLeft, validTokenPrimaryUuid: validTokenPrimary.document.uuid, source: "gm", type: "multiDialog" }; + let gmDialogArgs = { dialogTitle: dialogTitleGM, dialogContent, dialogId, initialTimeLeft, validTokenPrimaryUuid: validTokenPrimary.document.uuid, source: "gm", type: "multiDialog", notificationId: notificationMessage._id }; - result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); + result = await socket.executeAsUser("handleDialogPromises", gmUser, {userDialogArgs, gmDialogArgs}); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); let advantageToken = await fromUuid(allyTokenUuid); let chatContent; @@ -167,8 +161,8 @@ export async function silveryBarbs({workflowData,workflowType,workflowCombat}) { }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; @@ -216,18 +210,17 @@ export async function silveryBarbs({workflowData,workflowType,workflowCombat}) { } } ]; - if(advantageToken) await MidiQOL.socket().executeAsGM("createEffects", { actorUuid: advantageToken.actor.uuid, effects: effectData }); + if(advantageToken) await MidiQOL.socket().executeAsUser("createEffects", gmUser, { actorUuid: advantageToken.actor.uuid, effects: effectData }); if(workflowType === "save") { let saveDC = workflow.saveItem.system.save.dc; let saveAbility = workflow.saveItem.system.save.ability; let workflowTarget = Array.from(workflow.saves).find(t => t.document.uuid === enemyTokenUuid); - let targetUser = MidiQOL.playerForActor(workflowTarget.actor); - if (!targetUser.active) targetUser = game.users?.activeGM; + let browserUserTarget = helpers.getBrowserUser({ actorUuid: workflowTarget.actor.uuid }); let targetSaveBonus = workflowTarget.actor.system.abilities[`${saveAbility}`].save + workflowTarget.actor.system.abilities[`${saveAbility}`].saveBonus; let reroll; - if(workflowTarget.actor.type !== "npc") reroll = await socket.executeAsUser("rollAsUser", targetUser.id, { rollParams: `1d20 + ${targetSaveBonus}` }); - else reroll = await socket.executeAsGM("rollAsUser", { rollParams: `1d20 + ${targetSaveBonus}` }); + if(workflowTarget.actor.type !== "npc") reroll = await socket.executeAsUser("rollAsUser", browserUserTarget, { rollParams: `1d20 + ${targetSaveBonus}` }); + else reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `1d20 + ${targetSaveBonus}` }); if(reroll.total < saveDC) { workflow.saves.delete(workflowTarget); @@ -250,8 +243,8 @@ export async function silveryBarbs({workflowData,workflowType,workflowCombat}) { const saveSetting = workflow.options.noOnUseMacro; workflow.options.noOnUseMacro = true; let reroll; - if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser.id, { rollParams: `1d20 + ${rerollAddition}` }); - if(source && source === "gm") reroll = await socket.executeAsGM("rollAsUser", { rollParams: `1d20 + ${rerollAddition}` }); + if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser, { rollParams: `1d20 + ${rerollAddition}` }); + if(source && source === "gm") reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `1d20 + ${rerollAddition}` }); if(reroll.total < workflow.attackTotal) await workflow.setAttackRoll(reroll); workflow.options.noOnUseMacro = saveSetting; diff --git a/scripts/macros/witchesHex.js b/scripts/macros/witchesHex.js index 8b1588bf..3c83515e 100644 --- a/scripts/macros/witchesHex.js +++ b/scripts/macros/witchesHex.js @@ -3,13 +3,13 @@ export async function witchesHex({workflowData,workflowType,workflowCombat}) { const module = await import('../module.js'); const socket = module.socket; const helpers = await import('../helpers.js'); - const workflowUuid = workflowData; - const workflow = await MidiQOL.Workflow.getWorkflow(workflowUuid); - let itemName = "witches hex"; - let itemProperName = "Witches Hex"; - let dialogId = "witcheshex"; + const workflow = await MidiQOL.Workflow.getWorkflow(workflowData); if(!workflow) return; - if(workflow.item.name === itemProperName) return; + const gpsUuid = "02fc5000-7f5d-462e-94ac-42a27f453a8f"; + if(workflow.item.flags["gambits-premades"]?.gpsUuid === gpsUuid) return; + let itemName = "Witches Hex"; + let dialogId = gpsUuid; + let gmUser = helpers.getPrimaryGM(); if(workflowType === "save" && workflow.saveResults.length === 0) return; if(workflowType === "attack" && (workflow.isCritical === true || workflow.isFumble === true)) return; @@ -17,28 +17,26 @@ export async function witchesHex({workflowData,workflowType,workflowCombat}) { let findValidTokens; if(workflowType === "attack") { - findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: [itemName], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat}); + findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: [itemName], reactionCheck: true, sightCheck: true, rangeCheck: true, rangeTotal: 60, dispositionCheck: true, dispositionCheckType: "enemy", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); } else if(workflowType === "save") { - findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: [itemName], reactionCheck: true, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: true, dispositionCheckType: "ally", workflowType: workflowType, workflowCombat: workflowCombat}); + findValidTokens = helpers.findValidTokens({initiatingToken: workflow.token, targetedToken: null, itemName: itemName, itemType: "feature", itemChecked: [itemName], reactionCheck: true, sightCheck: false, rangeCheck: false, rangeTotal: null, dispositionCheck: true, dispositionCheckType: "ally", workflowType: workflowType, workflowCombat: workflowCombat, gpsUuid: gpsUuid}); } let browserUser; for (const validTokenPrimary of findValidTokens) { - const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemProperName} Timeout`)); + let chosenItem = validTokenPrimary.actor.items.find(i => i.flags["gambits-premades"]?.gpsUuid === gpsUuid); + let itemProperName = chosenItem?.name; const dialogTitlePrimary = `${validTokenPrimary.actor.name} | ${itemProperName}`; const dialogTitleGM = `Waiting for ${validTokenPrimary.actor.name}'s selection | ${itemProperName}`; + const initialTimeLeft = Number(MidiQOL.safeGetGameSetting('gambits-premades', `${itemName} Timeout`)); let hexDie = validTokenPrimary.actor.system.scale["kp-witch"]["hex-die"]?.die; if(!hexDie) { ui.notifications.error("You must have a Witch scale for this actor named 'kp-witch'") continue; } - let chosenItem = validTokenPrimary.actor.items.find(i => i.name === itemProperName); - browserUser = MidiQOL.playerForActor(validTokenPrimary.actor); - if (!browserUser.active) { - browserUser = game.users?.activeGM; - } + browserUser = helpers.getBrowserUser({ actorUuid: validTokenPrimary.actor.uuid }); let content; let dialogContent; const optionBackground = (document.body.classList.contains("theme-dark")) ? 'black' : 'var(--color-bg)'; @@ -109,34 +107,27 @@ export async function witchesHex({workflowData,workflowType,workflowCombat}) { content = ` ${validTokenPrimary.actor.name} has a reaction available for an attack triggering ${itemProperName}.` } - let chatData = { - user: game.users.find(u => u.isGM).id, - content: content, - whisper: game.users.find(u => u.isGM).id - }; - let notificationMessage = await MidiQOL.socket().executeAsGM("createChatMessage", { chatData }); + let chatData = { user: gmUser, content: content, roll: false, whisper: gmUser }; + let notificationMessage = await MidiQOL.socket().executeAsUser("createChatMessage", gmUser, { chatData }); let result; - if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser.id !== game.users?.activeGM.id) { - let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser.id }; + if (MidiQOL.safeGetGameSetting('gambits-premades', 'Mirror 3rd Party Dialog for GMs') && browserUser !== gmUser) { + let userDialogArgs = { dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "user",type: "multiDialog", browserUser: browserUser, notificationId: notificationMessage._id }; - let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog" }; + let gmDialogArgs = { dialogTitle:dialogTitleGM,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: "gm",type: "multiDialog", notificationId: notificationMessage._id }; result = await socket.executeAsGM("handleDialogPromises", userDialogArgs, gmDialogArgs); } else { - result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser.id, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source:browserUser.isGM ? "gm" : "user",type:"singleDialog"}); + result = await socket.executeAsUser("process3rdPartyReactionDialog", browserUser, {dialogTitle:dialogTitlePrimary,dialogContent,dialogId,initialTimeLeft,validTokenPrimaryUuid: validTokenPrimary.document.uuid,source: gmUser === browserUser ? "gm" : "user",type:"singleDialog", notificationId: notificationMessage._id}); } const { userDecision, enemyTokenUuid, allyTokenUuid, damageChosen, selectedItemUuid, favoriteCheck, source, type } = result; if (!userDecision) { - if(source === "gm" || type === "singleDialog") await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); continue; } else if (userDecision) { - await socket.executeAsGM("deleteChatMessage", { chatId: notificationMessage._id }); - let target; let targetDocument; if(workflowType === "attack") { @@ -160,8 +151,8 @@ export async function witchesHex({workflowData,workflowType,workflowCombat}) { }; let itemRoll; - if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser?.id, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); - else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsGM("completeItemUse", { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + if(source && source === "user") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", browserUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); + else if(source && source === "gm") itemRoll = await MidiQOL.socket().executeAsUser("completeItemUse", gmUser, { itemData: chosenItem, actorUuid: validTokenPrimary.actor.uuid, options: options }); if(itemRoll.aborted === true) continue; await helpers.addReaction({actorUuid: `${validTokenPrimary.actor.uuid}`}); @@ -263,8 +254,8 @@ export async function witchesHex({workflowData,workflowType,workflowCombat}) { workflow.options.noOnUseMacro = true; let saveDC = workflow.saveItem.system.save.dc; - if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser.id, { rollParams: `1${hexDie}`, type: workflowType }); - if(source && source === "gm") reroll = await socket.executeAsGM("rollAsUser", { rollParams: `1${hexDie}`, type: workflowType }); + if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser, { rollParams: `1${hexDie}`, type: workflowType }); + if(source && source === "gm") reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `1${hexDie}`, type: workflowType }); let rollFound = workflow.saveRolls.find(roll => roll.data.tokenUuid === returnedTokenUuid); let rollTotal = rollFound.total; let modifiedRoll = await new Roll(`${rollTotal} - ${reroll.total}`).evaluate(); @@ -290,8 +281,8 @@ export async function witchesHex({workflowData,workflowType,workflowCombat}) { const saveSetting = workflow.options.noOnUseMacro; workflow.options.noOnUseMacro = true; let reroll; - if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser.id, { rollParams: `1${hexDie}`, type: workflowType }); - if(source && source === "gm") reroll = await socket.executeAsGM("rollAsUser", { rollParams: `1${hexDie}`, type: workflowType }); + if(source && source === "user") reroll = await socket.executeAsUser("rollAsUser", browserUser, { rollParams: `1${hexDie}`, type: workflowType }); + if(source && source === "gm") reroll = await socket.executeAsUser("rollAsUser", gmUser, { rollParams: `1${hexDie}`, type: workflowType }); let rerollNew = await new Roll(`${workflow.attackRoll.result} - ${reroll.total}`).roll(); await workflow.setAttackRoll(rerollNew); diff --git a/scripts/module.js b/scripts/module.js index 1ddc35b9..8aa769f5 100644 --- a/scripts/module.js +++ b/scripts/module.js @@ -21,7 +21,7 @@ import { instinctiveCharm } from './macros/instinctiveCharm.js'; import { rainOfCinders } from './macros/rainOfCinders.js'; import { biohazard } from './macros/biohazard.js'; import { enableOpportunityAttack, disableOpportunityAttack, opportunityAttackScenarios } from './macros/opportunityAttack.js'; -import { deleteChatMessage, gmIdentifyItem, closeDialogById, handleDialogPromises, rollAsUser, convertFromFeet, gmUpdateTemplateSize, findValidTokens, pauseDialogById, freeSpellUse, process3rdPartyReactionDialog, moveTokenByCardinal, moveTokenByOriginPoint, addReaction, gmUpdateDisposition, gmToggleStatus, replaceChatCard, validateRegionMovement, ritualSpellUse } from './helpers.js'; +import { deleteChatMessage, gmIdentifyItem, closeDialogById, handleDialogPromises, rollAsUser, convertFromFeet, gmUpdateTemplateSize, findValidTokens, pauseDialogById, freeSpellUse, process3rdPartyReactionDialog, moveTokenByCardinal, moveTokenByOriginPoint, addReaction, gmUpdateDisposition, gmToggleStatus, replaceChatCard, validateRegionMovement, ritualSpellUse, getBrowserUser, getPrimaryGM } from './helpers.js'; export let socket; Hooks.once('init', async function() { @@ -29,78 +29,81 @@ Hooks.once('init', async function() { game.gpsSettings = game.gpsSettings || {}; await updateSettings(); - libWrapper.register('gambits-premades', 'Token.prototype.testInsideRegion', function (wrapped, ...args) { - const [region, position] = args; + let wrappingEnabled = game.settings.get("gambits-premades", "enableRegionWrapping"); + if(wrappingEnabled) { + libWrapper.register('gambits-premades', 'Token.prototype.testInsideRegion', function (wrapped, ...args) { + const [region, position] = args; - if (canvas.scene.grid.type >= 2) return wrapped(...args); //Don't wrap hex grid types for now - - if (!this || !this.document) return wrapped(...args); + if (canvas.scene.grid.type >= 2) return wrapped(...args); //Don't wrap hex grid types for now - const pointsToTest = []; - const size = canvas.dimensions.size; - const width = this.document.width; - const height = this.document.height; - const reduction = 5; + if (!this || !this.document) return wrapped(...args); + + const pointsToTest = []; + const size = canvas.dimensions.size; + const width = this.document.width; + const height = this.document.height; + const reduction = 5; + + const points = [ + { x: this.document.x + reduction, y: this.document.y + reduction, elevation: this.document.elevation }, + { x: this.document.x + (width * size) - reduction, y: this.document.y + reduction, elevation: this.document.elevation }, + { x: this.document.x + reduction, y: this.document.y + (height * size) - reduction, elevation: this.document.elevation }, + { x: this.document.x + (width * size) - reduction, y: this.document.y + (height * size) - reduction, elevation: this.document.elevation }, + { x: this.document.x + (width * size / 2), y: this.document.y + reduction, elevation: this.document.elevation }, + { x: this.document.x + (width * size / 2), y: this.document.y + (height * size) - reduction, elevation: this.document.elevation }, + { x: this.document.x + reduction, y: this.document.y + (height * size / 2), elevation: this.document.elevation }, + { x: this.document.x + (width * size) - reduction, y: this.document.y + (height * size / 2), elevation: this.document.elevation }, + { x: this.document.x + (width * size / 2), y: this.document.y + (height * size / 2), elevation: this.document.elevation } + ]; - const points = [ - { x: this.document.x + reduction, y: this.document.y + reduction, elevation: this.document.elevation }, - { x: this.document.x + (width * size) - reduction, y: this.document.y + reduction, elevation: this.document.elevation }, - { x: this.document.x + reduction, y: this.document.y + (height * size) - reduction, elevation: this.document.elevation }, - { x: this.document.x + (width * size) - reduction, y: this.document.y + (height * size) - reduction, elevation: this.document.elevation }, - { x: this.document.x + (width * size / 2), y: this.document.y + reduction, elevation: this.document.elevation }, - { x: this.document.x + (width * size / 2), y: this.document.y + (height * size) - reduction, elevation: this.document.elevation }, - { x: this.document.x + reduction, y: this.document.y + (height * size / 2), elevation: this.document.elevation }, - { x: this.document.x + (width * size) - reduction, y: this.document.y + (height * size / 2), elevation: this.document.elevation }, - { x: this.document.x + (width * size / 2), y: this.document.y + (height * size / 2), elevation: this.document.elevation } - ]; - - points.forEach(point => { - pointsToTest.push(point); - }); - - const testResults = pointsToTest.map(point => { - const result = region.testPoint(point, position?.elevation ?? this.document.elevation); - return result; - }); - - const isInside = testResults.some(x => x); - - return isInside || wrapped(...args); - }, 'MIXED'); - - libWrapper.register('gambits-premades', 'Token.prototype.segmentizeRegionMovement', function (wrapped, ...args) { - const [region, waypoints, options] = args; - - if (!this || !this.document) { - return wrapped(...args); - } + points.forEach(point => { + pointsToTest.push(point); + }); - const { teleport = false } = options || {}; - const samples = []; - const size = canvas.dimensions.size; - const width = this.document.width; - const height = this.document.height; - const reduction = 5; - - const points = [ - { x: reduction, y: reduction, elevation: this.document.elevation }, - { x: width * size - reduction, y: reduction, elevation: this.document.elevation }, - { x: reduction, y: height * size - reduction, elevation: this.document.elevation }, - { x: width * size - reduction, y: height * size - reduction, elevation: this.document.elevation }, - { x: width * size / 2, y: reduction, elevation: this.document.elevation }, - { x: width * size / 2, y: height * size - reduction, elevation: this.document.elevation }, - { x: reduction, y: height * size / 2, elevation: this.document.elevation }, - { x: width * size - reduction, y: height * size / 2, elevation: this.document.elevation } - ]; - - points.forEach(point => { - samples.push(point); - }); + const testResults = pointsToTest.map(point => { + const result = region.testPoint(point, position?.elevation ?? this.document.elevation); + return result; + }); + + const isInside = testResults.some(x => x); + + return isInside || wrapped(...args); + }, 'MIXED'); + + libWrapper.register('gambits-premades', 'Token.prototype.segmentizeRegionMovement', function (wrapped, ...args) { + const [region, waypoints, options] = args; + + if (!this || !this.document) { + return wrapped(...args); + } + + const { teleport = false } = options || {}; + const samples = []; + const size = canvas.dimensions.size; + const width = this.document.width; + const height = this.document.height; + const reduction = 5; - const segments = region.segmentizeMovement(waypoints, samples, { teleport }); + const points = [ + { x: reduction, y: reduction, elevation: this.document.elevation }, + { x: width * size - reduction, y: reduction, elevation: this.document.elevation }, + { x: reduction, y: height * size - reduction, elevation: this.document.elevation }, + { x: width * size - reduction, y: height * size - reduction, elevation: this.document.elevation }, + { x: width * size / 2, y: reduction, elevation: this.document.elevation }, + { x: width * size / 2, y: height * size - reduction, elevation: this.document.elevation }, + { x: reduction, y: height * size / 2, elevation: this.document.elevation }, + { x: width * size - reduction, y: height * size / 2, elevation: this.document.elevation } + ]; - return segments || wrapped(...args); - }, 'MIXED'); + points.forEach(point => { + samples.push(point); + }); + + const segments = region.segmentizeMovement(waypoints, samples, { teleport }); + + return segments || wrapped(...args); + }, 'MIXED'); + } }); Hooks.once('socketlib.ready', async function() { @@ -149,6 +152,7 @@ Hooks.once('socketlib.ready', async function() { socket.register("replaceChatCard", replaceChatCard); socket.register("validateRegionMovement", validateRegionMovement); socket.register("ritualSpellUse", ritualSpellUse); + socket.register("getBrowserUser", getBrowserUser); }) Hooks.once('ready', async function() { @@ -157,6 +161,8 @@ Hooks.once('ready', async function() { }).catch(error => { console.error("Error loading compendium data:", error); }); + + if(!game.gpsSettings.primaryGM) game.settings.set("gambits-premades", "primaryGM", game.users.activeGM.id); game.gps = { gmIdentifyItem, @@ -174,6 +180,7 @@ Hooks.once('ready', async function() { rainOfCinders, biohazard, ritualSpellUse, + getPrimaryGM, socket }; @@ -183,11 +190,7 @@ Hooks.once('ready', async function() { async function executeWorkflow({ workflowItem, workflowData, workflowType, workflowCombat }) { if(!game.gpsSettings.enable3prNoCombat && !game.combat && workflowCombat) return; - if (game.user.isGM) { - await socket.executeAsGM( workflowItem, { workflowData: workflowData, workflowType: workflowType, workflowCombat: workflowCombat }); - } else { - await socket.executeAsUser( workflowItem, game.user.id, { workflowData: workflowData, workflowType: workflowType, workflowCombat: workflowCombat }); - } + await socket.executeAsUser( workflowItem, game.user.id, { workflowData: workflowData, workflowType: workflowType, workflowCombat: workflowCombat }); } Hooks.on("midi-qol.prePreambleComplete", async (workflow) => { @@ -282,14 +285,14 @@ Hooks.once('ready', async function() { }); Hooks.on("preUpdateCombat", (combat, update, options) => { - if(!game.user.isGM) return; + if (game.user.id !== getPrimaryGM()) return; const startedPath = `gambits-premades.started`; const prevStarted = combat.started; foundry.utils.setProperty(options, startedPath, prevStarted); }) Hooks.on("updateCombat", async (combat, update, options) => { - if(!game.user.isGM) return; + if(game.user.id !== getPrimaryGM()) return; const combatStarted = combat.started && !foundry.utils.getProperty(options, `gambits-premades.started`); const hasProcessedStart = await combat.getFlag('gambits-premades', `startProcessed-${combat.id}`); if(combatStarted && !hasProcessedStart && game.gpsSettings.opportunityAttackEnabled) { @@ -299,7 +302,7 @@ Hooks.on("updateCombat", async (combat, update, options) => { }) Hooks.on("createCombatant", async (combatant, options, userId) => { - if(!game.user.isGM) return; + if(game.user.id !== getPrimaryGM()) return; let combat = game.combat; if (combat && combat.started && game.gpsSettings.opportunityAttackEnabled) { await enableOpportunityAttack(combatant, "enterCombat"); @@ -307,12 +310,12 @@ Hooks.on("createCombatant", async (combatant, options, userId) => { }); Hooks.on('deleteCombat', async (combat) => { - if(!game.user.isGM) return; + if(game.user.id !== getPrimaryGM()) return; if(game.gpsSettings.opportunityAttackEnabled) await disableOpportunityAttack(combat, "endCombat"); }); Hooks.on("deleteCombatant", async (combatant, options, userId) => { - if(!game.user.isGM) return; + if(game.user.id !== getPrimaryGM()) return; let combat = game.combat; if (combat && combat.started && game.gpsSettings.opportunityAttackEnabled) { await disableOpportunityAttack(combatant, "exitCombat"); @@ -345,7 +348,8 @@ async function updateSettings(settingKey = null) { 'enableMageSlayer': 'mageSlayerEnabled', 'enableInstinctiveCharm': 'instinctiveCharmEnabled', 'enableRainOfCinders': 'rainOfCindersEnabled', - 'Enable Opportunity Attack': 'opportunityAttackEnabled' + 'Enable Opportunity Attack': 'opportunityAttackEnabled', + 'primaryGM': 'primaryGM' }; if (settingKey === null) { @@ -361,7 +365,7 @@ async function updateSettings(settingKey = null) { } Hooks.on('updateSetting', (setting) => { - if (!game.user.isGM) return; + if (game.user.id !== getPrimaryGM()) return; if (setting.config.namespace === "gambits-premades") { updateSettings(setting.config.key); } @@ -402,7 +406,7 @@ function setupTemplateVisibilityHook() { }); canvas.templates.placeables.forEach(template => { - if(!game.user.isGM) return; + if(game.user.id !== getPrimaryGM()) return; if (game.gpsSettings.hideTemplates || template.document.getFlag('gambits-premades', 'templateHiddenOA')) { hideTemplateElements(template); } @@ -427,7 +431,7 @@ function setupTemplateCreationUpdateHooks() { } async function updateRegionPosition(region, tokenDocument) { - if (!game.user.isGM) return; + if (game.user.id !== getPrimaryGM()) return; if (!region || !tokenDocument) return; let regionDisabled = region.getFlag("gambits-premades", "regionDisabled"); @@ -492,7 +496,7 @@ async function updateRegionPosition(region, tokenDocument) { } Hooks.on('updateToken', async (tokenDocument, updateData, options, userId) => { - if (!game.user.isGM) return; + if (game.user.id !== getPrimaryGM()) return; if(!game.gpsSettings.opportunityAttackEnabled) return; if(!game.combat) return; diff --git a/scripts/settings.js b/scripts/settings.js index bddb25e6..4121ad9d 100644 --- a/scripts/settings.js +++ b/scripts/settings.js @@ -566,6 +566,24 @@ function registerSettings() { } }); + game.settings.register("gambits-premades", "enableRegionWrapping", { + name: "enableRegionWrapping", + scope: "world", + config: false, + type: Boolean, + default: true, + type: Boolean + }); + + game.settings.register('gambits-premades', 'primaryGM', { + name: "primaryGM", + hint: "", + scope: 'world', + config: false, + type: String, + default: "" + }); + game.settings.registerMenu('gambits-premades', 'generalSettings', { name: game.i18n.localize("General Settings"), label: game.i18n.localize("General Settings"), @@ -716,6 +734,7 @@ class BaseSettingsMenu extends FormApplication { const settings = { enableInterceptionCustomDiceNumber: Number(game.settings.get("gambits-premades", "enableInterceptionCustomDiceNumber")), enableInterceptionCustomDiceFace: Number(game.settings.get("gambits-premades", "enableInterceptionCustomDiceFace")), + primaryGM: game.settings.get("gambits-premades", "primaryGM") }; const numberSelect = html.find('#enableInterceptionCustomDiceNumber'); @@ -727,7 +746,7 @@ class BaseSettingsMenu extends FormApplication { option.selected = true; } numberSelect.append(option); - } + }; const faceSelect = html.find('#enableInterceptionCustomDiceFace'); const faces = [4, 6, 8, 10, 12, 20]; @@ -740,6 +759,18 @@ class BaseSettingsMenu extends FormApplication { } faceSelect.append(option); }); + + const primaryGM = html.find('#primaryGM'); + for (const user of game.users.contents) { + if(!user.isGM) continue; + const option = document.createElement('option'); + option.value = user.id; + option.textContent = user.name; + if (user.id === settings.primaryGM) { + option.selected = true; + } + primaryGM.append(option); + }; } } @@ -906,7 +937,9 @@ class generalSettingsMenu extends BaseSettingsMenu { hideTemplates: game.settings.get("gambits-premades", "hideTemplates"), debugEnabled: game.settings.get("gambits-premades", "debugEnabled"), enableIdentifyRestrictions: game.settings.get("gambits-premades", "Enable Identify Restrictions"), - identifyRestrictionMessage: game.settings.get("gambits-premades", "Identify Restriction Message") + identifyRestrictionMessage: game.settings.get("gambits-premades", "Identify Restriction Message"), + enableRegionWrapping: game.settings.get("gambits-premades", "enableRegionWrapping"), + primaryGM: game.settings.get("gambits-premades", "primaryGM") }; } @@ -918,5 +951,7 @@ class generalSettingsMenu extends BaseSettingsMenu { await game.settings.set("gambits-premades", "debugEnabled", formData.debugEnabled); await game.settings.set("gambits-premades", "Enable Identify Restrictions", formData.enableIdentifyRestrictions); await game.settings.set("gambits-premades", "Identify Restriction Message", formData.identifyRestrictionMessage); + await game.settings.set("gambits-premades", "enableRegionWrapping", formData.enableRegionWrapping); + await game.settings.set("gambits-premades", "primaryGM", formData.primaryGM); } } \ No newline at end of file diff --git a/templates/generalSettingsMenu.html b/templates/generalSettingsMenu.html index 102b9fa9..ec53d647 100644 --- a/templates/generalSettingsMenu.html +++ b/templates/generalSettingsMenu.html @@ -118,12 +118,12 @@ -