ghkghc
This commit is contained in:
parent
b61220425a
commit
e1e0128e0e
42
app.js
42
app.js
@ -335,15 +335,35 @@ app.post("/api/building/:id/upgrade", requireLogin, async (req, res) => {
|
||||
|
||||
app.get("/api/hud", requireLogin, async (req, res) => {
|
||||
const userId = req.session.user.id;
|
||||
const ENERGY_MAX = 40;
|
||||
try {
|
||||
const [[account]] = await db.query(
|
||||
"SELECT ingame_name FROM accounts WHERE id = ?",
|
||||
[userId],
|
||||
);
|
||||
const [[currency]] = await db.query(
|
||||
"SELECT silver, gold, gems, wood, stone FROM account_currency WHERE account_id = ?",
|
||||
"SELECT silver, gold, gems, wood, stone, energy, energy_reset FROM account_currency WHERE account_id = ?",
|
||||
[userId],
|
||||
);
|
||||
|
||||
/* ── Täglicher Energie-Reset ────────────────────────────
|
||||
Wenn energy_reset < heute (oder NULL) → Energie auf Max
|
||||
────────────────────────────────────────────────────────── */
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
const lastReset = currency?.energy_reset
|
||||
? new Date(currency.energy_reset).toISOString().slice(0, 10)
|
||||
: null;
|
||||
|
||||
let currentEnergy = currency?.energy ?? ENERGY_MAX;
|
||||
|
||||
if (lastReset !== today) {
|
||||
currentEnergy = ENERGY_MAX;
|
||||
await db.query(
|
||||
"UPDATE account_currency SET energy = ?, energy_reset = ? WHERE account_id = ?",
|
||||
[ENERGY_MAX, today, userId],
|
||||
);
|
||||
}
|
||||
|
||||
res.json({
|
||||
name: account?.ingame_name || "Held",
|
||||
silver: currency?.silver || 0,
|
||||
@ -351,6 +371,8 @@ app.get("/api/hud", requireLogin, async (req, res) => {
|
||||
gems: currency?.gems || 0,
|
||||
wood: currency?.wood || 0,
|
||||
stone: currency?.stone || 0,
|
||||
energy: currentEnergy,
|
||||
energy_max: ENERGY_MAX,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@ -412,6 +434,24 @@ app.use("/api", bazaarRoutes);
|
||||
app.use("/himmelstor", himmelstorRoutes);
|
||||
app.use("/api/himmelstor/daily", himmelstorDailyRoutes);
|
||||
|
||||
/* ========================
|
||||
Energie abfragen
|
||||
======================== */
|
||||
|
||||
app.get("/api/energy", requireLogin, async (req, res) => {
|
||||
const userId = req.session.user.id;
|
||||
const ENERGY_MAX = 40;
|
||||
try {
|
||||
const [[row]] = await db.query(
|
||||
"SELECT energy FROM account_currency WHERE account_id = ?",
|
||||
[userId],
|
||||
);
|
||||
res.json({ energy: row?.energy ?? ENERGY_MAX, energy_max: ENERGY_MAX });
|
||||
} catch (err) {
|
||||
res.status(500).json({ error: "DB Fehler" });
|
||||
}
|
||||
});
|
||||
|
||||
/* ========================
|
||||
404 Handler
|
||||
======================== */
|
||||
|
||||
@ -387,11 +387,72 @@ function initArenaModes() {
|
||||
|
||||
|
||||
/* ── 1v1 ───────────────────────────────────────────────────*/
|
||||
/* ── Energie prüfen ────────────────────────────────────────
|
||||
Gibt true zurück wenn Energie vorhanden, sonst false + Hinweis
|
||||
────────────────────────────────────────────────────────────── */
|
||||
async function checkEnergy() {
|
||||
try {
|
||||
const res = await fetch("/api/energy");
|
||||
if (!res.ok) return true; // bei Fehler nicht blockieren
|
||||
const { energy } = await res.json();
|
||||
if (energy <= 0) {
|
||||
showEnergyError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return true; // bei Netzwerkfehler nicht blockieren
|
||||
}
|
||||
}
|
||||
|
||||
function showEnergyError() {
|
||||
/* Bestehende Fehlermeldung entfernen */
|
||||
document.getElementById("arena-energy-notice")?.remove();
|
||||
|
||||
const box = document.createElement("div");
|
||||
box.id = "arena-energy-notice";
|
||||
box.style.cssText = `
|
||||
position:fixed; top:50%; left:50%; transform:translate(-50%,-50%);
|
||||
z-index:20000;
|
||||
background:linear-gradient(135deg,#1a0f04,#2a1808);
|
||||
border:2px solid rgba(231,76,60,.6);
|
||||
border-radius:14px; padding:28px 36px;
|
||||
text-align:center; max-width:340px;
|
||||
box-shadow:0 20px 60px rgba(0,0,0,.85);
|
||||
font-family:'Cinzel',serif;
|
||||
animation:arenaFadeIn .25s ease;`;
|
||||
box.innerHTML = `
|
||||
<div style="font-size:44px;margin-bottom:12px;">⚡</div>
|
||||
<div style="font-size:17px;color:#e74c3c;letter-spacing:2px;margin-bottom:10px;">KEINE ENERGIE</div>
|
||||
<p style="font-size:12px;color:#a08060;line-height:1.7;margin-bottom:20px;">
|
||||
Du hast heute keine Energie mehr für Arena-Kämpfe.<br>
|
||||
<strong style="color:#f0d060;">Deine Energie wird täglich um Mitternacht erneuert.</strong>
|
||||
</p>
|
||||
<button id="arena-energy-ok"
|
||||
style="background:linear-gradient(#4a1010,#2a0808);border:2px solid #8a3030;
|
||||
border-radius:8px;color:#e07070;font-family:'Cinzel',serif;
|
||||
font-size:12px;padding:9px 28px;cursor:pointer;transition:.15s;">
|
||||
✖ Schließen
|
||||
</button>`;
|
||||
|
||||
document.body.appendChild(box);
|
||||
document.getElementById("arena-energy-ok").addEventListener("click", () => box.remove());
|
||||
|
||||
/* Klick außerhalb schließt auch */
|
||||
setTimeout(() => {
|
||||
const close = (e) => { if (!box.contains(e.target)) { box.remove(); document.removeEventListener("click", close); } };
|
||||
document.addEventListener("click", close);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
async function handle1v1Click(card) {
|
||||
const socket = getSocket();
|
||||
if (!socket) { showArenaError("Keine Verbindung zum Server."); return; }
|
||||
if (card.classList.contains("searching")) return;
|
||||
|
||||
/* Energie prüfen bevor Queue beigetreten wird */
|
||||
if (!await checkEnergy()) return;
|
||||
|
||||
let me;
|
||||
try {
|
||||
const res = await fetch("/arena/me");
|
||||
@ -414,6 +475,11 @@ async function handle1v1Click(card) {
|
||||
socket.on("queue_status", data => {
|
||||
if (data.status === "waiting") showQueueStatus(me.level, levelRange, data.poolSize);
|
||||
else if (data.status === "left") { setCardSearching(card, false); hideQueueStatus(); }
|
||||
else if (data.status === "error") {
|
||||
setCardSearching(card, false);
|
||||
hideQueueStatus();
|
||||
showEnergyError();
|
||||
}
|
||||
});
|
||||
|
||||
socket.once("match_found", data => {
|
||||
@ -442,6 +508,9 @@ function cancelQueue(card) {
|
||||
async function openTeamLobby(mode) {
|
||||
const socket = getSocket();
|
||||
|
||||
/* Energie prüfen bevor Lobby geöffnet wird */
|
||||
if (!await checkEnergy()) return;
|
||||
|
||||
document.getElementById("arena-mode-screen").style.display = "none";
|
||||
document.getElementById(`arena-${mode}-screen`).style.display = "flex";
|
||||
|
||||
|
||||
@ -21,6 +21,21 @@ function applyHudData(data) {
|
||||
set("hud-gold", data.gold);
|
||||
set("hud-wood", data.wood);
|
||||
set("hud-stone", data.stone);
|
||||
|
||||
/* ── Energie anzeigen ────────────────────────────── */
|
||||
const energy = data.energy ?? 40;
|
||||
const energyMax = data.energy_max ?? 40;
|
||||
const energyEl = document.getElementById("hud-energy-value");
|
||||
if (energyEl) energyEl.textContent = energy + " / " + energyMax;
|
||||
|
||||
/* Farbe je nach Stand */
|
||||
if (energyEl) {
|
||||
energyEl.style.color =
|
||||
energy <= 0 ? "#e74c3c" // leer → rot
|
||||
: energy <= 10 ? "#e67e22" // niedrig → orange
|
||||
: energy < energyMax ? "#f0d9a6" // teilweise → normal
|
||||
: "#7de87d"; // voll → grün
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadHud() {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
============================================================ */
|
||||
|
||||
const { runCombatPhase } = require('./combat');
|
||||
const db = require('../database/database');
|
||||
const { htAiMatchIds } = require('./1vKI_daily.socket');
|
||||
const db = require('../database/database');
|
||||
const pointsRoute = require('../routes/points.route');
|
||||
@ -156,8 +157,49 @@ function leaveAllTeams_nvn(socketId, io, mode) {
|
||||
}
|
||||
}
|
||||
|
||||
/* ── Energie prüfen und abziehen ─────────────────────────────
|
||||
Gibt true zurück wenn genug Energie vorhanden, sonst false.
|
||||
Zieht ENERGY_COST ab und setzt energy_reset auf heute.
|
||||
────────────────────────────────────────────────────────────── */
|
||||
const ENERGY_COST = 2;
|
||||
const ENERGY_MAX = 40;
|
||||
|
||||
async function deductEnergy(accountId) {
|
||||
if (!accountId) return true; // kein Account → erlauben (Fallback)
|
||||
try {
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
|
||||
// Energie laden + ggf. tagesreset
|
||||
const [[row]] = await db.query(
|
||||
"SELECT energy, energy_reset FROM account_currency WHERE account_id = ?",
|
||||
[accountId]
|
||||
);
|
||||
if (!row) return true; // kein Eintrag → erlauben
|
||||
|
||||
const lastReset = row.energy_reset
|
||||
? new Date(row.energy_reset).toISOString().slice(0, 10)
|
||||
: null;
|
||||
const current = lastReset !== today ? ENERGY_MAX : (row.energy ?? ENERGY_MAX);
|
||||
|
||||
if (current < ENERGY_COST) return false; // nicht genug Energie
|
||||
|
||||
// Energie abziehen
|
||||
await db.query(
|
||||
`UPDATE account_currency
|
||||
SET energy = ?,
|
||||
energy_reset = ?
|
||||
WHERE account_id = ?`,
|
||||
[current - ENERGY_COST, today, accountId]
|
||||
);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error('[Energy] deductEnergy Fehler:', err);
|
||||
return true; // bei DB-Fehler nicht blockieren
|
||||
}
|
||||
}
|
||||
|
||||
/* ── 1v1 Matchmaking ── */
|
||||
function tryMatchmaking(io, newSocketId) {
|
||||
async function tryMatchmaking(io, newSocketId) {
|
||||
const challenger = waitingPool.get(newSocketId);
|
||||
if (!challenger) return;
|
||||
|
||||
@ -170,6 +212,38 @@ function tryMatchmaking(io, newSocketId) {
|
||||
waitingPool.delete(id);
|
||||
|
||||
const matchId = `match_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
||||
|
||||
// Energie beider Spieler abziehen (2 pro Match)
|
||||
const [energyOk1, energyOk2] = await Promise.all([
|
||||
deductEnergy(challenger.player.accountId),
|
||||
deductEnergy(entry.player.accountId),
|
||||
]);
|
||||
|
||||
if (!energyOk1) {
|
||||
challenger.socket.emit("queue_status", {
|
||||
status: "error",
|
||||
message: "Nicht genug Energie für einen Kampf. Warte bis morgen!",
|
||||
});
|
||||
waitingPool.set(newSocketId, challenger); // zurück in Pool
|
||||
waitingPool.set(id, entry);
|
||||
return;
|
||||
}
|
||||
if (!energyOk2) {
|
||||
// Energie von Spieler 1 zurückgeben
|
||||
if (challenger.player.accountId) {
|
||||
db.query(
|
||||
"UPDATE account_currency SET energy = LEAST(energy + ?, ?) WHERE account_id = ?",
|
||||
[ENERGY_COST, ENERGY_MAX, challenger.player.accountId]
|
||||
).catch(() => {});
|
||||
}
|
||||
entry.socket.emit("queue_status", {
|
||||
status: "error",
|
||||
message: "Nicht genug Energie für einen Kampf. Warte bis morgen!",
|
||||
});
|
||||
waitingPool.set(newSocketId, challenger);
|
||||
return;
|
||||
}
|
||||
|
||||
challenger.socket.emit("match_found", {
|
||||
matchId,
|
||||
opponent: entry.player,
|
||||
@ -567,6 +641,7 @@ function registerArenaHandlers(io, socket) {
|
||||
id: playerData.id,
|
||||
name: playerData.name,
|
||||
level: Number(playerData.level) || 1,
|
||||
accountId: playerData.id || null, // für Energie-Abzug
|
||||
};
|
||||
// levelRange vom Client übernehmen (5 oder 10), Standard = 5
|
||||
const levelRange = [5, 10].includes(Number(playerData.levelRange))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user