Upload files to "html"
This commit is contained in:
parent
27445f1778
commit
e570e5cf36
112
html/apperance.css
Normal file
112
html/apperance.css
Normal 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
384
html/apperance.js
Normal 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("&", "&")
|
||||
.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;
|
||||
}
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user