Update Dungeonsystem
This commit is contained in:
parent
54b85f0f1f
commit
86bfae2228
@ -31,7 +31,6 @@ class GameDataManager {
|
|||||||
if (Array.isArray(data.rooms)) {
|
if (Array.isArray(data.rooms)) {
|
||||||
data.rooms.forEach((r) => this.rooms.set(r.id, r));
|
data.rooms.forEach((r) => this.rooms.set(r.id, r));
|
||||||
}
|
}
|
||||||
console.log(this.hostiles);
|
|
||||||
if (data.languages) {
|
if (data.languages) {
|
||||||
this.translations = data.languages;
|
this.translations = data.languages;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -233,3 +233,41 @@
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qty-label {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 2px;
|
||||||
|
right: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 800;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow:
|
||||||
|
1px 1px 0 #000,
|
||||||
|
-1px -1px 0 #000,
|
||||||
|
1px -1px 0 #000,
|
||||||
|
-1px 1px 0 #000,
|
||||||
|
0 0 5px rgba(0, 0, 0, 0.8);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-slot {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
background: rgba(5, 8, 12, 0.9);
|
||||||
|
border: 1px solid #1a2638;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.2s;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-img-grid {
|
||||||
|
max-width: 80%;
|
||||||
|
max-height: 80%;
|
||||||
|
object-fit: contain;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|||||||
@ -3,12 +3,14 @@
|
|||||||
"id": "original:tutorial/tutorial_dungeon",
|
"id": "original:tutorial/tutorial_dungeon",
|
||||||
"displayName": "dungeons.original.tutorial.tutorial",
|
"displayName": "dungeons.original.tutorial.tutorial",
|
||||||
"description": "dungeons.original.tutorial.tutorial.desc",
|
"description": "dungeons.original.tutorial.tutorial.desc",
|
||||||
"meta":{
|
"meta": {
|
||||||
"energyCost": 0,
|
"energyCost": 0,
|
||||||
"repeatable": false,
|
"repeatable": false,
|
||||||
"missionArea":"space",
|
"missionArea": "space",
|
||||||
"raid": false, "_comment_1":"Future raid type picking, when you can have friends in the dugeon to help you.",
|
"raid": false,
|
||||||
"missionAllowed": [], "_comment_2":"Future ship type picking, when ship classes are started"
|
"_comment_1": "Future raid type picking, when you can have friends in the dugeon to help you.",
|
||||||
|
"missionAllowed": [],
|
||||||
|
"_comment_2": "Future ship type picking, when ship classes are started"
|
||||||
},
|
},
|
||||||
"rooms": [
|
"rooms": [
|
||||||
{ "id": "original:tutorial/tutorial_enemy_room" },
|
{ "id": "original:tutorial/tutorial_enemy_room" },
|
||||||
|
|||||||
@ -8,6 +8,19 @@
|
|||||||
"damage": 4,
|
"damage": 4,
|
||||||
"critical.chance": 0.3,
|
"critical.chance": 0.3,
|
||||||
"attack.rate": 2
|
"attack.rate": 2
|
||||||
|
},
|
||||||
|
"loot": [
|
||||||
|
{
|
||||||
|
"id": "original:ore_coal",
|
||||||
|
"chance": 1.0,
|
||||||
|
"count": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "original:ore_copper",
|
||||||
|
"chance": 1.0,
|
||||||
|
"count": 20
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"meta": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"rooms": {
|
"rooms": {
|
||||||
"id": "original:tutorial/tutorial_boss_room",
|
"id": "original:tutorial/tutorial_boss_room",
|
||||||
|
"displayName": "rooms.original.tutorial.tutorial_boss_room.name",
|
||||||
|
"description": "rooms.original.tutorial.tutorial_boss_room.desc",
|
||||||
"hostiles": ["original:tutorial/tutorial_boss_hostile"],
|
"hostiles": ["original:tutorial/tutorial_boss_hostile"],
|
||||||
"gainXp": 4,
|
"gainXp": 4,
|
||||||
"credits": 200
|
"credits": 200,
|
||||||
|
"loot": [],
|
||||||
|
"meta": {
|
||||||
|
"isBossRoom": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"rooms": {
|
"rooms": {
|
||||||
"id": "original:tutorial/tutorial_enemy_room",
|
"id": "original:tutorial/tutorial_enemy_room",
|
||||||
|
"displayName": "rooms.original.tutorial.tutorial_enemy_room.name",
|
||||||
|
"description": "rooms.original.tutorial.tutorial_enemy_room.desc",
|
||||||
"hostiles": ["original:tutorial/tutorial_hostile"],
|
"hostiles": ["original:tutorial/tutorial_hostile"],
|
||||||
"gainXp": 3,
|
"gainXp": 3,
|
||||||
"credits": 30
|
"credits": 30,
|
||||||
|
"loot": [],
|
||||||
|
"meta": {
|
||||||
|
"isBossRoom": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,20 @@
|
|||||||
{
|
{
|
||||||
"rooms": {
|
"rooms": {
|
||||||
"id": "original:tutorial/tutorial_loot_room",
|
"id": "original:tutorial/tutorial_loot_room",
|
||||||
"loot": [{ "id": "original:bio_pulp", "count": 1 }]
|
"displayName": "rooms.original.tutorial.tutorial_loot_room.name",
|
||||||
|
"description": "rooms.original.tutorial.tutorial_loot_room.desc",
|
||||||
|
"hostiles": [],
|
||||||
|
"gainXp": 0,
|
||||||
|
"credits": 0,
|
||||||
|
"loot": [
|
||||||
|
{
|
||||||
|
"id": "original:bio_pulp",
|
||||||
|
"chance": 1.0,
|
||||||
|
"count": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"isBossRoom": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -147,7 +147,7 @@ class DatapackLoader {
|
|||||||
const data = json[typeKey];
|
const data = json[typeKey];
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
const fullId = `${packName}:${data.id}`;
|
const fullId = `${data.id}`;
|
||||||
|
|
||||||
switch (typeKey) {
|
switch (typeKey) {
|
||||||
case "armour":
|
case "armour":
|
||||||
|
|||||||
@ -16,7 +16,6 @@ class DungeonManager {
|
|||||||
currentEnemyHp: undefined,
|
currentEnemyHp: undefined,
|
||||||
rewards: { xp: 0, credits: 0, items: [] },
|
rewards: { xp: 0, credits: 0, items: [] },
|
||||||
};
|
};
|
||||||
|
|
||||||
this.activeSessions.set(playerId, session);
|
this.activeSessions.set(playerId, session);
|
||||||
return this.getCurrentRoomData(playerId);
|
return this.getCurrentRoomData(playerId);
|
||||||
}
|
}
|
||||||
@ -27,16 +26,17 @@ class DungeonManager {
|
|||||||
|
|
||||||
const dungeon = DatapackLoader.getDungeon(session.dungeonId);
|
const dungeon = DatapackLoader.getDungeon(session.dungeonId);
|
||||||
const roomRef = dungeon.rooms[session.currentRoomIndex];
|
const roomRef = dungeon.rooms[session.currentRoomIndex];
|
||||||
const roomData = DatapackLoader.getRoom(roomRef.id);
|
|
||||||
if (!roomData) return null;
|
|
||||||
|
|
||||||
|
const rawRoom = DatapackLoader.getRoom(roomRef.id);
|
||||||
|
|
||||||
|
if (!rawRoom) return null;
|
||||||
|
|
||||||
|
const roomData = rawRoom;
|
||||||
const hostiles = (roomData.hostiles || [])
|
const hostiles = (roomData.hostiles || [])
|
||||||
.map((hId) => {
|
.map((hId) => {
|
||||||
const hostile = DatapackLoader.getEnemy(hId);
|
return DatapackLoader.getEnemy(hId);
|
||||||
return hostile ? { ...hostile } : null;
|
|
||||||
})
|
})
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
roomIndex: session.currentRoomIndex,
|
roomIndex: session.currentRoomIndex,
|
||||||
totalRooms: dungeon.rooms.length,
|
totalRooms: dungeon.rooms.length,
|
||||||
@ -51,15 +51,29 @@ class DungeonManager {
|
|||||||
|
|
||||||
const dungeon = DatapackLoader.getDungeon(session.dungeonId);
|
const dungeon = DatapackLoader.getDungeon(session.dungeonId);
|
||||||
const roomRef = dungeon.rooms[session.currentRoomIndex];
|
const roomRef = dungeon.rooms[session.currentRoomIndex];
|
||||||
const currentRoom = DatapackLoader.getRoom(roomRef.id);
|
const rawRoom = DatapackLoader.getRoom(roomRef.id);
|
||||||
|
|
||||||
if (currentRoom) {
|
if (rawRoom && rawRoom.room) {
|
||||||
session.rewards.xp += currentRoom.gainXp || 0;
|
const room = rawRoom.room;
|
||||||
session.rewards.credits += currentRoom.credits || 0;
|
|
||||||
|
|
||||||
if (currentRoom.loot && Array.isArray(currentRoom.loot)) {
|
session.rewards.xp += room.gainXp || 0;
|
||||||
currentRoom.loot.forEach((item) => {
|
session.rewards.credits += room.credits || 0;
|
||||||
session.rewards.items.push({ ...item });
|
|
||||||
|
if (room.loot && Array.isArray(room.loot)) {
|
||||||
|
room.loot.forEach((lootEntry) => {
|
||||||
|
const roll = Math.random();
|
||||||
|
if (roll <= (lootEntry.chance || 1.0)) {
|
||||||
|
session.rewards.items.push({
|
||||||
|
id: lootEntry.id,
|
||||||
|
count:
|
||||||
|
typeof lootEntry.count === "object"
|
||||||
|
? Math.floor(
|
||||||
|
Math.random() *
|
||||||
|
(lootEntry.count.max - lootEntry.count.min + 1),
|
||||||
|
) + lootEntry.count.min
|
||||||
|
: lootEntry.count || 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,25 +50,48 @@ module.exports = (io, socket) => {
|
|||||||
const session = dungeonManager.activeSessions.get(userId);
|
const session = dungeonManager.activeSessions.get(userId);
|
||||||
if (!session || session.isFinished) return;
|
if (!session || session.isFinished) return;
|
||||||
|
|
||||||
const enemyTemplate = DatapackLoader.getEnemy(enemyId);
|
const rawEnemy = DatapackLoader.getEnemy(enemyId);
|
||||||
if (!enemyTemplate) {
|
if (!rawEnemy || !rawEnemy) {
|
||||||
return socket.emit("error", { message: "Target data corrupted" });
|
return socket.emit("error", { message: "Target data corrupted" });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const enemy = rawEnemy;
|
||||||
|
|
||||||
if (session.currentEnemyHp === undefined) {
|
if (session.currentEnemyHp === undefined) {
|
||||||
session.currentEnemyHp = enemyTemplate.stats?.health || 100;
|
session.currentEnemyHp = enemy.stats?.health || 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
const damage = Math.floor(Math.random() * 10) + 20;
|
const damage = Math.floor(Math.random() * 10) + 20;
|
||||||
session.currentEnemyHp -= damage;
|
session.currentEnemyHp -= damage;
|
||||||
|
|
||||||
const isDefeated = session.currentEnemyHp <= 0;
|
const isDefeated = session.currentEnemyHp <= 0;
|
||||||
|
let lootDropped = [];
|
||||||
|
|
||||||
|
if (isDefeated && enemy.loot) {
|
||||||
|
enemy.loot.forEach((entry) => {
|
||||||
|
if (Math.random() <= (entry.chance || 1.0)) {
|
||||||
|
const count =
|
||||||
|
typeof entry.count === "object"
|
||||||
|
? Math.floor(
|
||||||
|
Math.random() * (entry.count.max - entry.count.min + 1),
|
||||||
|
) + entry.count.min
|
||||||
|
: entry.count || 1;
|
||||||
|
|
||||||
|
const drop = { id: entry.id, count };
|
||||||
|
lootDropped.push(drop);
|
||||||
|
session.rewards.items.push(drop);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
socket.emit("dungeon:combat_result", {
|
socket.emit("dungeon:combat_result", {
|
||||||
damageDealt: damage,
|
damageDealt: damage,
|
||||||
enemyHp: Math.max(0, session.currentEnemyHp),
|
enemyHp: Math.max(0, session.currentEnemyHp),
|
||||||
targetDefeated: isDefeated,
|
targetDefeated: isDefeated,
|
||||||
message: `Strike successful. Dealt ${damage} damage.`,
|
loot: lootDropped,
|
||||||
|
message: isDefeated
|
||||||
|
? `Enemy eliminated!`
|
||||||
|
: `Strike successful. Dealt ${damage} damage.`,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isDefeated) {
|
if (isDefeated) {
|
||||||
@ -119,10 +142,27 @@ async function finalizeDungeon(socket, sessionRewards) {
|
|||||||
await player.increment("credits", { by: sessionRewards.credits });
|
await player.increment("credits", { by: sessionRewards.credits });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sessionRewards.xp > 0 && player.xp !== undefined) {
|
||||||
|
await player.increment("xp", { by: sessionRewards.xp });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sessionRewards.items.length > 0) {
|
||||||
|
for (const item of sessionRewards.items) {
|
||||||
|
const [invItem, created] = await Inventory.findOrCreate({
|
||||||
|
where: { playerId: userId, itemId: item.id },
|
||||||
|
defaults: { quantity: 0 },
|
||||||
|
});
|
||||||
|
|
||||||
|
await invItem.increment("quantity", { by: item.count });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
socket.emit("dungeon:completed", {
|
socket.emit("dungeon:completed", {
|
||||||
rewards: sessionRewards,
|
rewards: sessionRewards,
|
||||||
message: "Mission successful. All objectives secured.",
|
message: "Mission successful. All objectives secured.",
|
||||||
});
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Finalize Error:", err);
|
||||||
} finally {
|
} finally {
|
||||||
dungeonManager.leaveDungeon(userId);
|
dungeonManager.leaveDungeon(userId);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user