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.
 
 
 

248 lines
7.5 KiB

class BossBar {
constructor() {
this.actor;
this.token;
this.bgPath = game.settings.get("bossbar", "backgroundPath");
this.fgPath = game.settings.get("bossbar", "foregroundPath");
this.tempBarColor = game.settings.get("bossbar", "tempBarColor");
this.textSize = game.settings.get("bossbar", "textSize");
this.position = game.settings.get("bossbar", "position");
}
static async create(token, render = true) {
let instance = new BossBar();
instance.actor = token.actor;
instance.token = token;
let bgFlag = token.document.getFlag("bossbar", "bgTex");
let fgFlag = token.document.getFlag("bossbar", "fgTex");
if (bgFlag) instance.bgPath = bgFlag;
if (fgFlag) instance.fgPath = fgFlag;
this.addBossBar(instance);
if (render) instance.draw(game.settings.get("bossbar", "barHeight"));
if (game.user.isGM) {
let oldBars = canvas.scene.getFlag("bossbar", "bossBarActive");
if (Array.isArray(oldBars)) {
oldBars.push(token.id);
} else {
oldBars = [token.id];
}
await canvas.scene.setFlag("bossbar", "bossBarActive", oldBars);
}
instance.hookId = Hooks.on("updateActor", (actor, updates) => {
if (
actor.id == instance.actor.id &&
Object.byString(updates.system, game.settings.get("bossbar", "currentHpPath")) !== undefined
) {
instance.update();
}
});
instance.CTHook = Hooks.on("renderCombatTracker", (app, html, data) => {
instance.CCTSetPosition();
});
instance.CCTHook = Hooks.on("combatDock:playIntroAnimation:finished", (app, html, data) => {
instance.CCTSetPosition(0);
});
instance.CCTCloseHook = Hooks.on("closeCombatDock", (app, html, data) => {
instance.CCTSetPosition();
});
return instance;
}
CCTSetPosition(delay = 0) {
setTimeout(() => {
try {
const combatDockElement = document.getElementById("combat-dock");
const spacer = document.querySelector(".bossBarSpacer");
if (!spacer) return;
spacer.style.setProperty("height", "0px");
const spacerDistanceFromTop = spacer.getBoundingClientRect().top;
if (!combatDockElement || combatDockElement.classList.contains("hidden")) {
spacer.style.setProperty("height", "0px");
return;
}
const height = combatDockElement.offsetHeight - spacerDistanceFromTop;
spacer.style.setProperty("height", `${height*0.8}px`);
} catch (error) {
}
}, delay);
}
draw(h) {
if ($("body").find(`div[id="bossBar-${this.id}"]`).length > 0) return; //#navigation
let bossBarContainer = `<div id="bossBarContainer"></div>`;
let bossBarHtml = `<div class="bossBarSpacer" style="transition: height 0.3s ease-in-out; flex-basis: 100%;height: 0px;" id="bossBarSpacer-${
this.id
}"></div><div id="bossBar-${this.id}" class="bossBar">
<a class="bossBarName" style="font-size: ${this.textSize}px;">${
this.name
}</a>
<div id ="bossBarBar-${this.id}" style="z-index: 1000;">
<div id="bossBarMax-${
this.id
}" class="bossBarMax" style="background-image:url('${
this.bgPath
}');height:${h}px;"></div>
<div id="bossBarTemp-${
this.id
}" class="bossBarTemp" style="background-color:${
this.tempBarColor
};height:${h}px;width:${this.hpPercent}%"></div>
<div id="bossBarCurrent-${
this.id
}" class="bossBarCurrent" style="background-image:url('${
this.fgPath
}');height:${h}px;width:${this.hpPercent}%"></div>
</div>
</div>
<div style="flex-basis: 100%;height: ${
this.textSize + 3
}px;" id ="bossBarSpacer-${this.id}"></div>
`;
switch (this.position) {
case 0:
$("#ui-top").append(bossBarHtml);
break;
case 1:
const cameraContainerW = $("#camera-views").width();
if ($("#bossBarContainer").length == 0) {
$("#ui-bottom").find("div").first().prepend(bossBarContainer);
}
$("#bossBarContainer").append(bossBarHtml);
$("#bossBarContainer").css({
position: "fixed",
bottom:
$("#hotbar").outerHeight(true) +
$(".bossBar").outerHeight(true) +
10,
width: `calc(100% - 330px - ${cameraContainerW}px)`,
left: 15 + cameraContainerW,
});
break;
default:
$("#ui-top").append(bossBarHtml);
}
this.update();
}
update() {
const isBar = document.getElementById(`bossBarCurrent-${this.id}`)
if(!isBar) return;
document
.getElementById(`bossBarCurrent-${this.id}`)
.style.setProperty("width", `${this.hpPercent}%`);
document
.getElementById(`bossBarTemp-${this.id}`)
.style.setProperty("width", `${this.hpPercent}%`);
this.CCTSetPosition();
}
clear() {
$("body").find(`div[id="bossBar-${this.id}"]`).remove();
}
async destroy() {
const flag = canvas.scene.getFlag("bossbar", "bossBarActive");
let newFlag = [];
for (let id of flag) {
if (id == this.token.id) continue;
newFlag.push(id);
}
await canvas.scene.setFlag("bossbar", "bossBarActive", newFlag);
this.unHook();
}
static clearAll() {
if (!canvas.scene._bossBars) return;
for (let bar of Object.entries(canvas.scene._bossBars)) {
$("body").find(`div[id="bossBar-${bar[1].id}"]`).remove();
$("body").find(`div[id="bossBarSpacer-${bar[1].id}"]`).remove();
}
}
static async remove() {
await canvas.scene.unsetFlag("bossbar", "bossBarActive");
canvas.scene._bossBars = {};
this.clearAll();
}
unHook() {
Hooks.off("updateActor", this.hookId);
Hooks.off("renderCombatTracker", this.CTHook)
Hooks.off("renderCombatDock", this.CCTHook)
Hooks.off("closeCombatDock", this.CCTCloseHook)
this.clear();
}
static addBossBar(bossBar) {
if (!canvas.scene._bossBars) {
canvas.scene._bossBars = {};
}
canvas.scene._bossBars[bossBar.id] = bossBar;
}
static cameraPan(tokenId, scale, duration) {
const token = canvas.tokens.get(tokenId);
canvas.animatePan({
x: token.center.x,
y: token.center.y,
scale: scale,
duration: duration,
});
}
static panCamera(token, scale = 1.8, duration = 1000) {
_BossBarSocket.executeForEveryone("cameraPan", token.id, scale, duration);
}
static async renderBossBar() {
if (canvas.scene) {
BossBar.clearAll();
const ids = canvas.scene.getFlag("bossbar", "bossBarActive");
if (!ids) return;
for (let id of ids) {
if (canvas.scene._bossBars && canvas.scene._bossBars[id]) {
canvas.scene._bossBars[id].draw(
game.settings.get("bossbar", "barHeight")
);
} else {
await BossBar.create(canvas.tokens.get(id));
}
}
}
}
get currentHp() {
return Object.byString(
this.actor.system,
game.settings.get("bossbar", "currentHpPath")
);
}
get maxHp() {
return Object.byString(
this.actor.system,
game.settings.get("bossbar", "maxHpPath")
);
}
get hpPercent() {
return Math.max(0, Math.round((100 * this.currentHp) / this.maxHp));
}
get hpPercentAsString() {
return String(this.hpPercent);
}
get name() {
return this.token.document.name;
}
get id() {
return this.token.id;
}
}