Scripts/resources/[hp]/hp_hud/vue.js
2024-12-29 20:48:41 +01:00

745 lines
25 KiB
JavaScript

function formatAmount(amount, addSuffix) {
let suffix = '';
if (addSuffix) {
if (amount >= 1000000) {
amount /= 1000000;
suffix = 'M';
} else if (amount >= 1000) {
amount /= 1000;
suffix = 'K';
}
}
const formatter = new Intl.NumberFormat('da-DK', {
style: 'currency',
currency: 'DKK',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
});
let num = formatter.format(amount);
return num
}
const app = new Vue({
el: '#app',
data() {
return {
backgroundImageStyle: {
backgroundImage: "url('assets/img/background.svg')"
},
defaultColors: {
health: "#FF3737",
armor: "#379FFF",
stress: "#FF37D3",
hunger: "#FFD337",
water: "#00FFF0",
oxygen: "#37FF63",
cash: "#83FF37",
bank: "#83FF37",
black: "#83FF37",
job: "#379FFF",
weapon: "#FF7337",
clock: "#379FFF",
id: "#379FFF",
bars: "#9643FF",
},
colors: ['#3757FF', '#3757FF', '#3757FF', '#3757FF'],
vehiclerpm: 0,
roundedRpm: 0,
allHud: false,
bars: Array(32).fill(0),
hudMenu: false,
hudType: localStorage.getItem('hudType') || 'squared', // squared or rounded
speedStyle: "squared",
forceHide: false,
carHud: false,
speedHz: 'KM/H',
notifications: [],
question: [],
speedometer: {
speedh: 0, fuel: 0, noss: 0, rpm: 0, max: 300, maxrpm: 7000, gear: 0,
seatbelt: "gray", door: "gray", speed: "gray", engine: "gray", signal: "gray", cruise: "gray", light: "gray"
},
player: {
job: {
variable: false,
name: "Policeman",
grade: "officer"
},
weapon: {
variable: false,
img: "appistol",
name: "Shotgun MK2",
ammo: "133/285"
},
clock: {
variable: false,
name: "13:42 30.03"
},
id: {
variable: false,
name: "981 1000"
},
microphone: {
variable: false,
color: "#FFFFFF"
},
cash: {
variable: false,
amount: formatAmount(69000, false),
},
bank: {
variable: false,
amount: formatAmount(6900, true),
},
black: {
variable: false,
amount: formatAmount(6, false),
}
},
hud: {
health: {
percentage: 50,
color: localStorage.getItem('healthColor') || "#FF3737",
picker: false,
drag: false,
position: {
top: localStorage.getItem("healthPositionTop") || "11rem",
left: localStorage.getItem("healthPositionLeft") || "0.75rem",
},
},
armor: {
percentage: 40,
color: localStorage.getItem('armorColor') || "#379FFF",
picker: false,
drag: false,
position: {
top: localStorage.getItem("armorPositionTop") || "11rem",
left: localStorage.getItem("armorPositionLeft") || "0.75rem",
},
},
stress: {
percentage: 0,
color: localStorage.getItem('stressColor') || "#FF37D3",
picker: false,
drag: false,
position: {
top: localStorage.getItem("stressPositionTop") || "11rem",
left: localStorage.getItem("stressPositionLeft") || "0.75rem",
},
},
hunger: {
percentage: 40,
color: localStorage.getItem('hungerColor') || "#FFD337",
picker: false,
drag: false,
position: {
top: localStorage.getItem("hungerPositionTop") || "11rem",
left: localStorage.getItem("hungerPositionLeft") || "0.75rem",
},
},
water: {
percentage: 100,
color: localStorage.getItem('waterColor') || "#00FFF0",
picker: false,
drag: false,
position: {
top: localStorage.getItem("waterPositionTop") || "11rem",
left: localStorage.getItem("waterPositionLeft") || "0.75rem",
},
},
oxygen: {
percentage: 100,
color: localStorage.getItem('oxygenColor') || "#37FF63",
picker: false,
drag: false,
position: {
top: localStorage.getItem("oxygenPositionTop") || "11rem",
left: localStorage.getItem("oxygenPositionLeft") || "0.75rem",
},
},
cash: {
color: localStorage.getItem('cashColor') || "#83FF37",
picker: false,
drag: false,
position: {
top: localStorage.getItem("cashPositionTop") || "8.25rem",
left: localStorage.getItem("cashPositionLeft") || "108.2969rem",
},
},
bank: {
color: localStorage.getItem('bankColor') || "#83FF37",
picker: false,
drag: false,
position: {
top: localStorage.getItem("bankPositionTop") || "11.5625rem",
left: localStorage.getItem("bankPositionLeft") || "109.8906rem",
},
},
black: {
color: localStorage.getItem('blackColor') || "#83FF37",
picker: false,
drag: false,
position: {
top: localStorage.getItem("blackPositionTop") || "14.875rem",
left: localStorage.getItem("blackPositionLeft") || "111.4844rem",
},
},
job: {
color: localStorage.getItem('jobColor') || "#379FFF",
picker: false,
drag: false,
position: {
top: localStorage.getItem("jobPositionTop") || "18.25rem",
left: localStorage.getItem("jobPositionLeft") || "104.6rem",
},
},
weapon: {
color: localStorage.getItem('weaponColor') || "#FF7337",
picker: false,
drag: false,
},
clock: {
color: localStorage.getItem('clockColor') || "#379FFF",
picker: false,
drag: false,
position: {
top: localStorage.getItem("clockPositionTop") || "8.25rem",
left: localStorage.getItem("clockPositionLeft") || "108.2969rem",
},
},
id: {
color: localStorage.getItem('idColor') || "#379FFF",
picker: false,
drag: false,
position: {
top: localStorage.getItem("idPositionTop") || "2.625rem",
left: localStorage.getItem("idPositionLeft") || "97.6875rem",
},
},
microphone: {
color: localStorage.getItem('micColor') || "#379FFF",
picker: false,
drag: false,
position: {
top: localStorage.getItem("microphonePositionTop") || "2.625rem",
left: localStorage.getItem("microphonePositionLeft") || "94.1rem",
},
},
bars: {
color: localStorage.getItem('barColor') || "#9643FF",
picker: false,
drag: false,
},
map: {
color: localStorage.getItem('mapColor') || "#9643FF",
picker: false,
drag: false,
type: localStorage.getItem('hud.map.type') || "rounded"
},
weapon: {
color: localStorage.getItem('weaponColor') || "#379FFF",
picker: false,
drag: false,
position: {
top: localStorage.getItem("weaponPositionTop") || "18.15rem",
left: localStorage.getItem("weaponPositionLeft") || "104.5rem",
},
},
}
};
},
computed: {
borderDashArray() {
const maxPathLength = 500;
const pathLength = (this.speedometer.speedh * maxPathLength) / 300;
return `${pathLength} ${500 - pathLength}`;
},
speedBarTransform() {
const clampedSpeedValue = Math.min(this.speedometer.speedh, 300);
const { innerWidth: width, innerHeight: height } = window;
const isLargeScreen = width === 2560 && height === 1440;
const isMiniScreen = width === 1366 && height === 768;
const angleOffset = (clampedSpeedValue * 310) / 400;
let rotationAngle;
if (isLargeScreen) {
const largeScreenSpeedAngleMap = [
[301, 300], [250, -85], [230, -70], [210, -75], [190, -80], [175, -85],
[165, -90], [150, -95], [145, -100], [135, -105], [120, -110], [115, -113],
[110, -115], [100, -120], [90, -125], [70, -130], [50, -135], [10, -142],
[0, -140]
];
for (const [speed, angle] of largeScreenSpeedAngleMap) {
if (clampedSpeedValue >= speed) {
rotationAngle = angle + angleOffset;
break;
}
}
} else if (isMiniScreen) {
const largeScreenSpeedAngleMapMini = [
[301, 300], [250, -85], [230, -70], [210, -75], [190, -80], [175, -85],
[165, -90], [150, -95], [145, -100], [135, -105], [120, -110], [115, -113],
[110, -115], [100, -110], [90, -110], [70, -120], [50, -125], [10, -130],
[0, -130]
];
for (const [speed, angle] of largeScreenSpeedAngleMapMini) {
if (clampedSpeedValue >= speed) {
// console.log(angle, angleOffset)
rotationAngle = angle + angleOffset;
break;
}
}
}
else {
const regularScreenSpeedAngleMap = [
[250, -85], [235, -80], [185, -85], [165, -90], [140, -100],
[130, -105], [120, -110], [100, -115], [90, -120], [70, -125],
[50, -130], [10, -135], [0, -140]
];
for (const [speed, angle] of regularScreenSpeedAngleMap) {
if (clampedSpeedValue >= speed) {
rotationAngle = angle + angleOffset;
break;
}
}
}
const centerX = 4;
const centerY = 24;
this.$nextTick(() => {
const speedBar = this.$refs.speedBar;
const speedValue = this.$refs.speedValue;
if (this.speedometer.speedh > 0) {
speedBar.classList.add('animation-bar');
} else {
speedBar.classList.remove('animation-bar');
speedValue.classList.remove('animation-text');
}
if (this.speedometer.speedh > 50 || this.speedometer.speedh > 100) {
speedValue.classList.add('animation-text');
} else {
speedValue.classList.remove('animation-text');
}
});
return `translate(${centerX}, ${centerY}) rotate(${rotationAngle}) translate(-${centerX}, -${centerY})`;
},
},
watch: {
"speedometer.speedh": function (newVal, oldVal) {
const rpmChange = newVal - oldVal;
if (newVal > 220) {
setTimeout(() => {
this.speedometer.rpm = Math.min(this.speedometer.rpm + rpmChange, 85);
}, 50);
} else {
if (rpmChange < 0) {
this.speedometer.rpm = Math.max(this.speedometer.rpm + rpmChange, 0);
} else {
this.speedometer.rpm = this.speedometer.rpm;
}
}
},
hudType(value) {
localStorage.setItem('hudType', value);
}
},
created() {
Object.keys(this.hud).forEach(key => {
this.$watch(`hud.${key}.color`, function (newColor) {
localStorage.setItem(`${key}Color`, newColor);
});
});
const hudItems = ['health', 'armor', 'stress', 'hunger', 'water', 'oxygen', 'cash', 'bank', 'black', 'job', 'weapon', 'clock', 'id', 'bars', 'map'];
hudItems.forEach(item => {
const colorKey = `${item}Color`;
this.hud[item].color = localStorage.getItem(colorKey) || this.hud[item].color;
});
this.$watch('hud.map.type', function (newType) {
localStorage.setItem('hud.map.type', newType);
});
const savedType = localStorage.getItem('hud.map.type') || 'rounded';
this.hud.map.type = savedType;
$.post(`https://${GetParentResourceName()}/GetMap`, JSON.stringify({ map: this.hud.map.type }), function (data) { })
},
methods: {
typeMap(type) {
this.hud.map.type = type;
localStorage.setItem('hud.map.type', type);
const targetElement = this.$refs.targetElement;
anime({
targets: targetElement,
translateX: ['-100%', 0],
duration: 1000,
easing: 'easeOutBounce'
});
$.post(`https://${GetParentResourceName()}/GetMap`, JSON.stringify({ map: this.hud.map.type }), function (data) { })
},
ResetColor() {
let data = {
type: "success",
header: "Farver",
description: "Alle farver nulstillet."
}
this.addNotification(data)
const hudItems = ['health', 'armor', 'stress', 'hunger', 'water', 'oxygen', 'cash', 'bank', 'black', 'job', 'weapon', 'clock', 'id', 'bars', 'bank'];
hudItems.forEach(item => {
this.hud[item].color = this.defaultColors[item];
});
},
addNotification(notification) {
this.notifications.push(notification);
setTimeout(() => {
this.removeNotification(notification);
}, 10000);
},
removeNotification(notification) {
this.notifications = this.notifications.filter(n => n !== notification);
},
setDefaultPositions() {
const positions = [
{ top: "11rem", left: "0.75rem" },
{ top: "15.9rem", left: "0.75rem" },
{ top: "21rem", left: "0.75rem" },
{ top: "26.1rem", left: "0.75rem" },
{ top: "31.25rem", left: "0.75rem" },
{ top: "36.5rem", left: "0.75rem" },
{ top: "11.5625rem", left: "109.8906rem" },
{ top: "2.625rem", left: "94.1rem" },
{ top: "27rem", left: "104.4375rem" }
];
const keys = ["health", "armor", "stress", "hunger", "water", "oxygen", "id", "clock", "weapon"];
for (let i = 0; i < keys.length; i++) {
const savedTop = localStorage.getItem(keys[i] + "PositionTop");
const savedLeft = localStorage.getItem(keys[i] + "PositionLeft");
if (savedTop && savedLeft) {
this.hud[keys[i]].position.top = savedTop;
this.hud[keys[i]].position.left = savedLeft;
} else {
this.hud[keys[i]].position.top = positions[i].top;
this.hud[keys[i]].position.left = positions[i].left;
localStorage.setItem(keys[i] + "PositionTop", positions[i].top);
localStorage.setItem(keys[i] + "PositionLeft", positions[i].left);
}
}
},
typeSpeedometer(type) {
this.speedStyle = type;
localStorage.setItem('speedStyle', type);
},
loadSettings() {
const savedSpeedStyle = localStorage.getItem("speedStyle");
if (savedSpeedStyle) {
this.speedStyle = savedSpeedStyle;
}
},
typeHud(id) {
this.hudType = id;
localStorage.setItem('hudType', id);
$.post(`https://${GetParentResourceName()}/UpStats`, JSON.stringify(), function (data) {
app.hud.hunger.percentage = data.hunger;
app.hud.water.percentage = data.thirst;
})
},
clickData(type) {
if (type == "reset") {
let data = {
type: "success",
header: "Reset",
description: "Din hud blev nulstillet!"
}
this.addNotification(data)
const positions = [
{ top: "25rem", left: "0.75rem" }, // health
{ top: "31rem", left: "0.75rem" }, // armor
{ top: "21rem", left: "-100rem" }, // stress
{ top: "36rem", left: "0.75rem" }, // hunger
{ top: "41rem", left: "0.75rem" }, // water
{ top: "46rem", left: "0.75rem" }, // Stamina/oxygen
{ top: "2.625rem", left: "97.6875rem" }, // id
{ top: "2.625rem", left: "101.3125rem" }, // clock
{ top: "11.55rem", left: "108.2969rem" }, // cash
{ top: "14.85rem", left: "108.2969rem" }, // bank
{ top: "2.625rem", left: "94.1rem" }, // microphone
{ top: "14.875rem", left: "1111.4844rem" }, // black
{ top: "8.25rem", left: "104.7rem" }, // job
{ top: "18.15rem", left: "104.5rem" },
];
const keys = ["health", "armor", "stress", "hunger", "water", "oxygen", "id", "clock", "cash", "bank", "microphone", "black", "job", "weapon"];
for (let i = 0; i < keys.length; i++) {
this.hud[keys[i]].position.top = positions[i].top;
this.hud[keys[i]].position.left = positions[i].left;
localStorage.setItem(keys[i] + "PositionTop", positions[i].top);
localStorage.setItem(keys[i] + "PositionLeft", positions[i].left);
}
}
},
getFillColor: function (index, id) {
let filledBars = Math.ceil(this.hud[id].percentage / 25);
return index < filledBars ? this.hud[id].color : 'black';
},
getFillOpacity: function (index) {
return index === 0 ? 1 : 1;
},
SetForceHide(val) {
this.forceHide = val
},
getEdit(type) {
this.hud[type].drag = !this.hud[type].drag;
localStorage.setItem(type + "Drag", this.hud[type].drag);
},
getPercentage(min, current) {
const range = 200 - min;
const adjustedValue = current - min;
const percentage = (adjustedValue / range) * 100;
return percentage;
},
updateColor(index, value) {
const hudItem = this.hud[index];
if (hudItem) {
hudItem.color = value;
localStorage.setItem(`${index}Color`, value);
} else {
console.warn(`Invalid index: ${index}`);
}
},
speedSelect(data) {
this.select = data;
},
mouseDownHandler: function (style, type, data, e) {
const drag = e.target.closest('.' + type);
const rect = drag.getBoundingClientRect();
const pos = { top: rect.top, left: rect.left, x: e.clientX, y: e.clientY };
if (type !== 'border') {
this.hud[data].drag = true;
}
const mouseMoveHandler = function (e) {
const dx = e.clientX - pos.x;
const dy = e.clientY - pos.y;
pos.top += dy;
pos.left += dx;
if (type !== 'border') {
const appRect = document.getElementById("app").getBoundingClientRect();
pos.top = Math.max(appRect.top, Math.min(pos.top, appRect.bottom - drag.offsetHeight));
pos.left = Math.max(appRect.left, Math.min(pos.left, appRect.right - drag.offsetWidth));
const elements = document.querySelectorAll('.' + type + '.drag');
elements.forEach(element => {
if (element !== drag) {
const rect = element.getBoundingClientRect();
const distance = Math.sqrt(Math.pow(pos.left - rect.left, 2) + Math.pow(pos.top - rect.top, 2));
if (distance < 50) {
this.hud[element.dataset.id].drag = true;
}
}
});
}
drag.style.top = `${pos.top}px`;
drag.style.left = `${pos.left}px`;
pos.x = e.clientX;
pos.y = e.clientY;
this.updatePlayerPosition(style, data, pos.top, pos.left);
}.bind(this);
const mouseUpHandler = function () {
document.removeEventListener("mousemove", mouseMoveHandler);
document.removeEventListener("mouseup", mouseUpHandler);
if (type !== 'border') {
const elements = document.querySelectorAll('.' + type + '.drag');
elements.forEach(element => {
if (element !== drag) {
this.hud[element.dataset.id].drag = false;
}
});
this.hud[data].drag = false;
} else {
this.hud[data].drag = false;
}
}.bind(this);
document.addEventListener("mousemove", mouseMoveHandler);
document.addEventListener("mouseup", mouseUpHandler);
},
updatePlayerPosition: function (style, data, top, left) {
if (style === "hud") {
const dataKey = typeof data === "string" ? data : data.id;
if (this.hud && this.hud[dataKey]) {
this.hud[dataKey].position = { top: top + "px", left: left + "px" };
localStorage.setItem(dataKey + "PositionTop", top + "px");
localStorage.setItem(dataKey + "PositionLeft", left + "px");
} else {
console.error(`Could not find object with id "${dataKey}" in hud`);
}
} else {
const dataKey = typeof data === "string" ? data : data.id;
if (this.position && this.position[dataKey]) {
this.position[dataKey] = { top: top + "px", left: left + "px" };
localStorage.setItem(dataKey + "PositionTop", top + "px");
localStorage.setItem(dataKey + "PositionLeft", left + "px");
} else {
console.error(`Could not find object with id "${dataKey}" in position`);
}
}
},
},
mounted() {
let tilNextRefresh = 1000;
setInterval(() => {
const now = new Date();
const secondsUntilNextMinute = 60 - now.getSeconds();
const msUntilNextMinute = secondsUntilNextMinute * 1000;
tilNextRefresh = msUntilNextMinute;
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
const day = now.getDate().toString().padStart(2, '0');
const monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'];
const month = now.getMonth();
const monthAbbreviation = monthNames[month];
const timeString = `${hours}:${minutes}`;
const dateString = `${day}. ${monthAbbreviation}`;
this.player.clock.name = `${timeString} ${dateString}`;
}, 1000);
this.loadSettings();
this.setDefaultPositions();
const keys = ["health", "armor", "stress", "hunger", "water", "oxygen", "id", "clock", "cash", "bank", "microphone", "black", "job", "weapon"];
let isLocalStorageEmpty = false;
for (let i = 0; i < keys.length; i++) {
if (!localStorage.getItem(keys[i] + "PositionTop") || !localStorage.getItem(keys[i] + "PositionLeft")) {
isLocalStorageEmpty = true;
break;
}
}
if (isLocalStorageEmpty) {
this.clickData('reset');
}
}
})
window.addEventListener('message', event => {
const { action, type, ...data } = event.data;
const appActions = {
GET_JOB: () => {
const { job, grade } = data;
app.player.job.name = job.charAt(0).toUpperCase() + job.slice(1);
app.player.job.grade = grade;
},
MENU: () => app.hudMenu = true,
SETCARHUD: () => app.carHud = data.variable,
CARHUD: () => {
const { speed, fuel, engine, cruise, state, seatbelt, gear, rpm, door, blinkers, type } = data;
Object.assign(app.speedometer, {
speedh: speed,
fuel: (Math.floor(fuel) * 1.75),
cruise: cruise ? "lightgreen" : "gray",
engine: engine ? "orange" : "gray",
light: state ? "white" : "gray",
seatbelt: seatbelt ? "white" : "gray",
door: door ? "white" : "gray",
signal: blinkers ? "orange" : "gray",
gear
});
if (rpm == 16) {
app.roundedRpm = (3 / 78 * 100)
app.vehiclerpm = 3;
} else {
app.roundedRpm = (rpm / 78 * 100)
app.vehiclerpm = rpm;
}
//WHAT THE FUCK IS A MILE? KINGDOM METRIC/H RAAAAAAAAAAAAAAAH
app.speedHz = 'KM/H'
},
HIDEHUD: () => app.SetForceHide(data.hudStatus),
NOTCAR: () => app.carHud = false,
HEALTH: () => app.hud.health.percentage = data.health,
ARMOR: () => app.hud.armor.percentage = data.armor,
STATUS: () => {
const { hunger, thirst } = data;
app.hud.hunger.percentage = hunger;
app.hud.water.percentage = thirst;
app.allHud = true;
},
UPDATE_NOSS: () => {
if (typeof data.noss === 'number' && !isNaN(data.noss)) {
if (data.noss === 0) {
app.speedometer.noss = 0;
} else {
app.speedometer.noss = data.noss * 1.75;
}
}
},
EXIT: () => app.allHud = data.args,
ECONOMY: () => {
const { cash, bank, black } = data;
app.player.cash.amount = formatAmount(cash, false);
app.player.bank.amount = formatAmount(bank, false);
app.player.black.amount = formatAmount(black, true);
},
GET_STAMINA: () => app.hud.oxygen.percentage = data.stamina,
STRESS: () => app.hud.stress.percentage = data.stress,
MICROPHONE: () => app.player.microphone.color = data.variable,
PLAYERS: () => app.player.id.name = data.players,
GET_WEAPON: () => {
const { stats, name, img } = data;
const noSpaceName = name.toLowerCase().split(" ").join("");
app.player.weapon.variable = stats;
app.player.weapon.name = name;
app.player.weapon.img = img;
},
GET_AMMO: () => app.player.weapon.ammo = data.ammo,
GET_NOTIFICATION: () => {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const time = `${hours}:${minutes}:${seconds}`;
const { ntype, nheader, nmsg } = data;
app.addNotification({ type: ntype, header: nheader, description: nmsg, time: time });
},
GET_QUESTION: () => {
if (data.qstats) {
const { qheader, qmsg } = data;
let ques = { header: qheader, description: qmsg };
app.question.push(ques);
} else {
app.question = [];
}
}
};
(appActions[action || type] || (() => { }))();
});
document.onkeyup = function (data) {
if (data.which == 27) {
app.hudMenu = false;
$.post(`https://${GetParentResourceName()}/exit`, JSON.stringify({}));
}
};