All user data for FoundryVTT. Includes worlds, systems, modules, and any asset in the "foundryuserdata" directory. Does NOT include the FoundryVTT installation itself.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
9.5 KiB

1 year ago
  1. export function registerWrappers(){
  2. const LevelsConfig = CONFIG.Levels
  3. const computeUI = LevelsConfig.handlers.UIHandler.UIVisible
  4. /*Hooks.on("refreshTile", (placeable) => {
  5. const visible = LevelsConfig.handlers.TileHandler.isTileVisible(placeable);
  6. placeable.visible = placeable.visible && visible;
  7. computeUI(placeable);
  8. })*/
  9. Hooks.on("refreshTile", (placeable) => {
  10. const visible = LevelsConfig.handlers.TileHandler.isTileVisible(placeable);
  11. if(CONFIG.Levels.currentToken || canvas.tokens.controlled.length) {
  12. if ((CONFIG.Levels.currentToken ?? canvas.tokens.controlled[0]).losHeight < placeable.document.elevation) {
  13. if (!visible) {
  14. if(placeable.mesh){
  15. placeable.mesh.occluded = true;
  16. placeable.mesh.shader.enabled = false;
  17. placeable.mesh.alpha = 0;
  18. }
  19. }
  20. } else {
  21. placeable.visible = placeable.visible && visible;
  22. }
  23. } else {
  24. placeable.visible = placeable.visible && visible;
  25. }
  26. computeUI(placeable);
  27. })
  28. Hooks.on("refreshDrawing", (placeable) => {
  29. const visible = LevelsConfig.handlers.DrawingHandler.isDrawingVisible(placeable);
  30. placeable.visible = placeable.visible && visible;
  31. computeUI(placeable);
  32. })
  33. Hooks.on("refreshToken", (placeable) => {
  34. CONFIG.Levels.FoWHandler.lazyCreateBubble(placeable);
  35. LevelsConfig.handlers.TokenHandler.setScale(placeable);
  36. computeUI(placeable);
  37. })
  38. Hooks.on("updateToken", (token, updates) => {
  39. if("elevation" in updates && CONFIG.Levels.settings.get("tokenElevScale")){
  40. LevelsConfig.handlers.RefreshHandler.refresh(canvas.tokens)
  41. }
  42. })
  43. Hooks.on("controlToken", (token, control) => {
  44. CONFIG.Levels.settings.get("tokenElevScale") && LevelsConfig.handlers.RefreshHandler.refresh(canvas.tokens)
  45. })
  46. Hooks.on("refreshAmbientLight", (placeable) => {
  47. computeUI(placeable);
  48. })
  49. Hooks.on("refreshNote", (placeable) => {
  50. computeUI(placeable);
  51. })
  52. Hooks.on("refreshWall", (placeable) => {
  53. computeUI(placeable);
  54. })
  55. Hooks.on("refreshAmbientSound", (placeable) => {
  56. computeUI(placeable);
  57. })
  58. libWrapper.register(
  59. LevelsConfig.MODULE_ID,
  60. "CONFIG.Tile.objectClass.prototype.isRoof", function isRoof(wrapped, ...args){
  61. if(this.document.flags?.levels?.noCollision || this.document.flags["tile-scroll"]?.enableRotate || this.document.flags["tile-scroll"]?.enableScroll) return wrapped(...args);
  62. return wrapped(...args) || (this.document.overhead && Number.isFinite(this.document.flags?.levels?.rangeBottom));
  63. },
  64. "WRAPPER"
  65. );
  66. libWrapper.register(
  67. LevelsConfig.MODULE_ID,
  68. "CONFIG.Wall.objectClass.prototype.identifyInteriorState", function disableInteriorState(wrapped,...args){
  69. this.roof = null;
  70. for (const tile of canvas.tiles.roofs) {
  71. const allWallBlockSight = tile.document?.flags?.levels?.allWallBlockSight ?? true;
  72. if (tile.document.hidden || !allWallBlockSight) continue;
  73. const isBottomFinite = Number.isFinite(tile.document.flags?.levels?.rangeBottom);
  74. if (isBottomFinite && Number.isFinite(tile.document?.flags?.levels?.rangeTop)) continue;
  75. if(isBottomFinite){
  76. const bottom = tile.document.flags?.levels?.rangeBottom;
  77. const wallBottom = this.document.flags["wall-height"]?.bottom ?? -Infinity;
  78. if(wallBottom >= bottom) continue;
  79. }
  80. const [x1, y1, x2, y2] = this.document.c;
  81. const isInterior = tile.containsPixel(x1, y1) && tile.containsPixel(x2, y2);
  82. if (isInterior) {
  83. this.roof = tile;
  84. break;
  85. }
  86. }
  87. },
  88. "OVERRIDE",
  89. { perf_mode: "FAST" }
  90. );
  91. libWrapper.register(
  92. LevelsConfig.MODULE_ID,
  93. "TilesLayer.prototype.displayRoofs", function displayRoofs(wrapped, ...args){
  94. const res = wrapped(...args);
  95. return res || (CONFIG.Levels.UI?.rangeEnabled && !canvas.tokens.controlled.length);
  96. },
  97. "WRAPPER"
  98. );
  99. Hooks.on("activateTilesLayer ", () => {
  100. if(CONFIG.Levels.UI?.rangeEnabled){
  101. ui.controls.control.foreground = true;
  102. canvas.tiles._activateSubLayer(true);
  103. }
  104. })
  105. const visibilityTestObjectStack = [];
  106. libWrapper.register(
  107. LevelsConfig.MODULE_ID,
  108. "CanvasVisibility.prototype.testVisibility",
  109. function visibilityWrapper(wrapped, ...args) {
  110. const options = args[1] ??= {};
  111. if (options.object instanceof Token) options.tolerance = 0;
  112. visibilityTestObjectStack.push(LevelsConfig.visibilityTestObject);
  113. LevelsConfig.visibilityTestObject = args[1].object;
  114. const res = wrapped(...args);
  115. LevelsConfig.visibilityTestObject = visibilityTestObjectStack.pop();
  116. return !!res;
  117. },
  118. "WRAPPER"
  119. );
  120. function elevatePoints(config, visionSource) {
  121. const object = config.object;
  122. const unitsToPixel = canvas.dimensions.size / canvas.dimensions.distance;
  123. if (object instanceof Token) {
  124. if (config.tests._levels !== object) {
  125. config.tests.length = 0;
  126. for (const p of LevelsConfig.handlers.SightHandler.getTestPoints(object)) {
  127. config.tests.push({ point: { x: p.x, y: p.y, z: p.z * unitsToPixel }, los: new Map() });
  128. }
  129. config.tests._levels = object;
  130. }
  131. } else {
  132. let z;
  133. if (object instanceof PlaceableObject) {
  134. z = object.document.elevation ?? object.document.flags.levels?.rangeBottom;
  135. } else if (object instanceof DoorControl) {
  136. z = visionSource?.elevation;
  137. }
  138. z ??= canvas.primary.background.elevation;
  139. z *= unitsToPixel;
  140. for (const test of config.tests) {
  141. test.point.z = z;
  142. }
  143. }
  144. return config;
  145. }
  146. libWrapper.register(
  147. LevelsConfig.MODULE_ID,
  148. "DetectionMode.prototype.testVisibility",
  149. function (wrapped, visionSource, mode, config) {
  150. return wrapped(visionSource, mode, elevatePoints(config, visionSource));
  151. },
  152. "WRAPPER",
  153. { perf_mode: "FAST" }
  154. );
  155. libWrapper.register(
  156. LevelsConfig.MODULE_ID,
  157. "LightSource.prototype.testVisibility",
  158. function (wrapped, config) {
  159. return wrapped(elevatePoints(config, CONFIG.Levels.currentToken?.vision));
  160. },
  161. "WRAPPER",
  162. { perf_mode: "FAST" }
  163. );
  164. if(!game.modules.get("perfect-vision")?.active){
  165. libWrapper.register(
  166. LevelsConfig.MODULE_ID,
  167. "DetectionMode.prototype._testRange",
  168. LevelsConfig.handlers.SightHandler._testRange,
  169. "OVERRIDE",
  170. { perf_mode: "FAST" }
  171. );
  172. }
  173. libWrapper.register(
  174. LevelsConfig.MODULE_ID,
  175. "ClockwiseSweepPolygon.prototype.contains",
  176. LevelsConfig.handlers.SightHandler.containsWrapper,
  177. "MIXED"
  178. );
  179. libWrapper.register(
  180. LevelsConfig.MODULE_ID,
  181. "ClockwiseSweepPolygon.prototype._testCollision",
  182. LevelsConfig.handlers.SightHandler._testCollision,
  183. "MIXED"
  184. );
  185. libWrapper.register(
  186. LevelsConfig.MODULE_ID,
  187. "CONFIG.AmbientLight.objectClass.prototype.emitsLight",
  188. LevelsConfig.handlers.LightHandler.isLightVisibleWrapper,
  189. "WRAPPER"
  190. );
  191. libWrapper.register(
  192. LevelsConfig.MODULE_ID,
  193. "CONFIG.Token.objectClass.prototype.emitsLight",
  194. LevelsConfig.handlers.LightHandler.isLightVisibleWrapper,
  195. "WRAPPER"
  196. );
  197. libWrapper.register(
  198. LevelsConfig.MODULE_ID,
  199. "CONFIG.AmbientSound.objectClass.prototype.isAudible",
  200. LevelsConfig.handlers.SoundHandler.isAudible,
  201. "WRAPPER"
  202. );
  203. libWrapper.register(
  204. LevelsConfig.MODULE_ID,
  205. "CONFIG.Note.objectClass.prototype.isVisible",
  206. LevelsConfig.handlers.NoteHandler.isVisible,
  207. "WRAPPER"
  208. );
  209. libWrapper.register(
  210. LevelsConfig.MODULE_ID,
  211. "CONFIG.Token.objectClass.prototype._drawTooltip",
  212. LevelsConfig.handlers.TokenHandler._drawTooltip,
  213. "MIXED"
  214. );
  215. libWrapper.register(
  216. LevelsConfig.MODULE_ID,
  217. "CONFIG.MeasuredTemplate.objectClass.prototype.draw",
  218. LevelsConfig.handlers.TemplateHandler.drawTooltip,
  219. "WRAPPER"
  220. );
  221. libWrapper.register(
  222. LevelsConfig.MODULE_ID,
  223. "CONFIG.MeasuredTemplate.objectClass.prototype._refreshRulerText",
  224. LevelsConfig.handlers.TemplateHandler._refreshRulerText,
  225. "OVERRIDE"
  226. );
  227. libWrapper.register(
  228. LevelsConfig.MODULE_ID,
  229. "CONFIG.MeasuredTemplate.objectClass.prototype.isVisible",
  230. LevelsConfig.handlers.TemplateHandler.isVisible,
  231. "WRAPPER"
  232. );
  233. libWrapper.register(
  234. LevelsConfig.MODULE_ID,
  235. "CanvasOcclusionMask.prototype._identifyOccludedTiles",
  236. LevelsConfig.handlers.TileHandler._identifyOccludedTiles,
  237. "OVERRIDE"
  238. );
  239. libWrapper.register(LevelsConfig.MODULE_ID, "CONFIG.Token.objectClass.prototype.isVisible", LevelsConfig.handlers.UIHandler.tokenUIWrapperIsVisible, "WRAPPER");
  240. }