Upload files to "html"

This commit is contained in:
tanthius 2026-02-12 11:58:03 +00:00
parent 27445f1778
commit e570e5cf36
2 changed files with 496 additions and 0 deletions

112
html/apperance.css Normal file
View File

@ -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;
}

384
html/apperance.js Normal file
View File

@ -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 = `
<span class="lb-name" style="color: rgb(${R}, ${G}, ${B});">
${escapeHtml(name)}
</span>
<span class="lb-val">${Number.isFinite(val) ? val : 0}</span>
`;
lbRows.appendChild(div);
});
}
function escapeHtml(s) {
return String(s)
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;")
.replaceAll("'", "&#039;");
}
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 didnt 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;
}
});