pop14
This commit is contained in:
parent
640f3c1549
commit
88705b5a06
2
app.js
2
app.js
@ -19,6 +19,7 @@ const buildingRoutes = require("./routes/buildings");
|
||||
const inventory = require("./routes/inventory");
|
||||
const avatar = require("./routes/avatar");
|
||||
const equip = require("./routes/equip");
|
||||
const equipment = require("./routes/equipment");
|
||||
|
||||
const app = express();
|
||||
app.set("trust proxy", 1);
|
||||
@ -191,6 +192,7 @@ app.use("/", buildingRoutes);
|
||||
app.use("/api/inventory", inventory);
|
||||
app.use("/api/avatar", avatar);
|
||||
app.use("/api/equip", equip);
|
||||
app.use("/api/equipment", equipment);
|
||||
|
||||
/* ========================
|
||||
404 Handler
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
/* =========================
|
||||
Base
|
||||
========================= */
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
@ -29,18 +33,16 @@ body {
|
||||
|
||||
.building-popup {
|
||||
position: fixed;
|
||||
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
width: 460px;
|
||||
width: 900px;
|
||||
max-width: 90vw;
|
||||
|
||||
background: url("/images/parchment.png") center / cover no-repeat;
|
||||
|
||||
border: 4px solid #6b4b2a;
|
||||
|
||||
border-radius: 10px;
|
||||
|
||||
box-shadow:
|
||||
@ -48,7 +50,6 @@ body {
|
||||
inset 0 0 25px rgba(0, 0, 0, 0.5);
|
||||
|
||||
display: none;
|
||||
|
||||
z-index: 1000;
|
||||
|
||||
animation: popupFade 0.25s ease;
|
||||
@ -60,9 +61,7 @@ body {
|
||||
|
||||
.popup-header {
|
||||
padding: 14px;
|
||||
|
||||
font-family: "Tangerine", serif;
|
||||
|
||||
font-size: 36px;
|
||||
|
||||
background: linear-gradient(#6b4b2a, #3c2414);
|
||||
@ -70,11 +69,9 @@ body {
|
||||
border-bottom: 2px solid #8b6a3c;
|
||||
|
||||
display: flex;
|
||||
|
||||
justify-content: space-between;
|
||||
|
||||
color: #f0d9a6;
|
||||
|
||||
text-shadow: 0 2px 4px black;
|
||||
}
|
||||
|
||||
@ -88,27 +85,22 @@ body {
|
||||
|
||||
.popup-tabs {
|
||||
display: flex;
|
||||
|
||||
border-bottom: 2px solid #8b6a3c;
|
||||
}
|
||||
|
||||
.popup-tabs button {
|
||||
flex: 1;
|
||||
|
||||
padding: 10px;
|
||||
|
||||
font-family: "Cinzel", serif;
|
||||
|
||||
font-weight: bold;
|
||||
|
||||
background: linear-gradient(#5c3b20, #3a2513);
|
||||
|
||||
border: 1px solid #8b6a3c;
|
||||
|
||||
color: #e7d9b4;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
@ -118,7 +110,6 @@ body {
|
||||
|
||||
.popup-tabs button.active {
|
||||
background: linear-gradient(#d4b97a, #9c7a3a);
|
||||
|
||||
color: #2b1b0f;
|
||||
}
|
||||
|
||||
@ -129,35 +120,23 @@ body {
|
||||
.popup-content {
|
||||
padding: 20px;
|
||||
|
||||
font-family: "Cinzel", serif;
|
||||
|
||||
font-size: 20px;
|
||||
|
||||
line-height: 1.6;
|
||||
|
||||
letter-spacing: 0.5px;
|
||||
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
|
||||
border-radius: 6px;
|
||||
|
||||
color: #2b1b0f;
|
||||
}
|
||||
|
||||
/* Titel im Inhalt */
|
||||
|
||||
.popup-content h3 {
|
||||
font-family: "Tangerine", serif;
|
||||
|
||||
font-size: 32px;
|
||||
|
||||
color: #3b2412;
|
||||
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Text */
|
||||
|
||||
.popup-content p {
|
||||
color: #3a2413;
|
||||
}
|
||||
@ -184,28 +163,164 @@ body {
|
||||
background: linear-gradient(#7a5a2a, #caa24b);
|
||||
|
||||
border: 1px solid #e0c67b;
|
||||
|
||||
padding: 10px 18px;
|
||||
|
||||
color: #1a1206;
|
||||
|
||||
font-weight: bold;
|
||||
|
||||
font-family: "Cinzel", serif;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.popup-content button:hover {
|
||||
transform: scale(1.05);
|
||||
|
||||
box-shadow:
|
||||
0 0 10px #ffd66b,
|
||||
0 0 25px #caa24b;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Tooltip
|
||||
========================= */
|
||||
|
||||
#map-tooltip {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
color: #fff;
|
||||
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
|
||||
font-size: 14px;
|
||||
|
||||
display: none;
|
||||
z-index: 9999;
|
||||
|
||||
max-width: 200px;
|
||||
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
#map-tooltip strong {
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Character Window
|
||||
========================= */
|
||||
|
||||
#character-ui {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 60px;
|
||||
|
||||
margin-bottom: 40px;
|
||||
margin-top: -20px;
|
||||
}
|
||||
|
||||
.equip-left,
|
||||
.equip-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.character img {
|
||||
height: 280px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Equipment Slots
|
||||
========================= */
|
||||
|
||||
.equip-slot {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
|
||||
background-image: url("/images/items/slot_mittel.png");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Inventory
|
||||
========================= */
|
||||
|
||||
#inventory-grid {
|
||||
display: grid;
|
||||
|
||||
grid-template-columns: repeat(8, 70px);
|
||||
grid-template-rows: repeat(4, 70px);
|
||||
|
||||
gap: 8px;
|
||||
|
||||
justify-content: center;
|
||||
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.inventory-slot {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
|
||||
background-image: url("/images/items/slot_mittel.png");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-common {
|
||||
border: 2px solid #9d9d9d;
|
||||
}
|
||||
|
||||
.item-rare {
|
||||
border: 2px solid #0070dd;
|
||||
}
|
||||
|
||||
.item-epic {
|
||||
border: 2px solid #a335ee;
|
||||
}
|
||||
|
||||
.item-legendary {
|
||||
border: 2px solid #ff8000;
|
||||
}
|
||||
|
||||
.inventory-slot img,
|
||||
.equip-slot img {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.inventory-slot:hover {
|
||||
filter: brightness(1.2);
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Tooltip (Items)
|
||||
========================= */
|
||||
|
||||
#item-tooltip {
|
||||
position: absolute;
|
||||
background: #111;
|
||||
border: 1px solid #555;
|
||||
padding: 6px;
|
||||
color: white;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Animation
|
||||
========================= */
|
||||
@ -221,115 +336,3 @@ body {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
/* =========================
|
||||
Popup Titel
|
||||
========================= */
|
||||
|
||||
#popup-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#map-tooltip {
|
||||
position: fixed;
|
||||
pointer-events: none;
|
||||
background: rgba(0, 0, 0, 0.85);
|
||||
color: #fff;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
display: none;
|
||||
z-index: 9999;
|
||||
max-width: 200px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
#map-tooltip strong {
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
#inventory-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 64px);
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.inventory-slot {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
background: #1b1b1b;
|
||||
border: 1px solid #8b6f3d;
|
||||
position: relative;
|
||||
box-shadow: 0 0 4px #000 inset;
|
||||
}
|
||||
|
||||
.inventory-slot img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.item-amount {
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
right: 4px;
|
||||
font-size: 12px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#item-tooltip {
|
||||
position: absolute;
|
||||
background: #111;
|
||||
border: 1px solid #555;
|
||||
padding: 6px;
|
||||
color: white;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#character-ui {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 40px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.equip-left,
|
||||
.equip-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.equip-slot {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: 2px solid #8b6f3d;
|
||||
background: #111;
|
||||
}
|
||||
|
||||
.equip-slot img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.character img {
|
||||
height: 260px;
|
||||
}
|
||||
|
||||
#inventory-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 64px);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.inventory-slot {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: 1px solid #555;
|
||||
background: #1b1b1b;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inventory-slot img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
BIN
public/images/items/slot_gross.png
Normal file
BIN
public/images/items/slot_gross.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
public/images/items/slot_klein.png
Normal file
BIN
public/images/items/slot_klein.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
BIN
public/images/items/slot_mittel.png
Normal file
BIN
public/images/items/slot_mittel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
@ -33,6 +33,22 @@ export async function loadWohnhaus() {
|
||||
`;
|
||||
|
||||
loadInventory();
|
||||
loadEquipment();
|
||||
}
|
||||
|
||||
async function loadEquipment() {
|
||||
const res = await fetch("/api/equipment");
|
||||
const equipment = await res.json();
|
||||
|
||||
equipment.forEach((item) => {
|
||||
const slot = document.querySelector(
|
||||
'.equip-slot[data-slot="' + item.slot + '"]',
|
||||
);
|
||||
|
||||
if (!slot) return;
|
||||
|
||||
slot.innerHTML = `<img src="${item.icon}">`;
|
||||
});
|
||||
}
|
||||
|
||||
async function loadInventory() {
|
||||
@ -48,7 +64,9 @@ async function loadInventory() {
|
||||
|
||||
html += `
|
||||
<div class="inventory-slot"
|
||||
data-slot="${item.equip_slot || ""}">
|
||||
data-slot="${item.equip_slot}"
|
||||
data-id="${item.id}"
|
||||
data-level="${item.level}">
|
||||
<img src="${icon}">
|
||||
</div>
|
||||
`;
|
||||
@ -61,16 +79,34 @@ data-slot="${item.equip_slot || ""}">
|
||||
|
||||
function initEquip() {
|
||||
document.querySelectorAll(".inventory-slot").forEach((item) => {
|
||||
const icon = item.querySelector("img").src;
|
||||
|
||||
item.addEventListener("click", () => {
|
||||
const slot = item.dataset.slot;
|
||||
const slotType = item.dataset.slot;
|
||||
|
||||
const target = document.querySelector(
|
||||
'.equip-slot[data-slot="' + slot + '"]',
|
||||
'.equip-slot[data-slot="' + slotType + '"]',
|
||||
);
|
||||
|
||||
if (!target) return;
|
||||
|
||||
target.innerHTML = item.innerHTML;
|
||||
target.innerHTML = `<img src="${icon}">`;
|
||||
|
||||
saveEquipment(slotType, item.dataset.id, item.dataset.level);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function saveEquipment(slot, itemId, itemLevelId) {
|
||||
await fetch("/api/equip", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
slot: slot,
|
||||
itemId: itemId,
|
||||
itemLevelId: itemLevelId,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,16 +3,20 @@ const router = express.Router();
|
||||
const db = require("../database/database");
|
||||
|
||||
router.post("/", async (req, res) => {
|
||||
const userId = 1;
|
||||
const { itemId, itemLevelId } = req.body;
|
||||
const userId = req.session.user.id;
|
||||
|
||||
const { slot, itemId, itemLevelId } = req.body;
|
||||
|
||||
await db.query(
|
||||
`
|
||||
REPLACE INTO avatar_equipment
|
||||
(user_id,slot,item_id,item_level_id)
|
||||
VALUES (?,?,?,?)
|
||||
`,
|
||||
[userId, "weapon", itemId, itemLevelId],
|
||||
INSERT INTO avatar_equipment
|
||||
(user_id,slot,item_id,item_level_id)
|
||||
VALUES (?,?,?,?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
item_id = VALUES(item_id),
|
||||
item_level_id = VALUES(item_level_id)
|
||||
`,
|
||||
[userId, slot, itemId, itemLevelId],
|
||||
);
|
||||
|
||||
res.json({ success: true });
|
||||
|
||||
23
routes/equipment.js
Normal file
23
routes/equipment.js
Normal file
@ -0,0 +1,23 @@
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
const db = require("../database/database");
|
||||
|
||||
router.get("/", async (req, res) => {
|
||||
const userId = req.session.user.id;
|
||||
|
||||
const [rows] = await db.query(
|
||||
`
|
||||
SELECT
|
||||
ae.slot,
|
||||
items.icon
|
||||
FROM avatar_equipment ae
|
||||
LEFT JOIN items ON items.id = ae.item_id
|
||||
WHERE ae.user_id=?
|
||||
`,
|
||||
[userId],
|
||||
);
|
||||
|
||||
res.json(rows);
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Loading…
Reference in New Issue
Block a user