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 inventory = require("./routes/inventory");
|
||||||
const avatar = require("./routes/avatar");
|
const avatar = require("./routes/avatar");
|
||||||
const equip = require("./routes/equip");
|
const equip = require("./routes/equip");
|
||||||
|
const equipment = require("./routes/equipment");
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.set("trust proxy", 1);
|
app.set("trust proxy", 1);
|
||||||
@ -191,6 +192,7 @@ app.use("/", buildingRoutes);
|
|||||||
app.use("/api/inventory", inventory);
|
app.use("/api/inventory", inventory);
|
||||||
app.use("/api/avatar", avatar);
|
app.use("/api/avatar", avatar);
|
||||||
app.use("/api/equip", equip);
|
app.use("/api/equip", equip);
|
||||||
|
app.use("/api/equipment", equipment);
|
||||||
|
|
||||||
/* ========================
|
/* ========================
|
||||||
404 Handler
|
404 Handler
|
||||||
|
|||||||
@ -1,3 +1,7 @@
|
|||||||
|
/* =========================
|
||||||
|
Base
|
||||||
|
========================= */
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
@ -29,18 +33,16 @@ body {
|
|||||||
|
|
||||||
.building-popup {
|
.building-popup {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
|
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
width: 460px;
|
width: 900px;
|
||||||
|
max-width: 90vw;
|
||||||
|
|
||||||
background: url("/images/parchment.png") center / cover no-repeat;
|
background: url("/images/parchment.png") center / cover no-repeat;
|
||||||
|
|
||||||
border: 4px solid #6b4b2a;
|
border: 4px solid #6b4b2a;
|
||||||
|
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
|
||||||
box-shadow:
|
box-shadow:
|
||||||
@ -48,7 +50,6 @@ body {
|
|||||||
inset 0 0 25px rgba(0, 0, 0, 0.5);
|
inset 0 0 25px rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
display: none;
|
display: none;
|
||||||
|
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
|
|
||||||
animation: popupFade 0.25s ease;
|
animation: popupFade 0.25s ease;
|
||||||
@ -60,9 +61,7 @@ body {
|
|||||||
|
|
||||||
.popup-header {
|
.popup-header {
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
|
|
||||||
font-family: "Tangerine", serif;
|
font-family: "Tangerine", serif;
|
||||||
|
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
|
|
||||||
background: linear-gradient(#6b4b2a, #3c2414);
|
background: linear-gradient(#6b4b2a, #3c2414);
|
||||||
@ -70,11 +69,9 @@ body {
|
|||||||
border-bottom: 2px solid #8b6a3c;
|
border-bottom: 2px solid #8b6a3c;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
color: #f0d9a6;
|
color: #f0d9a6;
|
||||||
|
|
||||||
text-shadow: 0 2px 4px black;
|
text-shadow: 0 2px 4px black;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,27 +85,22 @@ body {
|
|||||||
|
|
||||||
.popup-tabs {
|
.popup-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
border-bottom: 2px solid #8b6a3c;
|
border-bottom: 2px solid #8b6a3c;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-tabs button {
|
.popup-tabs button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
font-family: "Cinzel", serif;
|
font-family: "Cinzel", serif;
|
||||||
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
background: linear-gradient(#5c3b20, #3a2513);
|
background: linear-gradient(#5c3b20, #3a2513);
|
||||||
|
|
||||||
border: 1px solid #8b6a3c;
|
border: 1px solid #8b6a3c;
|
||||||
|
|
||||||
color: #e7d9b4;
|
color: #e7d9b4;
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +110,6 @@ body {
|
|||||||
|
|
||||||
.popup-tabs button.active {
|
.popup-tabs button.active {
|
||||||
background: linear-gradient(#d4b97a, #9c7a3a);
|
background: linear-gradient(#d4b97a, #9c7a3a);
|
||||||
|
|
||||||
color: #2b1b0f;
|
color: #2b1b0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,35 +120,23 @@ body {
|
|||||||
.popup-content {
|
.popup-content {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
|
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
|
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
|
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
|
||||||
color: #2b1b0f;
|
color: #2b1b0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Titel im Inhalt */
|
|
||||||
|
|
||||||
.popup-content h3 {
|
.popup-content h3 {
|
||||||
font-family: "Tangerine", serif;
|
font-family: "Tangerine", serif;
|
||||||
|
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
|
|
||||||
color: #3b2412;
|
color: #3b2412;
|
||||||
|
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Text */
|
|
||||||
|
|
||||||
.popup-content p {
|
.popup-content p {
|
||||||
color: #3a2413;
|
color: #3a2413;
|
||||||
}
|
}
|
||||||
@ -184,28 +163,164 @@ body {
|
|||||||
background: linear-gradient(#7a5a2a, #caa24b);
|
background: linear-gradient(#7a5a2a, #caa24b);
|
||||||
|
|
||||||
border: 1px solid #e0c67b;
|
border: 1px solid #e0c67b;
|
||||||
|
|
||||||
padding: 10px 18px;
|
padding: 10px 18px;
|
||||||
|
|
||||||
color: #1a1206;
|
color: #1a1206;
|
||||||
|
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
||||||
font-family: "Cinzel", serif;
|
|
||||||
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
transition: 0.2s;
|
transition: 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-content button:hover {
|
.popup-content button:hover {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
|
|
||||||
box-shadow:
|
box-shadow:
|
||||||
0 0 10px #ffd66b,
|
0 0 10px #ffd66b,
|
||||||
0 0 25px #caa24b;
|
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
|
Animation
|
||||||
========================= */
|
========================= */
|
||||||
@ -221,115 +336,3 @@ body {
|
|||||||
transform: translate(-50%, -50%);
|
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();
|
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() {
|
async function loadInventory() {
|
||||||
@ -48,7 +64,9 @@ async function loadInventory() {
|
|||||||
|
|
||||||
html += `
|
html += `
|
||||||
<div class="inventory-slot"
|
<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}">
|
<img src="${icon}">
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
@ -61,16 +79,34 @@ data-slot="${item.equip_slot || ""}">
|
|||||||
|
|
||||||
function initEquip() {
|
function initEquip() {
|
||||||
document.querySelectorAll(".inventory-slot").forEach((item) => {
|
document.querySelectorAll(".inventory-slot").forEach((item) => {
|
||||||
|
const icon = item.querySelector("img").src;
|
||||||
|
|
||||||
item.addEventListener("click", () => {
|
item.addEventListener("click", () => {
|
||||||
const slot = item.dataset.slot;
|
const slotType = item.dataset.slot;
|
||||||
|
|
||||||
const target = document.querySelector(
|
const target = document.querySelector(
|
||||||
'.equip-slot[data-slot="' + slot + '"]',
|
'.equip-slot[data-slot="' + slotType + '"]',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!target) return;
|
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");
|
const db = require("../database/database");
|
||||||
|
|
||||||
router.post("/", async (req, res) => {
|
router.post("/", async (req, res) => {
|
||||||
const userId = 1;
|
const userId = req.session.user.id;
|
||||||
const { itemId, itemLevelId } = req.body;
|
|
||||||
|
const { slot, itemId, itemLevelId } = req.body;
|
||||||
|
|
||||||
await db.query(
|
await db.query(
|
||||||
`
|
`
|
||||||
REPLACE INTO avatar_equipment
|
INSERT INTO avatar_equipment
|
||||||
(user_id,slot,item_id,item_level_id)
|
(user_id,slot,item_id,item_level_id)
|
||||||
VALUES (?,?,?,?)
|
VALUES (?,?,?,?)
|
||||||
`,
|
ON DUPLICATE KEY UPDATE
|
||||||
[userId, "weapon", itemId, itemLevelId],
|
item_id = VALUES(item_id),
|
||||||
|
item_level_id = VALUES(item_level_id)
|
||||||
|
`,
|
||||||
|
[userId, slot, itemId, itemLevelId],
|
||||||
);
|
);
|
||||||
|
|
||||||
res.json({ success: true });
|
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