513 lines
16 KiB
JavaScript
513 lines
16 KiB
JavaScript
/**
|
|
* Galaxy Strike Online - Server Base System
|
|
* Manages player base building and customization
|
|
*/
|
|
|
|
class BaseSystem {
|
|
constructor() {
|
|
this.playerBases = new Map(); // userId -> base data
|
|
|
|
// Room types
|
|
this.roomTypes = {
|
|
command_center: {
|
|
name: 'Command Center',
|
|
description: 'Central control room for your operations',
|
|
size: 'large',
|
|
powerCost: 20,
|
|
storageBonus: 0,
|
|
buildCost: 0,
|
|
requiredLevel: 1,
|
|
maxLevel: 1,
|
|
icon: 'fa-satellite-dish'
|
|
},
|
|
barracks: {
|
|
name: 'Barracks',
|
|
description: 'Housing for crew and allies',
|
|
size: 'medium',
|
|
powerCost: 10,
|
|
storageBonus: 100,
|
|
buildCost: 500,
|
|
requiredLevel: 2,
|
|
maxLevel: 5,
|
|
icon: 'fa-home'
|
|
},
|
|
laboratory: {
|
|
name: 'Laboratory',
|
|
description: 'Research facility for new technologies',
|
|
size: 'medium',
|
|
powerCost: 15,
|
|
storageBonus: 50,
|
|
buildCost: 1000,
|
|
requiredLevel: 3,
|
|
maxLevel: 5,
|
|
icon: 'fa-flask'
|
|
},
|
|
workshop: {
|
|
name: 'Workshop',
|
|
description: 'Crafting and equipment modification station',
|
|
size: 'medium',
|
|
powerCost: 12,
|
|
storageBonus: 80,
|
|
buildCost: 800,
|
|
requiredLevel: 2,
|
|
maxLevel: 5,
|
|
icon: 'fa-hammer'
|
|
},
|
|
storage_bay: {
|
|
name: 'Storage Bay',
|
|
description: 'Additional storage for resources and items',
|
|
size: 'large',
|
|
powerCost: 5,
|
|
storageBonus: 500,
|
|
buildCost: 300,
|
|
requiredLevel: 1,
|
|
maxLevel: 10,
|
|
icon: 'fa-warehouse'
|
|
},
|
|
power_generator: {
|
|
name: 'Power Generator',
|
|
description: 'Generates power for base operations',
|
|
size: 'small',
|
|
powerCost: -25, // Generates power
|
|
storageBonus: 0,
|
|
buildCost: 400,
|
|
requiredLevel: 2,
|
|
maxLevel: 5,
|
|
icon: 'fa-bolt'
|
|
},
|
|
defense_turret: {
|
|
name: 'Defense Turret',
|
|
description: 'Automated defense system',
|
|
size: 'small',
|
|
powerCost: 8,
|
|
storageBonus: 0,
|
|
buildCost: 600,
|
|
requiredLevel: 4,
|
|
maxLevel: 8,
|
|
icon: 'fa-crosshairs'
|
|
},
|
|
medical_bay: {
|
|
name: 'Medical Bay',
|
|
description: 'Healing station for crew',
|
|
size: 'medium',
|
|
powerCost: 10,
|
|
storageBonus: 30,
|
|
buildCost: 750,
|
|
requiredLevel: 3,
|
|
maxLevel: 5,
|
|
icon: 'fa-heartbeat'
|
|
},
|
|
communication_array: {
|
|
name: 'Communication Array',
|
|
description: 'Enhances communication and scanning',
|
|
size: 'large',
|
|
powerCost: 15,
|
|
storageBonus: 20,
|
|
buildCost: 1200,
|
|
requiredLevel: 5,
|
|
maxLevel: 3,
|
|
icon: 'fa-broadcast-tower'
|
|
},
|
|
refinery: {
|
|
name: 'Refinery',
|
|
description: 'Processes raw materials into refined resources',
|
|
size: 'large',
|
|
powerCost: 20,
|
|
storageBonus: 100,
|
|
buildCost: 2000,
|
|
requiredLevel: 6,
|
|
maxLevel: 5,
|
|
icon: 'fa-industry'
|
|
}
|
|
};
|
|
|
|
// Decoration types
|
|
this.decorationTypes = {
|
|
trophy_case: {
|
|
name: 'Trophy Case',
|
|
description: 'Display your achievements',
|
|
buildCost: 100,
|
|
icon: 'fa-trophy'
|
|
},
|
|
statue: {
|
|
name: 'Hero Statue',
|
|
description: 'Commemorative statue',
|
|
buildCost: 500,
|
|
icon: 'fa-monument'
|
|
},
|
|
garden: {
|
|
name: 'Garden',
|
|
description: 'Decorative garden area',
|
|
buildCost: 200,
|
|
icon: 'fa-tree'
|
|
},
|
|
fountain: {
|
|
name: 'Fountain',
|
|
description: 'Decorative water feature',
|
|
buildCost: 300,
|
|
icon: 'fa-water'
|
|
},
|
|
banner: {
|
|
name: 'Banner',
|
|
description: 'Display your faction colors',
|
|
buildCost: 150,
|
|
icon: 'fa-flag'
|
|
}
|
|
};
|
|
}
|
|
|
|
initializePlayerBase(userId) {
|
|
if (!this.playerBases.has(userId)) {
|
|
this.playerBases.set(userId, {
|
|
name: 'Command Center Alpha',
|
|
level: 1,
|
|
experience: 0,
|
|
experienceToNext: 500,
|
|
rooms: [
|
|
{
|
|
type: 'command_center',
|
|
level: 1,
|
|
builtAt: new Date().toISOString(),
|
|
lastUpgraded: null
|
|
}
|
|
],
|
|
decorations: [],
|
|
power: 100,
|
|
maxPower: 100,
|
|
storage: 1000,
|
|
maxStorage: 1000,
|
|
defense: 10,
|
|
maxDefense: 10,
|
|
crewCapacity: 5,
|
|
maxCrewCapacity: 5,
|
|
researchBonus: 0,
|
|
craftingBonus: 0,
|
|
createdAt: new Date().toISOString(),
|
|
lastActive: new Date().toISOString()
|
|
});
|
|
}
|
|
return this.playerBases.get(userId);
|
|
}
|
|
|
|
getPlayerBase(userId) {
|
|
return this.playerBases.get(userId) || this.initializePlayerBase(userId);
|
|
}
|
|
|
|
addExperience(userId, amount) {
|
|
const base = this.getPlayerBase(userId);
|
|
base.experience += amount;
|
|
|
|
let levelsGained = 0;
|
|
const oldLevel = base.level;
|
|
|
|
// Check for level up
|
|
while (base.experience >= base.experienceToNext) {
|
|
base.experience -= base.experienceToNext;
|
|
base.level += 1;
|
|
levelsGained++;
|
|
|
|
// Update experience needed for next level
|
|
base.experienceToNext = this.getExperienceNeeded(base.level);
|
|
|
|
// Apply level up bonuses
|
|
this.applyLevelUpBonuses(base);
|
|
}
|
|
|
|
base.lastActive = new Date().toISOString();
|
|
|
|
return {
|
|
experienceGained: amount,
|
|
levelsGained,
|
|
newLevel: base.level,
|
|
experienceToNext: base.experienceToNext
|
|
};
|
|
}
|
|
|
|
getExperienceNeeded(level) {
|
|
// Exponential experience curve
|
|
return Math.floor(500 * Math.pow(1.5, level - 1));
|
|
}
|
|
|
|
applyLevelUpBonuses(base) {
|
|
// Increase base stats on level up
|
|
base.maxPower += 20;
|
|
base.maxStorage += 200;
|
|
base.maxDefense += 5;
|
|
base.maxCrewCapacity += 2;
|
|
|
|
// Restore to max values
|
|
base.power = Math.min(base.power, base.maxPower);
|
|
base.storage = Math.min(base.storage, base.maxStorage);
|
|
base.defense = Math.min(base.defense, base.maxDefense);
|
|
base.crewCapacity = Math.min(base.crewCapacity, base.maxCrewCapacity);
|
|
}
|
|
|
|
buildRoom(userId, roomType, level = 1) {
|
|
const base = this.getPlayerBase(userId);
|
|
const roomTemplate = this.roomTypes[roomType];
|
|
|
|
if (!roomTemplate) {
|
|
throw new Error('Invalid room type');
|
|
}
|
|
|
|
// Check requirements
|
|
if (base.level < roomTemplate.requiredLevel) {
|
|
throw new Error('Base level too low');
|
|
}
|
|
|
|
// Check if room already exists
|
|
const existingRoom = base.rooms.find(room => room.type === roomType);
|
|
if (existingRoom) {
|
|
throw new Error('Room already exists');
|
|
}
|
|
|
|
// Check power capacity
|
|
const totalPowerCost = this.calculateTotalPowerCost(base);
|
|
if (totalPowerCost + roomTemplate.powerCost > base.maxPower) {
|
|
throw new Error('Insufficient power capacity');
|
|
}
|
|
|
|
// Add room
|
|
const room = {
|
|
type: roomType,
|
|
level,
|
|
builtAt: new Date().toISOString(),
|
|
lastUpgraded: null
|
|
};
|
|
|
|
base.rooms.push(room);
|
|
this.updateBaseStats(base);
|
|
|
|
return {
|
|
success: true,
|
|
room,
|
|
newStats: {
|
|
power: base.power,
|
|
maxPower: base.maxPower,
|
|
storage: base.storage,
|
|
maxStorage: base.maxStorage,
|
|
defense: base.defense,
|
|
maxDefense: base.maxDefense
|
|
}
|
|
};
|
|
}
|
|
|
|
upgradeRoom(userId, roomType) {
|
|
const base = this.getPlayerBase(userId);
|
|
const roomTemplate = this.roomTypes[roomType];
|
|
const room = base.rooms.find(room => room.type === roomType);
|
|
|
|
if (!room) {
|
|
throw new Error('Room not found');
|
|
}
|
|
|
|
if (room.level >= roomTemplate.maxLevel) {
|
|
throw new Error('Room already at max level');
|
|
}
|
|
|
|
// Upgrade room
|
|
room.level += 1;
|
|
room.lastUpgraded = new Date().toISOString();
|
|
|
|
this.updateBaseStats(base);
|
|
|
|
return {
|
|
success: true,
|
|
room,
|
|
newStats: {
|
|
power: base.power,
|
|
maxPower: base.maxPower,
|
|
storage: base.storage,
|
|
maxStorage: base.maxStorage,
|
|
defense: base.defense,
|
|
maxDefense: base.maxDefense
|
|
}
|
|
};
|
|
}
|
|
|
|
demolishRoom(userId, roomType) {
|
|
const base = this.getPlayerBase(userId);
|
|
const roomIndex = base.rooms.findIndex(room => room.type === roomType);
|
|
|
|
if (roomIndex === -1) {
|
|
throw new Error('Room not found');
|
|
}
|
|
|
|
const room = base.rooms[roomIndex];
|
|
|
|
// Cannot demolish command center
|
|
if (room.type === 'command_center') {
|
|
throw new Error('Cannot demolish command center');
|
|
}
|
|
|
|
// Remove room
|
|
base.rooms.splice(roomIndex, 1);
|
|
this.updateBaseStats(base);
|
|
|
|
return {
|
|
success: true,
|
|
demolishedRoom: room
|
|
};
|
|
}
|
|
|
|
addDecoration(userId, decorationType) {
|
|
const base = this.getPlayerBase(userId);
|
|
const decorationTemplate = this.decorationTypes[decorationType];
|
|
|
|
if (!decorationTemplate) {
|
|
throw new Error('Invalid decoration type');
|
|
}
|
|
|
|
const decoration = {
|
|
type: decorationType,
|
|
placedAt: new Date().toISOString()
|
|
};
|
|
|
|
base.decorations.push(decoration);
|
|
|
|
return {
|
|
success: true,
|
|
decoration
|
|
};
|
|
}
|
|
|
|
removeDecoration(userId, decorationIndex) {
|
|
const base = this.getPlayerBase(userId);
|
|
|
|
if (decorationIndex < 0 || decorationIndex >= base.decorations.length) {
|
|
throw new Error('Invalid decoration index');
|
|
}
|
|
|
|
const removedDecoration = base.decorations.splice(decorationIndex, 1)[0];
|
|
|
|
return {
|
|
success: true,
|
|
removedDecoration
|
|
};
|
|
}
|
|
|
|
calculateTotalPowerCost(base) {
|
|
let totalCost = 0;
|
|
|
|
for (const room of base.rooms) {
|
|
const roomTemplate = this.roomTypes[room.type];
|
|
totalCost += roomTemplate.powerCost * room.level;
|
|
}
|
|
|
|
return totalCost;
|
|
}
|
|
|
|
updateBaseStats(base) {
|
|
// Reset to base values
|
|
base.power = 100;
|
|
base.maxPower = 100;
|
|
base.storage = 1000;
|
|
base.maxStorage = 1000;
|
|
base.defense = 10;
|
|
base.maxDefense = 10;
|
|
base.crewCapacity = 5;
|
|
base.maxCrewCapacity = 5;
|
|
base.researchBonus = 0;
|
|
base.craftingBonus = 0;
|
|
|
|
// Apply room bonuses
|
|
for (const room of base.rooms) {
|
|
const roomTemplate = this.roomTypes[room.type];
|
|
|
|
base.maxPower += roomTemplate.powerCost * room.level;
|
|
base.maxStorage += roomTemplate.storageBonus * room.level;
|
|
base.maxDefense += roomTemplate.powerCost * room.level * 0.5; // Defense rooms give defense bonus
|
|
|
|
if (room.type === 'barracks') {
|
|
base.maxCrewCapacity += 5 * room.level;
|
|
}
|
|
|
|
if (room.type === 'laboratory') {
|
|
base.researchBonus += 10 * room.level;
|
|
}
|
|
|
|
if (room.type === 'workshop') {
|
|
base.craftingBonus += 5 * room.level;
|
|
}
|
|
}
|
|
|
|
// Apply level bonuses
|
|
base.maxPower += 20 * (base.level - 1);
|
|
base.maxStorage += 200 * (base.level - 1);
|
|
base.maxDefense += 5 * (base.level - 1);
|
|
base.maxCrewCapacity += 2 * (base.level - 1);
|
|
}
|
|
|
|
getBaseStatistics(userId) {
|
|
const base = this.getPlayerBase(userId);
|
|
|
|
return {
|
|
name: base.name,
|
|
level: base.level,
|
|
experience: base.experience,
|
|
experienceToNext: base.experienceToNext,
|
|
rooms: base.rooms.length,
|
|
decorations: base.decorations.length,
|
|
power: base.power,
|
|
maxPower: base.maxPower,
|
|
storage: base.storage,
|
|
maxStorage: base.maxStorage,
|
|
defense: base.defense,
|
|
maxDefense: base.maxDefense,
|
|
crewCapacity: base.crewCapacity,
|
|
maxCrewCapacity: base.maxCrewCapacity,
|
|
researchBonus: base.researchBonus,
|
|
craftingBonus: base.craftingBonus,
|
|
totalPowerCost: this.calculateTotalPowerCost(base),
|
|
powerEfficiency: base.maxPower > 0 ? (base.power / base.maxPower) * 100 : 0,
|
|
storageEfficiency: base.maxStorage > 0 ? (base.storage / base.maxStorage) * 100 : 0
|
|
};
|
|
}
|
|
|
|
getAvailableRooms(userId) {
|
|
const base = this.getPlayerBase(userId);
|
|
const availableRooms = [];
|
|
|
|
for (const [roomType, template] of Object.entries(this.roomTypes)) {
|
|
// Skip if already built
|
|
if (base.rooms.find(room => room.type === roomType)) {
|
|
continue;
|
|
}
|
|
|
|
// Check level requirement
|
|
if (base.level >= template.requiredLevel) {
|
|
availableRooms.push({
|
|
type: roomType,
|
|
...template,
|
|
canAfford: true // In a real implementation, check player credits
|
|
});
|
|
}
|
|
}
|
|
|
|
return availableRooms;
|
|
}
|
|
|
|
getRoomUpgrades(userId) {
|
|
const base = this.getPlayerBase(userId);
|
|
const upgradableRooms = [];
|
|
|
|
for (const room of base.rooms) {
|
|
const template = this.roomTypes[room.type];
|
|
|
|
if (room.level < template.maxLevel) {
|
|
upgradableRooms.push({
|
|
type: room.type,
|
|
currentLevel: room.level,
|
|
maxLevel: template.maxLevel,
|
|
nextLevelCost: template.buildCost * room.level,
|
|
template
|
|
});
|
|
}
|
|
}
|
|
|
|
return upgradableRooms;
|
|
}
|
|
}
|
|
|
|
module.exports = BaseSystem;
|