API/Client-Server/js/systems/SkillSystem.js

597 lines
21 KiB
JavaScript

/**
* Galaxy Strike Online - Skill System
* Manages skills, progression, and specialization
*/
class SkillSystem {
constructor(gameEngine) {
this.game = gameEngine;
// Skill categories
this.categories = {
combat: 'Combat',
science: 'Science',
crafting: 'Crafting'
};
// Skill definitions
this.skills = {
combat: {
weapons_mastery: {
name: 'Weapons Mastery',
description: 'Increases weapon damage and critical chance',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
attack: 2,
criticalChance: 0.01
},
icon: 'fa-sword',
unlocked: true
},
shield_techniques: {
name: 'Shield Techniques',
description: 'Improves defense and energy efficiency',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
defense: 2,
maxEnergy: 5
},
icon: 'fa-shield-alt',
unlocked: true
},
piloting: {
name: 'Piloting',
description: 'Enhances speed and evasion',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
speed: 2,
criticalChance: 0.005
},
icon: 'fa-rocket',
unlocked: true
},
tactical_analysis: {
name: 'Tactical Analysis',
description: 'Reveals enemy weaknesses and improves accuracy',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
criticalDamage: 0.05,
attack: 1
},
icon: 'fa-brain',
unlocked: false,
requiredLevel: 5
}
},
science: {
engineering: {
name: 'Engineering',
description: 'Technical skills for ship components and machinery',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
craftingBonus: 0.08,
shipStats: 0.03
},
icon: 'fa-wrench',
unlocked: true
},
energy_manipulation: {
name: 'Energy Manipulation',
description: 'Better energy control and regeneration',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
maxEnergy: 10,
energyRegeneration: 0.1
},
icon: 'fa-bolt',
unlocked: true
},
alien_technology: {
name: 'Alien Technology',
description: 'Understanding and using alien artifacts',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
findRarity: 0.05,
itemValue: 0.1
},
icon: 'fa-atom',
unlocked: false,
requiredLevel: 3
},
quantum_physics: {
name: 'Quantum Physics',
description: 'Advanced quantum mechanics for better equipment',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
criticalDamage: 0.1,
attack: 3
},
icon: 'fa-microscope',
unlocked: false,
requiredLevel: 8
},
bio_engineering: {
name: 'Bio-Engineering',
description: 'Biological enhancements and healing',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
maxHealth: 15,
healthRegeneration: 0.05
},
icon: 'fa-dna',
unlocked: false,
requiredLevel: 6
}
},
crafting: {
crafting: {
name: 'General Crafting',
description: 'Basic crafting skills for all items',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
craftingBonus: 0.05
},
icon: 'fa-hammer',
unlocked: true
},
weapon_crafting: {
name: 'Weapon Crafting',
description: 'Create and upgrade weapons',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
craftingBonus: 0.1,
weaponStats: 0.05
},
icon: 'fa-hammer',
unlocked: true
},
armor_forging: {
name: 'Armor Forging',
description: 'Forge protective armor and shields',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
craftingBonus: 0.1,
armorStats: 0.05
},
icon: 'fa-anvil',
unlocked: true
},
resource_extraction: {
name: 'Resource Extraction',
description: 'Better resource gathering and efficiency',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
resourceBonus: 0.15,
findResources: 0.1
},
icon: 'fa-gem',
unlocked: false,
requiredLevel: 4
},
engineering: {
name: 'Engineering',
description: 'Advanced ship modifications and systems',
maxLevel: 10,
currentLevel: 0,
experience: 0,
experienceToNext: 100,
effects: {
shipUpgrades: 0.2,
systemEfficiency: 0.1
},
icon: 'fa-cogs',
unlocked: false,
requiredLevel: 7
}
}
};
// Skill experience rates
this.experienceRates = {
combat: 1.0,
science: 0.8,
crafting: 0.6
};
// Active buffs from skills
this.activeBuffs = {};
}
async initialize() {
}
// Skill management
addSkillExperience(category, skillId, amount) {
const skill = this.skills[category]?.[skillId];
if (!skill || skill.currentLevel >= skill.maxLevel) {
return false;
}
skill.experience += amount;
// Check for level up
while (skill.experience >= skill.experienceToNext && skill.currentLevel < skill.maxLevel) {
this.levelUpSkill(category, skillId);
}
this.applySkillEffects();
return true;
}
levelUpSkill(category, skillId) {
const skill = this.skills[category][skillId];
// Handle excess experience
const excessExperience = skill.experience - skill.experienceToNext;
skill.currentLevel++;
skill.experienceToNext = Math.floor(skill.experienceToNext * 1.5);
// Set experience to excess (minimum 0)
skill.experience = Math.max(0, excessExperience);
// Apply skill effects
this.applySkillEffects();
this.game.showNotification(`${skill.name} leveled up to ${skill.currentLevel}!`, 'success', 4000);
this.game.showNotification('Skill effects applied!', 'info', 3000);
}
upgradeSkill(category, skillId) {
const skill = this.skills[category]?.[skillId];
const player = this.game.systems.player;
if (!skill) {
this.game.showNotification('Skill not found', 'error', 3000);
return false;
}
if (!skill.unlocked) {
this.game.showNotification('Skill is locked', 'error', 3000);
return false;
}
if (skill.currentLevel >= skill.maxLevel) {
this.game.showNotification('Skill is at maximum level', 'warning', 3000);
return false;
}
if (player.stats.skillPoints < 1) {
this.game.showNotification('Not enough skill points', 'error', 3000);
return false;
}
// Use skill point and level up
player.stats.skillPoints--;
this.levelUpSkill(category, skillId);
// Update UI to refresh skill points display only if in multiplayer mode or game is actively running
const shouldUpdateUI = window.smartSaveManager?.isMultiplayer || this.game?.isRunning;
if (shouldUpdateUI) {
this.updateUI();
}
return true;
}
unlockSkill(category, skillId) {
const skill = this.skills[category]?.[skillId];
const player = this.game.systems.player;
if (!skill) {
this.game.showNotification('Skill not found', 'error', 3000);
return false;
}
if (skill.unlocked) {
this.game.showNotification('Skill is already unlocked', 'warning', 3000);
return false;
}
if (skill.requiredLevel && player.stats.level < skill.requiredLevel) {
this.game.showNotification(`Requires level ${skill.requiredLevel}`, 'error', 3000);
return false;
}
if (player.stats.skillPoints < 2) {
this.game.showNotification('Requires 2 skill points to unlock', 'error', 3000);
return false;
}
// Unlock skill
player.stats.skillPoints -= 2;
skill.unlocked = true;
skill.currentLevel = 1;
this.applySkillEffects();
// Update UI to refresh skill points display only if in multiplayer mode or game is actively running
const shouldUpdateUI = window.smartSaveManager?.isMultiplayer || this.game?.isRunning;
if (shouldUpdateUI) {
this.updateUI();
}
this.game.showNotification(`${skill.name} unlocked!`, 'success', 4000);
return true;
}
applySkillEffects() {
const player = this.game.systems.player;
// Reset to base stats first
this.resetToBaseStats();
// Apply all skill effects
Object.values(this.skills).forEach(skill => {
if (skill.level > 0) {
const skillData = this.skillData[skill.id];
if (skillData && skillData.effects) {
Object.entries(skillData.effects).forEach(([effect, value]) => {
const totalEffect = value * skill.level;
switch (effect) {
case 'attack':
player.attributes.attack += totalEffect;
break;
case 'defense':
player.attributes.defense += totalEffect;
break;
case 'speed':
player.attributes.speed += totalEffect;
break;
case 'maxHealth':
player.attributes.maxHealth += totalEffect;
break;
case 'maxEnergy':
player.attributes.maxEnergy += totalEffect;
break;
case 'criticalChance':
player.attributes.criticalChance += totalEffect;
break;
case 'criticalDamage':
player.attributes.criticalDamage += totalEffect;
break;
case 'energyRegeneration':
case 'healthRegeneration':
case 'craftingBonus':
case 'weaponStats':
case 'armorStats':
case 'resourceBonus':
case 'shipUpgrades':
case 'systemEfficiency':
case 'findRarity':
case 'itemValue':
case 'findResources':
// Store these for other systems to use
if (!this.activeBuffs[effect]) {
this.activeBuffs[effect] = 0;
}
this.activeBuffs[effect] += totalEffect;
break;
}
});
}
}
});
player.updateUI();
}
resetToBaseStats() {
const player = this.game.systems.player;
// Reset to base values (would need to store base stats separately)
// For now, we'll use initial values
const baseStats = {
attack: 10 + (player.stats.level - 1) * 2,
defense: 5 + (player.stats.level - 1) * 1,
speed: 10,
maxHealth: 100 + (player.stats.level - 1) * 10,
maxEnergy: 100 + (player.stats.level - 1) * 5,
criticalChance: 0.05,
criticalDamage: 1.5
};
Object.assign(player.attributes, baseStats);
this.activeBuffs = {};
}
// Skill experience from actions
awardCombatExperience(amount) {
this.addSkillExperience('combat', 'weapons_mastery', amount);
this.addSkillExperience('combat', 'tactical_analysis', amount * 0.5);
}
awardScienceExperience(amount) {
this.addSkillExperience('science', 'energy_manipulation', amount);
this.addSkillExperience('science', 'alien_technology', amount * 0.3);
}
awardCraftingExperience(amount) {
this.addSkillExperience('crafting', 'weapon_crafting', amount);
this.addSkillExperience('crafting', 'armor_forging', amount * 0.5);
}
// Skill checks
getSkillLevel(category, skillId) {
return this.skills[category]?.[skillId]?.currentLevel || 0;
}
hasSkill(category, skillId, minimumLevel = 1) {
const skill = this.skills[category]?.[skillId];
return skill && skill.unlocked && skill.currentLevel >= minimumLevel;
}
getSkillBonus(effect) {
return this.activeBuffs[effect] || 0;
}
// UI updates
updateUI() {
this.updateSkillsGrid();
this.updateSkillPointsDisplay();
}
updateSkillsGrid() {
const skillsGridElement = document.getElementById('skillsGrid');
if (!skillsGridElement) return;
const activeCategory = document.querySelector('.skill-cat-btn.active')?.dataset.category || 'combat';
const skills = this.skills[activeCategory] || {};
skillsGridElement.innerHTML = '';
Object.entries(skills).forEach(([skillId, skill]) => {
const skillElement = document.createElement('div');
skillElement.className = `skill-item ${!skill.unlocked ? 'locked' : ''}`;
const progressPercent = skill.currentLevel > 0 ?
(skill.experience / skill.experienceToNext) * 100 : 0;
// Use texture manager for icon fallback
const iconClass = this.game.systems.textureManager ?
this.game.systems.textureManager.getIcon(skill.icon) :
(skill.icon || 'fa-question');
skillElement.innerHTML = `
<div class="skill-header">
<div class="skill-icon">
<i class="fas ${iconClass}"></i>
</div>
<div class="skill-info">
<div class="skill-name">${skill.name}</div>
<div class="skill-level">Lv. ${skill.currentLevel}/${skill.maxLevel}</div>
</div>
</div>
<div class="skill-description">${skill.description}</div>
${skill.currentLevel > 0 && skill.currentLevel < skill.maxLevel ? `
<div class="skill-progress">
<div class="progress-bar">
<div class="progress-fill" style="width: ${progressPercent}%"></div>
</div>
<span>${skill.experience}/${skill.experienceToNext} XP</span>
</div>
` : skill.currentLevel >= skill.maxLevel ? `
<div class="skill-max-level">
<span>MAX LEVEL</span>
</div>
` : ''}
<div class="skill-actions">
${!skill.unlocked ? `
<button class="btn btn-warning" onclick="if(window.game && window.game.systems) window.game.systems.skillSystem.unlockSkill('${activeCategory}', '${skillId}')">
Unlock (2 Points)
</button>
` : skill.currentLevel < skill.maxLevel ? `
<button class="btn btn-primary" onclick="if(window.game && window.game.systems) window.game.systems.skillSystem.upgradeSkill('${activeCategory}', '${skillId}')">
Upgrade (1 Point)
</button>
` : `
<span class="max-level">MAX LEVEL</span>
`}
</div>
${skill.requiredLevel && !skill.unlocked ? `
<div class="skill-requirement">Requires Level ${skill.requiredLevel}</div>
` : ''}
`;
skillsGridElement.appendChild(skillElement);
});
}
updateSkillPointsDisplay() {
const player = this.game.systems.player;
// Update skill points display if element exists
const skillPointsElements = document.querySelectorAll('.skill-points');
skillPointsElements.forEach(element => {
element.textContent = `Skill Points: ${player.stats.skillPoints}`;
});
}
// Save/Load
save() {
return {
skills: this.skills,
activeBuffs: this.activeBuffs
};
}
load(data) {
if (data.skills) {
// Deep merge to preserve structure
for (const [category, skills] of Object.entries(data.skills)) {
if (this.skills[category]) {
for (const [skillId, skillData] of Object.entries(skills)) {
if (this.skills[category][skillId]) {
Object.assign(this.skills[category][skillId], skillData);
}
}
}
}
}
if (data.activeBuffs) {
this.activeBuffs = data.activeBuffs;
}
this.applySkillEffects();
}
reset() {
this.skillPoints = 0;
this.unlockedSkills = [];
this.activeBuffs = [];
// Skills are already defined in constructor, just reset levels
Object.values(this.skills).forEach(category => {
Object.values(category).forEach(skill => {
skill.currentLevel = 0;
skill.experience = 0;
});
});
}
clear() {
this.reset();
}
}