Skip to content

Commit 32018a7

Browse files
authored
Add files via upload
1 parent ad7d8fb commit 32018a7

File tree

5 files changed

+177
-13
lines changed

5 files changed

+177
-13
lines changed

module.json

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
"dependencies": [
3232
{
3333
"name": "betterroofs"
34+
},
35+
{
36+
"name": "lib-wrapper"
3437
}
3538
]
3639
}

scripts/config.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Hooks.on("ready",()=>{
2+
libWrapper.register(_levelsModuleName,"Token.prototype.refresh", levelsTokenRefresh, "OVERRIDE")
3+
libWrapper.register(_levelsModuleName,"Token.prototype._onMovementFrame", _levelsOnMovementFrame, "OVERRIDE")
4+
})
5+
16
Hooks.on("renderTileConfig", (app, html, data) => {
27
let heightRange = app.object.getFlag(
38
_levelsModuleName,

scripts/helpers.js

+79-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,79 @@
1-
/////
1+
function levelsTokenRefresh() {
2+
// Token position and visibility
3+
if (!this._movement) this.position.set(this.data.x, this.data.y);
4+
5+
// Size the texture aspect ratio within the token frame
6+
const tex = this.texture;
7+
if (tex) {
8+
let aspect = tex.width / tex.height;
9+
const scale = this.icon.scale;
10+
if (aspect >= 1) {
11+
this.icon.width = this.w * this.data.scale;
12+
scale.y = Number(scale.x);
13+
} else {
14+
this.icon.height = this.h * this.data.scale;
15+
scale.x = Number(scale.y);
16+
}
17+
}
18+
19+
// Mirror horizontally or vertically
20+
this.icon.scale.x =
21+
Math.abs(this.icon.scale.x) * (this.data.mirrorX ? -1 : 1);
22+
this.icon.scale.y =
23+
Math.abs(this.icon.scale.y) * (this.data.mirrorY ? -1 : 1);
24+
25+
// Set rotation, position, and opacity
26+
this.icon.rotation = this.data.lockRotation
27+
? 0
28+
: Math.toRadians(this.data.rotation);
29+
this.icon.position.set(this.w / 2, this.h / 2);
30+
if (!this.levelsHidden)
31+
this.icon.alpha = this.data.hidden
32+
? Math.min(this.data.alpha, 0.5)
33+
: this.data.alpha;
34+
35+
// Refresh Token border and target
36+
this._refreshBorder();
37+
this._refreshTarget();
38+
39+
// Refresh nameplate and resource bars
40+
this.nameplate.visible = this._canViewMode(this.data.displayName);
41+
this.bars.visible = this._canViewMode(this.data.displayBars);
42+
return this;
43+
}
44+
45+
function _levelsOnMovementFrame(dt, anim, config) {
46+
// Update the displayed position of the Token
47+
this.data.x = this.x;
48+
this.data.y = this.y;
49+
// Update the token copy
50+
let tempTokenSprite = _levels.floorContainer.spriteIndex[this.id];
51+
if (tempTokenSprite) {
52+
tempTokenSprite.width = this.data.width * canvas.scene.dimensions.size;
53+
tempTokenSprite.height = this.data.height * canvas.scene.dimensions.size;
54+
tempTokenSprite.position.x = this.position.x;
55+
tempTokenSprite.position.y = this.position.y;
56+
tempTokenSprite.position.x += this.icon.x;
57+
tempTokenSprite.position.y += this.icon.y;
58+
tempTokenSprite.anchor = this.icon.anchor;
59+
tempTokenSprite.angle = this.icon.angle;
60+
tempTokenSprite.alpha = 1;
61+
tempTokenSprite.zIndex = this.data.elevation;
62+
}
63+
// Animate perception changes
64+
if (!config.animate || !anim.length) return;
65+
let updateFog = config.fog;
66+
if (config.source) {
67+
const dist = Math.hypot(anim[0].done, anim[1]?.done || 0);
68+
const n = Math.floor(dist / canvas.dimensions.size);
69+
if (n > 0 && anim[0].dist !== n) {
70+
updateFog = true;
71+
anim[0].dist = n;
72+
}
73+
}
74+
this._animatePerceptionFrame({
75+
source: config.source,
76+
sound: config.sound,
77+
fog: updateFog,
78+
});
79+
}

scripts/levels.js

+78-11
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ class Levels {
1515

1616
static get() {
1717
Levels._instance = new Levels();
18+
Levels._instance.floorContainer.sortableChildren = true;
1819
canvas.background.addChild(Levels._instance.floorContainer);
19-
//canvas.lighting.coloration.addChild(Levels._instance.occlusionContainer);
2020
return Levels._instance;
2121
}
2222

@@ -82,25 +82,55 @@ class Levels {
8282
}
8383
}
8484

85-
computeTokens(tokens, elevation, holes,cTokenElev,ctokenId) {
85+
computeTokens(tokens, elevation, holes, cTokenElev, ctokenId) {
8686
tokens.forEach((t) => {
87-
if(t.token.id != ctokenId){
87+
if (t.token.id != ctokenId) {
8888
if (!(t.range[1] >= elevation && t.range[0] <= elevation)) {
8989
let isInHole = this.isTokenInHole(t, holes);
90-
if (!isInHole || (t.token.data.elevation <= isInHole.range[1] && t.token.data.elevation >= isInHole.range[0] && !(cTokenElev <= isInHole.range[1] && cTokenElev >= isInHole.range[0]))) {
90+
if (!this.isInsideHoleRange(isInHole, t, cTokenElev)) {
91+
t.token.levelsHidden = true;
92+
t.token.icon.alpha = 0;
93+
if (!this.floorContainer.children.find((c) => c.name == t.token.id))
94+
this.getTokenIconSprite(t.token);
95+
} else {
9196
t.token.visible = false;
97+
this.removeTempToken(t.token);
9298
}
99+
} else {
100+
t.token.levelsHidden = false;
101+
t.token.icon.alpha = 1;
102+
this.removeTempToken(t.token);
93103
}
94104
}
95105
});
96106
}
97107

108+
isInsideHoleRange(isInHole, t, cTokenElev) {
109+
return (
110+
!isInHole ||
111+
(t.token.data.elevation <= isInHole.range[1] &&
112+
t.token.data.elevation >= isInHole.range[0] &&
113+
!(cTokenElev <= isInHole.range[1] && cTokenElev >= isInHole.range[0]))
114+
);
115+
}
116+
98117
isTokenInHole(t, holes) {
99-
for(let hole of holes){
100-
if ((t.range[1] <= hole.range[1] && t.range[0] >= hole.range[0]) && hole.poly.contains(t.token.center.x,t.token.center.y)) {
118+
let cs = canvas.scene.dimensions.size;
119+
let th = t.token.height;
120+
let tw = t.token.width;
121+
for (let hole of holes) {
122+
if (
123+
t.range[1] <= hole.range[1] &&
124+
t.range[0] >= hole.range[0] &&
125+
(hole.poly.contains(t.token.center.x, t.token.center.y) ||
126+
hole.poly.contains(t.token.x + tw, t.token.y) ||
127+
hole.poly.contains(t.token.x, t.token.y + th) ||
128+
hole.poly.contains(t.token.x + tw, t.token.y + th) ||
129+
hole.poly.contains(t.token.x, t.token.y))
130+
) {
101131
return hole;
102132
}
103-
};
133+
}
104134
return false;
105135
}
106136

@@ -164,13 +194,16 @@ class Levels {
164194
sprite.angle = tileImg.angle;
165195
sprite.alpha = 1;
166196
sprite.name = tile.id;
197+
sprite.zIndex = tileIndex.range[1];
167198
this.floorContainer.spriteIndex[tile.id] = sprite;
168199
this.floorContainer.addChild(sprite);
169200
}
170201

171202
occludeLights(tileIndex) {
172203
let tile = tileIndex.tile;
173-
let oldSprite = this.occlusionContainer.children.find((c) => c.name == tile.id);
204+
let oldSprite = this.occlusionContainer.children.find(
205+
(c) => c.name == tile.id
206+
);
174207
let tileImg = tile.children[0];
175208
if (!tileImg || oldSprite || !tileImg.texture.baseTexture) return;
176209
let sprite = new PIXI.Sprite.from(tileImg.texture);
@@ -184,10 +217,9 @@ class Levels {
184217
sprite.angle = tileImg.angle;
185218
sprite.alpha = 1;
186219
sprite.name = tile.id;
187-
sprite.tint = 0x000000
220+
sprite.tint = 0x000000;
188221
this.occlusionContainer.spriteIndex[tile.id] = sprite;
189222
this.occlusionContainer.addChild(sprite);
190-
191223
}
192224

193225
removeTempTile(tileIndex) {
@@ -224,7 +256,7 @@ class Levels {
224256
holeDrawings.forEach((drawing) => {
225257
let p = new PIXI.Polygon(this.adjustPolygonPoints(drawing));
226258
let range = drawing.data.text.split("|")[1].split(",");
227-
holes.push({ poly: p, range: [parseInt(range[0]),parseInt(range[1])] });
259+
holes.push({ poly: p, range: [parseInt(range[0]), parseInt(range[1])] });
228260
});
229261
return holes;
230262
}
@@ -237,6 +269,41 @@ class Levels {
237269
return globalPoints;
238270
}
239271

272+
getTokenIconSprite(token, x, y, rotate) {
273+
let oldSprite = this.floorContainer.children.find((c) => c.name == token.id);
274+
let icon = token.icon;
275+
if (
276+
token._controlled ||
277+
(oldSprite && !rotate) ||
278+
!icon ||
279+
!icon.texture.baseTexture
280+
)
281+
return;
282+
let sprite = oldSprite ? oldSprite : new PIXI.Sprite.from(icon.texture);
283+
sprite.isSprite = true;
284+
sprite.width = token.data.width * canvas.scene.dimensions.size;
285+
sprite.height = token.data.height * canvas.scene.dimensions.size;
286+
sprite.position.x = x || token.position.x;
287+
sprite.position.y = y || token.position.y;
288+
sprite.position.x += icon.x;
289+
sprite.position.y += icon.y;
290+
sprite.anchor = icon.anchor;
291+
sprite.angle = icon.angle;
292+
sprite.alpha = 1;
293+
sprite.name = token.id;
294+
sprite.zIndex = token.data.elevation;
295+
if (!oldSprite) {
296+
this.floorContainer.spriteIndex[token.id] = sprite;
297+
this.floorContainer.addChild(sprite);
298+
}
299+
}
300+
301+
removeTempToken(token) {
302+
let tile = token;
303+
let sprite = this.floorContainer.children.find((c) => c.name == tile.id);
304+
if (sprite) this.floorContainer.removeChild(sprite);
305+
}
306+
240307
/*****************************************************
241308
* 1: TILE IS ABOVE -1: TILE IS BELOW 0 : SAME LEVEL *
242309
*****************************************************/

scripts/main.js

+12-1
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,24 @@ Hooks.on("sightRefresh", () => {
2828
});
2929

3030
Hooks.on("updateToken", (token, updates) => {
31-
if ("elevation" in updates || "x" in updates || "y" in updates) canvas.sight.refresh();
31+
if(token._controlled) return
32+
if ("elevation" in updates || "x" in updates || "y" in updates || "rotation" in updates) {
33+
_levels.getTokenIconSprite(canvas.tokens.get(token.id),updates.x,updates.y,"rotation" in updates)
34+
canvas.sight.refresh();
35+
}
3236
});
3337

3438
Hooks.on("controlToken", (token, contorlled) => {
3539
if(!contorlled){
3640
canvas.foreground.placeables.forEach((t)=>{
3741
_levels.removeTempTile(t);
3842
})
43+
canvas.tokens.placeables.forEach((t)=>{
44+
if(t.levelsHidden==true){
45+
t.levelsHidden==false
46+
t.icon.alpha=1
47+
_levels.removeTempToken(t)
48+
}
49+
})
3950
}
4051
});

0 commit comments

Comments
 (0)