This repository has been archived on 2026-05-04. You can view files and clone it, but cannot push or open issues or pull requests.
Galaxy-Strike-Online/GameServer/systems/ShipSystem.js
2026-01-24 21:39:56 -04:00

489 lines
14 KiB
JavaScript

/**
* Galaxy Strike Online - Server Ship System
* Manages ship data, upgrades, and combat mechanics
*/
class ShipSystem {
constructor() {
this.shipTemplates = new Map();
this.playerShips = new Map(); // userId -> array of ships
this.initializeShipTemplates();
}
initializeShipTemplates() {
// Starter Ships
this.addShipTemplate('starter_cruiser', {
name: 'Starter Cruiser',
class: 'Cruiser',
description: 'A reliable cruiser for beginners',
rarity: 'Common',
baseStats: {
health: 100,
maxHealth: 100,
attack: 10,
defense: 5,
speed: 10,
energy: 50,
maxEnergy: 50
},
slots: {
weapon: 2,
armor: 1,
module: 1
},
requirements: {
level: 1,
credits: 0
},
experience: 0,
requiredExp: 100,
texture: 'assets/textures/ships/starter_cruiser.png'
});
this.addShipTemplate('light_fighter', {
name: 'Light Fighter',
class: 'Fighter',
description: 'Fast and agile fighter ship',
rarity: 'Common',
baseStats: {
health: 80,
maxHealth: 80,
attack: 15,
defense: 3,
speed: 15,
energy: 40,
maxEnergy: 40
},
slots: {
weapon: 3,
armor: 0,
module: 2
},
requirements: {
level: 3,
credits: 1000
},
experience: 0,
requiredExp: 150,
texture: 'assets/textures/ships/light_fighter.png'
});
this.addShipTemplate('heavy_bomber', {
name: 'Heavy Bomber',
class: 'Bomber',
description: 'Slow but powerful bomber',
rarity: 'Uncommon',
baseStats: {
health: 150,
maxHealth: 150,
attack: 25,
defense: 10,
speed: 5,
energy: 60,
maxEnergy: 60
},
slots: {
weapon: 4,
armor: 2,
module: 1
},
requirements: {
level: 5,
credits: 5000
},
experience: 0,
requiredExp: 200,
texture: 'assets/textures/ships/heavy_bomber.png'
});
this.addShipTemplate('exploration_vessel', {
name: 'Exploration Vessel',
class: 'Explorer',
description: 'Versatile ship for exploration missions',
rarity: 'Rare',
baseStats: {
health: 120,
maxHealth: 120,
attack: 12,
defense: 8,
speed: 12,
energy: 80,
maxEnergy: 80
},
slots: {
weapon: 2,
armor: 1,
module: 3
},
requirements: {
level: 8,
credits: 15000
},
experience: 0,
requiredExp: 300,
texture: 'assets/textures/ships/exploration_vessel.png'
});
this.addShipTemplate('battle_cruiser', {
name: 'Battle Cruiser',
class: 'Cruiser',
description: 'Heavy combat cruiser',
rarity: 'Rare',
baseStats: {
health: 200,
maxHealth: 200,
attack: 30,
defense: 15,
speed: 8,
energy: 70,
maxEnergy: 70
},
slots: {
weapon: 5,
armor: 3,
module: 2
},
requirements: {
level: 12,
credits: 50000
},
experience: 0,
requiredExp: 500,
texture: 'assets/textures/ships/battle_cruiser.png'
});
this.addShipTemplate('flagship', {
name: 'Flagship',
class: 'Capital',
description: 'Ultimate command vessel',
rarity: 'Legendary',
baseStats: {
health: 500,
maxHealth: 500,
attack: 50,
defense: 30,
speed: 6,
energy: 150,
maxEnergy: 150
},
slots: {
weapon: 8,
armor: 5,
module: 4
},
requirements: {
level: 20,
credits: 500000
},
experience: 0,
requiredExp: 1000,
texture: 'assets/textures/ships/flagship.png'
});
}
addShipTemplate(id, template) {
this.shipTemplates.set(id, {
id,
...template,
createdAt: new Date().toISOString()
});
}
getShipTemplate(id) {
return this.shipTemplates.get(id);
}
getShipTemplatesByClass(shipClass) {
return Array.from(this.shipTemplates.values()).filter(template => template.class === shipClass);
}
getShipTemplatesByRarity(rarity) {
return Array.from(this.shipTemplates.values()).filter(template => template.rarity === rarity);
}
getAllShipTemplates() {
return Array.from(this.shipTemplates.values());
}
initializePlayerShips(userId) {
if (!this.playerShips.has(userId)) {
this.playerShips.set(userId, []);
// Give starter ship to new players
const starterShip = this.createShip(userId, 'starter_cruiser');
if (starterShip) {
this.playerShips.get(userId).push(starterShip);
}
}
return this.playerShips.get(userId);
}
createShip(userId, templateId, customizations = {}) {
const template = this.shipTemplates.get(templateId);
if (!template) {
throw new Error(`Ship template not found: ${templateId}`);
}
const ship = {
id: `ship_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
userId,
templateId,
name: customizations.name || template.name,
class: template.class,
rarity: template.rarity,
level: customizations.level || 1,
experience: 0,
requiredExp: template.requiredExp,
stats: { ...template.baseStats },
maxStats: { ...template.baseStats },
slots: { ...template.slots },
equippedItems: {},
texture: template.texture,
status: 'active',
createdAt: new Date().toISOString(),
lastUsed: new Date().toISOString()
};
return ship;
}
getPlayerShips(userId) {
return this.playerShips.get(userId) || this.initializePlayerShips(userId);
}
getShip(userId, shipId) {
const ships = this.getPlayerShips(userId);
return ships.find(ship => ship.id === shipId);
}
getCurrentShip(userId) {
const ships = this.getPlayerShips(userId);
return ships.find(ship => ship.status === 'active' && ship.lastUsed === Math.max(...ships.map(s => new Date(s.lastUsed).getTime())));
}
setCurrentShip(userId, shipId) {
const ships = this.getPlayerShips(userId);
const ship = ships.find(s => s.id === shipId);
if (!ship) {
throw new Error('Ship not found');
}
// Update last used time for all ships
ships.forEach(s => {
if (s.id === shipId) {
s.status = 'active';
s.lastUsed = new Date().toISOString();
} else {
s.status = 'inactive';
}
});
return ship;
}
addExperience(userId, shipId, amount) {
const ship = this.getShip(userId, shipId);
if (!ship) {
throw new Error('Ship not found');
}
ship.experience += amount;
// Check for level up
let levelsGained = 0;
while (ship.experience >= ship.requiredExp) {
ship.experience -= ship.requiredExp;
ship.level += 1;
levelsGained++;
// Increase stats on level up
this.levelUpShip(ship);
// Update required experience for next level
ship.requiredExp = this.getExperienceNeeded(ship.level);
}
return {
experienceGained: amount,
levelsGained,
newLevel: ship.level,
newStats: ship.stats
};
}
levelUpShip(ship) {
const statIncrease = 1.1; // 10% increase per level
for (const [stat, value] of Object.entries(ship.stats)) {
if (typeof value === 'number') {
ship.stats[stat] = Math.floor(value * statIncrease);
ship.maxStats[stat] = Math.floor(ship.maxStats[stat] * statIncrease);
}
}
}
getExperienceNeeded(level) {
// Exponential experience curve
return Math.floor(100 * Math.pow(1.5, level - 1));
}
upgradeShip(userId, shipId, upgradeType) {
const ship = this.getShip(userId, shipId);
if (!ship) {
throw new Error('Ship not found');
}
switch (upgradeType) {
case 'health':
ship.stats.health = Math.floor(ship.stats.health * 1.2);
ship.stats.maxHealth = Math.floor(ship.stats.maxHealth * 1.2);
break;
case 'attack':
ship.stats.attack = Math.floor(ship.stats.attack * 1.15);
break;
case 'defense':
ship.stats.defense = Math.floor(ship.stats.defense * 1.15);
break;
case 'speed':
ship.stats.speed = Math.floor(ship.stats.speed * 1.1);
break;
case 'energy':
ship.stats.energy = Math.floor(ship.stats.energy * 1.2);
ship.stats.maxEnergy = Math.floor(ship.stats.maxEnergy * 1.2);
break;
default:
throw new Error('Invalid upgrade type');
}
return {
upgradeType,
newStats: ship.stats
};
}
equipItem(userId, shipId, slot, itemId) {
const ship = this.getShip(userId, shipId);
if (!ship) {
throw new Error('Ship not found');
}
if (!ship.slots[slot]) {
throw new Error('Invalid slot type');
}
ship.equippedItems[slot] = itemId;
return {
slot,
itemId,
equippedItems: ship.equippedItems
};
}
unequipItem(userId, shipId, slot) {
const ship = this.getShip(userId, shipId);
if (!ship) {
throw new Error('Ship not found');
}
const itemId = ship.equippedItems[slot];
delete ship.equippedItems[slot];
return {
slot,
itemId,
equippedItems: ship.equippedItems
};
}
repairShip(userId, shipId, amount = null) {
const ship = this.getShip(userId, shipId);
if (!ship) {
throw new Error('Ship not found');
}
if (amount === null) {
// Full repair
ship.stats.health = ship.stats.maxHealth;
} else {
// Partial repair
ship.stats.health = Math.min(ship.stats.health + amount, ship.stats.maxHealth);
}
return {
health: ship.stats.health,
maxHealth: ship.stats.maxHealth,
repaired: amount || (ship.stats.maxHealth - ship.stats.health)
};
}
deleteShip(userId, shipId) {
const ships = this.getPlayerShips(userId);
const shipIndex = ships.findIndex(ship => ship.id === shipId);
if (shipIndex === -1) {
throw new Error('Ship not found');
}
const deletedShip = ships.splice(shipIndex, 1)[0];
// If this was the current ship, set a new current ship
if (deletedShip.status === 'active' && ships.length > 0) {
ships[0].status = 'active';
ships[0].lastUsed = new Date().toISOString();
}
return deletedShip;
}
getShipClasses() {
const classes = new Set();
for (const template of this.shipTemplates.values()) {
classes.add(template.class);
}
return Array.from(classes).sort();
}
getShipRarities() {
const rarities = new Set();
for (const template of this.shipTemplates.values()) {
rarities.add(template.rarity);
}
return Array.from(rarities).sort();
}
getAvailableShips(userId, playerLevel = 1) {
return Array.from(this.shipTemplates.values())
.filter(template => template.requirements.level <= playerLevel)
.map(template => ({
id: template.id,
name: template.name,
class: template.class,
rarity: template.rarity,
description: template.description,
requirements: template.requirements,
baseStats: template.baseStats,
slots: template.slots,
texture: template.texture
}));
}
getPlayerShipStats(userId) {
const ships = this.getPlayerShips(userId);
return {
totalShips: ships.length,
activeShip: this.getCurrentShip(userId),
shipClasses: ships.reduce((acc, ship) => {
acc[ship.class] = (acc[ship.class] || 0) + 1;
return acc;
}, {}),
averageLevel: ships.length > 0 ? Math.floor(ships.reduce((sum, ship) => sum + ship.level, 0) / ships.length) : 0,
totalExperience: ships.reduce((sum, ship) => sum + ship.experience, 0)
};
}
}
module.exports = ShipSystem;