From e570e5cf3664c719a199b4fa89fbea00c98b8061 Mon Sep 17 00:00:00 2001 From: tanthius Date: Thu, 12 Feb 2026 11:58:03 +0000 Subject: [PATCH] Upload files to "html" --- html/apperance.css | 112 +++++++++++++ html/apperance.js | 384 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 496 insertions(+) create mode 100644 html/apperance.css create mode 100644 html/apperance.js diff --git a/html/apperance.css b/html/apperance.css new file mode 100644 index 0000000..d2fbc69 --- /dev/null +++ b/html/apperance.css @@ -0,0 +1,112 @@ +html, body { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + background: transparent; + overflow: hidden; + font-family: Arial, Helvetica, sans-serif; +} + +/* block game clicks by default */ +body { pointer-events: none; } +#wrap, #wrap * { pointer-events: auto; } + +.hidden { display: none !important; } + +#wrap { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; +} + +#wrap::before { + content: ""; + position: absolute; + inset: 0; + background: radial-gradient(circle at 50% 40%, rgba(0,0,0,0.15), rgba(0,0,0,0.60)); +} + +.panel { + position: relative; + z-index: 2; + width: 420px; + border-radius: 14px; + background: rgba(18,18,22,0.90); + box-shadow: 0 12px 40px rgba(0,0,0,0.45); + padding: 18px; + color: #fff; +} + +.title { + font-size: 22px; + font-weight: 700; + margin-bottom: 14px; +} + +.row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 0; + border-top: 1px solid rgba(255,255,255,0.08); +} + +.label { + font-size: 14px; + opacity: 0.9; +} + +.controls { + display: flex; + gap: 8px; + align-items: center; +} + +.value { + min-width: 48px; + text-align: center; + font-weight: 700; + opacity: 0.95; +} + +button { + border: 0; + padding: 8px 10px; + border-radius: 10px; + background: rgba(255,255,255,0.12); + color: #fff; + cursor: pointer; +} + +button:hover { + background: rgba(255,255,255,0.18); +} + +button.primary { + background: rgba(80,160,255,0.85); +} + +button.primary:hover { + background: rgba(80,160,255,1); +} + +button.active { + outline: 2px solid rgba(80,160,255,0.9); +} + +.footer { + display: flex; + justify-content: flex-end; + padding-top: 12px; + border-top: 1px solid rgba(255,255,255,0.08); + margin-top: 12px; +} + +.hint { + margin-top: 10px; + font-size: 12px; + opacity: 0.65; +} diff --git a/html/apperance.js b/html/apperance.js new file mode 100644 index 0000000..55d38ff --- /dev/null +++ b/html/apperance.js @@ -0,0 +1,384 @@ +console.log("[ATM UI] atm.js loaded"); +console.log("[NUI] loaded"); + +// ===================== +// DOM refs +// ===================== +const wrap = document.getElementById("wrap"); +const cashEl = document.getElementById("cash"); +const bankEl = document.getElementById("bank"); +const amountEl = document.getElementById("amount"); + +const btnDeposit = document.getElementById("btnDeposit"); +const btnWithdraw = document.getElementById("btnWithdraw"); +const btnClose = document.getElementById("btnClose"); + +// Gang Bank HUD +const gbHud = document.getElementById("gangbankHud"); +const gbAmount = document.getElementById("gbAmount"); +const gbLabel = document.getElementById("gbLabel"); + +// Capture HUD +const capHud = document.getElementById("captureHud"); +const capTitle = document.getElementById("capTitle"); +const capFill = document.getElementById("capFill"); +const capSub = document.getElementById("capSub"); +const capBar = document.getElementById("capBar"); + +// Leaderboard HUD +const lbHud = document.getElementById("leaderboardHud"); +const lbTitle = document.getElementById("lbTitle"); +const lbRows = document.getElementById("lbRows"); +const lbError = document.getElementById("lbError"); + +// ===================== +// State +// ===================== +let lastGangBank = null; + +// ===================== +// Helpers +// ===================== +function fmt(n) { + n = Number(n || 0); + if (!Number.isFinite(n)) n = 0; + return "$" + Math.floor(n).toLocaleString(); +} + +function post(name, data = {}) { + try { + fetch(`https://${GetParentResourceName()}/${name}`, { + method: "POST", + headers: { "Content-Type": "application/json; charset=UTF-8" }, + body: JSON.stringify(data) + }).catch(() => {}); + } catch (e) { + console.log("[ATM UI] post failed:", name, e); + } +} + +function getAmount() { + const v = Number(amountEl?.value || 0); + if (!Number.isFinite(v)) return 0; + return Math.floor(v); +} + +// ===================== +// ATM UI +// ===================== +function hideATM() { + wrap?.classList.add("hidden"); +} + +function showATM() { + wrap?.classList.remove("hidden"); + setTimeout(() => amountEl?.focus(), 0); +} + +// ======================== +// Turf Capture HUD (fixed) +// ======================== +function capShow() { + capHud?.classList.remove("cap-hidden"); +} + +function capHide() { + capHud?.classList.add("cap-hidden"); + if (capFill) capFill.style.width = "0%"; + if (capSub) capSub.textContent = "0%"; +} + +function capStart(titleText) { + capShow(); + if (capTitle) capTitle.textContent = titleText || "Capturing…"; + capSet(0); +} + +function capSet(t) { + t = Math.max(0, Math.min(1, Number(t || 0))); + const pct = Math.round(t * 100); + if (capFill) capFill.style.width = pct + "%"; + if (capSub) capSub.textContent = pct + "%"; +} + +/** + * Capture styling: + * - fillCss = contesting/capturing gang + * - bgCss = outgoing/current owner gang + */ +function capStyle(fillCss, bgCss) { + if (capFill && fillCss) capFill.style.background = fillCss; + if (capBar && bgCss) capBar.style.background = bgCss; +} + +function capPaused(isPaused) { + if (!capSub) return; + if (isPaused) capSub.textContent = "PAUSED"; +} + +// ======================== +// Leaderboard HUD +// ======================== +function lbShow() { + lbHud?.classList.remove("lb-hidden"); +} + +function lbHide() { + lbHud?.classList.add("lb-hidden"); +} + +function lbRender(payload) { + if (!payload) return; + + lbShow(); + + if (lbTitle) lbTitle.textContent = String(payload.title || "Most influence"); + + // Error display (optional) + if (payload.error) { + if (lbError) { + lbError.textContent = String(payload.error); + lbError.classList.remove("lb-hidden"); + } + } else { + lbError?.classList.add("lb-hidden"); + if (lbError) lbError.textContent = ""; + } + + if (!lbRows) return; + lbRows.innerHTML = ""; + + const rows = Array.isArray(payload.rows) ? payload.rows : []; + + rows.forEach((r) => { + const gangId = Number(r.gangId); + const name = String(r.name ?? "Unknown"); + const val = Number(r.value ?? 0); + + // 🚫 Skip Police + if (gangId === 3) return; + + // --- Color handling --- + const rgb = Array.isArray(r.rgb) ? r.rgb : [255, 255, 255]; + + let R = Number(rgb[0]); + let G = Number(rgb[1]); + let B = Number(rgb[2]); + + // Fallback safety + if (!Number.isFinite(R)) R = 255; + if (!Number.isFinite(G)) G = 255; + if (!Number.isFinite(B)) B = 255; + + // Brighten very dark colors only (Lost Gang) + if (R < 80 && G < 80 && B < 80) { + R = Math.min(255, R + 80); + G = Math.min(255, G + 80); + B = Math.min(255, B + 80); + } + + const div = document.createElement("div"); + div.className = "lb-row"; + + div.innerHTML = ` + + ${escapeHtml(name)} + + ${Number.isFinite(val) ? val : 0} + `; + + lbRows.appendChild(div); + }); +} + +function escapeHtml(s) { + return String(s) + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +} + +function setGangBankColor(rgb) { + if (!gbLabel) return; + + const arr = Array.isArray(rgb) ? rgb : [255, 255, 255]; + + let R = Number(arr[0]); + let G = Number(arr[1]); + let B = Number(arr[2]); + + if (!Number.isFinite(R)) R = 255; + if (!Number.isFinite(G)) G = 255; + if (!Number.isFinite(B)) B = 255; + + // Brighten very dark colors (e.g. Lost Gang) + if (R < 80 && G < 80 && B < 80) { + R = Math.min(255, R + 80); + G = Math.min(255, G + 80); + B = Math.min(255, B + 80); + } + + const css = `rgb(${R}, ${G}, ${B})`; + + // Apply to label (and optionally amount if you want later) + gbLabel.style.setProperty("--gang-color", css); + gbLabel.style.color = "var(--gang-color)"; // ensures it shows even if CSS missing +} + + + +// ===================== +// Boot +// ===================== +document.addEventListener("DOMContentLoaded", () => { + hideATM(); + capHide(); // ✅ was capStop() in your file (but didn’t exist) + lbHide(); // start hidden until first update + + console.log("[ATM UI] DOMContentLoaded -> posting atm:ready"); + post("atm:ready"); +}); + +// ===================== +// Button wiring +// ===================== +btnDeposit?.addEventListener("click", () => { + const amount = getAmount(); + if (amount > 0) post("atm:deposit", { amount }); +}); + +btnWithdraw?.addEventListener("click", () => { + const amount = getAmount(); + if (amount > 0) post("atm:withdraw", { amount }); +}); + +btnClose?.addEventListener("click", () => post("atm:close")); + +document.addEventListener("keydown", (e) => { + if (e.key === "Escape") post("atm:close"); +}); + +// ===================== +// NUI messages (single listener) +// ===================== +window.addEventListener("message", (event) => { + const data = event.data || {}; + const type = data.type; + if (!type) return; + + // Capture debug (optional) + if (type.startsWith("capture:")) { + // console.log("[NUI] capture msg", data); + } + + switch (type) { + // -------- ATM -------- + case "atm:open": + showATM(); + break; + + case "atm:close": + hideATM(); + break; + + case "atm:balances": + if (cashEl) cashEl.textContent = fmt(data.cash); + if (bankEl) bankEl.textContent = fmt(data.bank); + break; + +// ---- Gang Bank HUD ---- +case "gangbank:show": + gbHud?.classList.remove("gb-hidden"); + break; + +case "gangbank:hide": + gbHud?.classList.add("gb-hidden"); + break; + +case "gangbank:label": { + if (gbLabel) gbLabel.textContent = String(data.label || "Gang Bank"); + + // ✅ set color if provided + if (data.rgb) setGangBankColor(data.rgb); + + break; +} + +case "gangbank:update": { + if (!gbAmount) break; + + const amt = Number(data.balance ?? data.amount ?? 0); + gbAmount.textContent = fmt(amt); + + // ✅ also accept rgb here (in case update is the only message carrying it) + if (data.rgb) setGangBankColor(data.rgb); + + // pulse only if changed + if (lastGangBank !== null && amt !== lastGangBank) { + gbAmount.classList.remove("gb-pulse"); + void gbAmount.offsetWidth; // restart animation + gbAmount.classList.add("gb-pulse"); + } + lastGangBank = amt; + break; +} + + // ---- Turf Capture HUD ---- + case "capture:start": + capStart(data.turfName || data.title || "Capturing…"); + if (data.t !== undefined) capSet(data.t); + if (data.fill || data.bg) capStyle(data.fill, data.bg); + break; + + case "capture:set": + capShow(); + capSet(data.t); + break; + + case "capture:style": + capStyle(data.fill, data.bg); + break; + + case "capture:paused": + capPaused(!!data.paused); + break; + + case "capture:hint": + if (capSub && data.text) { + capSub.textContent = String(data.text); + setTimeout(() => { + // only clear if still showing the same hint-like text + if (capSub && capSub.textContent === String(data.text)) { + capSub.textContent = ""; + } + }, 1500); + } + break; + + case "capture:stop": + capHide(); + break; + + // ---- ✅ Leaderboard ---- + // We accept either name: + // - "leaderboard:update" (client might send this) + // - "turfwar:leaderboard:update" (recommended) + case "leaderboard:update": + case "turfwar:leaderboard:update": + lbRender(data.payload || data); + break; + + case "leaderboard:hide": + lbHide(); + break; + + case "leaderboard:show": + lbShow(); + break; + + default: + break; + } +});