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/SkillSystem.js
2026-01-24 21:39:56 -04:00

398 lines
12 KiB
JavaScript

/**
* Galaxy Strike Online - Server Skill System
* Manages skill progression, experience, and abilities
*/
class SkillSystem {
constructor() {
this.skills = new Map();
this.playerSkills = new Map(); // userId -> skill data
this.initializeSkills();
}
initializeSkills() {
// Combat skills
this.addSkill('weapons_mastery', {
name: 'Weapons Mastery',
description: 'Increases damage and accuracy with all weapons',
category: 'combat',
maxLevel: 100,
experiencePerLevel: 1000,
bonuses: {
damage: 2, // +2% per level
accuracy: 1, // +1% per level
criticalChance: 0.5 // +0.5% per level
}
});
this.addSkill('defense_training', {
name: 'Defense Training',
description: 'Improves damage reduction and resistance',
category: 'combat',
maxLevel: 100,
experiencePerLevel: 1000,
bonuses: {
damageReduction: 1.5, // +1.5% per level
resistance: 1, // +1% per level
health: 5 // +5 HP per level
}
});
this.addSkill('speed_reflexes', {
name: 'Speed & Reflexes',
description: 'Enhances movement speed and reaction time',
category: 'combat',
maxLevel: 100,
experiencePerLevel: 1000,
bonuses: {
speed: 2, // +2% per level
dodgeChance: 0.8, // +0.8% per level
initiative: 1 // +1 per level
}
});
// Crafting skills
this.addSkill('weapons_crafting', {
name: 'Weapons Crafting',
description: 'Ability to craft and improve weapons',
category: 'crafting',
maxLevel: 100,
experiencePerLevel: 800,
bonuses: {
craftingSpeed: 2, // +2% per level
craftingSuccess: 1, // +1% per level
rareChance: 0.5 // +0.5% per level
}
});
this.addSkill('armor_crafting', {
name: 'Armor Crafting',
description: 'Ability to craft and improve armor',
category: 'crafting',
maxLevel: 100,
experiencePerLevel: 800,
bonuses: {
craftingSpeed: 2, // +2% per level
durabilityBonus: 3, // +3% per level
rareChance: 0.5 // +0.5% per level
}
});
// Social skills
this.addSkill('leadership', {
name: 'Leadership',
description: 'Improves team performance and guild bonuses',
category: 'social',
maxLevel: 100,
experiencePerLevel: 1200,
bonuses: {
teamDamage: 1, // +1% per level
guildBonus: 2, // +2% per level
maxPartySize: 0.1 // +0.1 per level (rounded)
}
});
this.addSkill('negotiation', {
name: 'Negotiation',
description: 'Better prices from shops and traders',
category: 'social',
maxLevel: 100,
experiencePerLevel: 1000,
bonuses: {
shopDiscount: 0.5, // -0.5% per level
tradeBonus: 1, // +1% per level
reputationGain: 2 // +2% per level
}
});
// Exploration skills
this.addSkill('navigation', {
name: 'Navigation',
description: 'Faster travel and better map awareness',
category: 'exploration',
maxLevel: 100,
experiencePerLevel: 900,
bonuses: {
travelSpeed: 3, // +3% per level
discoveryRange: 2, // +2% per level
mapAccuracy: 1 // +1% per level
}
});
this.addSkill('scavenging', {
name: 'Scavenging',
description: 'Find more materials and rare items',
category: 'exploration',
maxLevel: 100,
experiencePerLevel: 900,
bonuses: {
materialFind: 2, // +2% per level
rareFind: 1, // +1% per level
salvageBonus: 3 // +3% per level
}
});
}
addSkill(id, skill) {
this.skills.set(id, {
id,
...skill,
createdAt: new Date().toISOString()
});
}
getSkill(id) {
return this.skills.get(id);
}
getAllSkills() {
return Array.from(this.skills.values());
}
getSkillsByCategory(category) {
return Array.from(this.skills.values()).filter(skill => skill.category === category);
}
initializePlayerData(userId) {
if (!this.playerSkills.has(userId)) {
this.playerSkills.set(userId, {
skillPoints: 0,
totalExperience: 0,
skills: new Map(),
unlockedSkills: new Set(['weapons_mastery', 'defense_training']), // Start with basic skills
skillHistory: []
});
// Initialize unlocked skills at level 1
const playerData = this.playerSkills.get(userId);
for (const skillId of playerData.unlockedSkills) {
playerData.skills.set(skillId, {
level: 1,
experience: 0,
totalExperience: 0,
unlockedAt: new Date().toISOString()
});
}
}
return this.playerSkills.get(userId);
}
getPlayerData(userId) {
return this.playerSkills.get(userId) || this.initializePlayerData(userId);
}
addExperience(userId, skillId, amount) {
const skill = this.getSkill(skillId);
if (!skill) {
throw new Error('Skill not found');
}
const playerData = this.getPlayerData(userId);
// Check if skill is unlocked
if (!playerData.unlockedSkills.has(skillId)) {
throw new Error('Skill not unlocked');
}
const playerSkill = playerData.skills.get(skillId);
if (!playerSkill) {
throw new Error('Skill data not found');
}
// Add experience
playerSkill.experience += amount;
playerSkill.totalExperience += amount;
playerData.totalExperience += amount;
let levelsGained = 0;
let oldLevel = playerSkill.level;
// Check for level up
while (playerSkill.experience >= skill.experiencePerLevel && playerSkill.level < skill.maxLevel) {
playerSkill.experience -= skill.experiencePerLevel;
playerSkill.level += 1;
levelsGained++;
}
// Record in history
playerData.skillHistory.push({
skillId,
experienceGained: amount,
levelsGained,
newLevel: playerSkill.level,
timestamp: new Date().toISOString()
});
// Keep only last 100 skill records
if (playerData.skillHistory.length > 100) {
playerData.skillHistory = playerData.skillHistory.slice(-100);
}
return {
success: true,
experienceGained: amount,
levelsGained,
newLevel: playerSkill.level,
oldLevel,
experienceToNext: playerSkill.level < skill.maxLevel ? skill.experiencePerLevel - playerSkill.experience : 0
};
}
unlockSkill(userId, skillId) {
const skill = this.getSkill(skillId);
if (!skill) {
throw new Error('Skill not found');
}
const playerData = this.getPlayerData(userId);
if (playerData.unlockedSkills.has(skillId)) {
throw new Error('Skill already unlocked');
}
// Add to unlocked skills
playerData.unlockedSkills.add(skillId);
// Initialize at level 1
playerData.skills.set(skillId, {
level: 1,
experience: 0,
totalExperience: 0,
unlockedAt: new Date().toISOString()
});
return {
success: true,
skillId,
skillName: skill.name,
category: skill.category
};
}
getPlayerSkills(userId) {
const playerData = this.getPlayerData(userId);
const skills = [];
for (const skillId of playerData.unlockedSkills) {
const skill = this.getSkill(skillId);
const playerSkill = playerData.skills.get(skillId);
skills.push({
...skill,
level: playerSkill.level,
experience: playerSkill.experience,
totalExperience: playerSkill.totalExperience,
experienceToNext: playerSkill.level < skill.maxLevel ? skill.experiencePerLevel - playerSkill.experience : 0,
isMaxLevel: playerSkill.level >= skill.maxLevel,
unlockedAt: playerSkill.unlockedAt
});
}
return skills;
}
getSkillBonuses(userId) {
const playerData = this.getPlayerData(userId);
const totalBonuses = {
damage: 0,
accuracy: 0,
criticalChance: 0,
damageReduction: 0,
resistance: 0,
health: 0,
speed: 0,
dodgeChance: 0,
initiative: 0,
craftingSpeed: 0,
craftingSuccess: 0,
rareChance: 0,
durabilityBonus: 0,
teamDamage: 0,
guildBonus: 0,
maxPartySize: 0,
shopDiscount: 0,
tradeBonus: 0,
reputationGain: 0,
travelSpeed: 0,
discoveryRange: 0,
mapAccuracy: 0,
materialFind: 0,
rareFind: 0,
salvageBonus: 0
};
for (const skillId of playerData.unlockedSkills) {
const skill = this.getSkill(skillId);
const playerSkill = playerData.skills.get(skillId);
if (skill && playerSkill) {
for (const [bonus, value] of Object.entries(skill.bonuses)) {
totalBonuses[bonus] += value * playerSkill.level;
}
}
}
return totalBonuses;
}
awardSkillPoints(userId, amount) {
const playerData = this.getPlayerData(userId);
playerData.skillPoints += amount;
return {
success: true,
pointsAwarded: amount,
totalPoints: playerData.skillPoints
};
}
allocateSkillPoint(userId, skillId) {
const playerData = this.getPlayerData(userId);
if (playerData.skillPoints <= 0) {
throw new Error('No skill points available');
}
const skill = this.getSkill(skillId);
if (!skill) {
throw new Error('Skill not found');
}
const playerSkill = playerData.skills.get(skillId);
if (!playerSkill) {
throw new Error('Skill not unlocked');
}
if (playerSkill.level >= skill.maxLevel) {
throw new Error('Skill already at max level');
}
// Allocate point
playerSkill.level += 1;
playerData.skillPoints -= 1;
return {
success: true,
skillId,
newLevel: playerSkill.level,
remainingPoints: playerData.skillPoints
};
}
getSkillStatistics(userId) {
const playerData = this.getPlayerData(userId);
const skills = this.getPlayerSkills(userId);
return {
skillPoints: playerData.skillPoints,
totalExperience: playerData.totalExperience,
unlockedSkills: playerData.unlockedSkills.size,
maxLevelSkills: skills.filter(skill => skill.isMaxLevel).length,
averageLevel: skills.length > 0 ? Math.floor(skills.reduce((sum, skill) => sum + skill.level, 0) / skills.length) : 0,
recentHistory: playerData.skillHistory.slice(-10)
};
}
}
module.exports = SkillSystem;