Game-Server/Galaxy-Strike-Online-main/Client/js/systems/IdleSystem.js

379 lines
14 KiB
JavaScript

/**
* Galaxy Strike Online - Idle System
* Manages offline progression and idle mechanics
*/
class IdleSystem {
constructor(gameEngine) {
this.game = gameEngine;
// Idle settings
this.maxOfflineTime = 7 * 24 * 60 * 60 * 1000; // 7 days in milliseconds
this.lastActiveTime = Date.now();
this.accumulatedTime = 0; // Track time for resource generation
// Idle production rates (online rates)
this.productionRates = {
credits: 0.1, // 1 credit every 10 seconds (0.1 per second)
experience: 0, // no auto experience - only from dungeons
energy: 1/300 // 1 energy every 5 minutes (1/300 per second)
};
// Offline rates (different from online rates)
this.offlineProductionRates = {
credits: 1/60, // 1 credit every 1 minute (1/60 per second)
experience: 0, // no experience offline - only from dungeons
energy: 1/300 // 1 energy every 5 minutes (same as online)
};
// Offline rewards
this.offlineRewards = {
credits: 0,
experience: 0,
energy: 0,
items: []
};
// Idle bonuses
this.bonuses = {
premium: 1.0,
guild: 1.0,
research: 1.0
};
// Idle achievements
this.achievements = {
totalOfflineTime: 0,
maxOfflineSession: 0,
totalIdleCredits: 0,
totalIdleExperience: 0
};
}
async initialize() {
// Calculate offline progress if returning
this.calculateOfflineProgress();
}
calculateOfflineProgress(offlineTime = null) {
const currentTime = Date.now();
const actualOfflineTime = offlineTime || (currentTime - this.lastActiveTime);
// Cap offline time to maximum
const cappedOfflineTime = Math.min(actualOfflineTime, this.maxOfflineTime);
if (cappedOfflineTime < 60000) { // Less than 1 minute
return;
}
// Calculate production
const totalBonus = this.getTotalBonus();
const productionSeconds = cappedOfflineTime / 1000;
this.offlineRewards = {
credits: Math.floor(this.productionRates.credits * productionSeconds * totalBonus),
experience: Math.floor(this.productionRates.experience * productionSeconds * totalBonus),
energy: Math.min(
this.game.systems.player.attributes.maxEnergy,
Math.floor(this.productionRates.energy * productionSeconds)
),
items: this.generateIdleItems(cappedOfflineTime)
};
// Update achievements
this.achievements.totalOfflineTime += cappedOfflineTime;
this.achievements.maxOfflineSession = Math.max(this.achievements.maxOfflineSession, cappedOfflineTime);
this.achievements.totalIdleCredits += this.offlineRewards.credits;
this.achievements.totalIdleExperience += this.offlineRewards.experience;
// Show offline rewards notification
this.showOfflineRewards(cappedOfflineTime);
}
getTotalBonus() {
return this.bonuses.premium * this.bonuses.guild * this.bonuses.research;
}
generateIdleItems(offlineTime) {
const items = [];
const hours = offlineTime / (1000 * 60 * 60);
// Chance to find items based on offline time
const itemChance = Math.min(0.5, hours * 0.05);
if (Math.random() < itemChance) {
const itemCount = Math.floor(hours / 2) + 1;
for (let i = 0; i < itemCount; i++) {
const rarity = this.getRandomItemRarity();
const item = this.game.systems.inventory.generateItem('consumable', rarity);
items.push(item);
}
}
return items;
}
getRandomItemRarity() {
const roll = Math.random();
if (roll < 0.05) return 'legendary';
if (roll < 0.15) return 'epic';
if (roll < 0.35) return 'rare';
if (roll < 0.65) return 'uncommon';
return 'common';
}
showOfflineRewards(offlineTime) {
const timeString = this.game.formatTime(offlineTime);
this.game.showNotification(
`Welcome back! You were offline for ${timeString}`,
'info',
5000
);
// Format rewards message
let rewardsMessage = 'Offline Rewards:\n';
if (this.offlineRewards.credits > 0) {
rewardsMessage += `+${this.game.formatNumber(this.offlineRewards.credits)} credits\n`;
}
if (this.offlineRewards.experience > 0) {
rewardsMessage += `+${this.game.formatNumber(this.offlineRewards.experience)} XP\n`;
}
if (this.offlineRewards.energy > 0) {
rewardsMessage += `+${this.game.formatNumber(this.offlineRewards.energy)} energy\n`;
}
if (this.offlineRewards.items.length > 0) {
rewardsMessage += `+${this.offlineRewards.items.length} items\n`;
}
this.game.showNotification(rewardsMessage, 'success', 5000);
}
claimOfflineRewards() {
// In multiplayer mode, use server communication
if (window.smartSaveManager?.isMultiplayer) {
this.game.showNotification('Claiming offline rewards from server...', 'info', 2000);
// Send request to server
if (window.game && window.game.socket) {
window.game.socket.emit('claimOfflineRewards', {});
} else {
this.game.showNotification('Not connected to server', 'error', 3000);
}
return;
}
// Singleplayer mode - use local logic
if (this.offlineRewards.credits === 0 &&
this.offlineRewards.experience === 0 &&
this.offlineRewards.items.length === 0) {
this.game.showNotification('No offline rewards to claim', 'info', 3000);
return;
}
// Give rewards
if (this.offlineRewards.credits > 0) {
this.game.systems.economy.addCredits(this.offlineRewards.credits, 'offline');
}
if (this.offlineRewards.experience > 0) {
this.game.systems.player.addExperience(this.offlineRewards.experience);
}
if (this.offlineRewards.energy > 0) {
this.game.systems.player.restoreEnergy(this.offlineRewards.energy);
}
// Add items to inventory
if (this.offlineRewards.items.length > 0) {
const inventory = this.game.systems.inventory;
this.offlineRewards.items.forEach(item => {
inventory.addItem(item);
});
}
// Reset offline rewards
this.offlineRewards = {
credits: 0,
experience: 0,
energy: 0,
items: []
};
this.game.showNotification('Offline rewards claimed!', 'success', 3000);
}
// Active idle production
update(deltaTime) {
if (this.game.state.paused) return;
// Use real computer time delta
const seconds = deltaTime / 1000;
const totalBonus = this.getTotalBonus();
// Only add resources once per second, not every frame
this.accumulatedTime += seconds;
if (this.accumulatedTime >= 1.0) {
// Calculate active production
const activeCredits = Math.floor(this.productionRates.credits * totalBonus);
const activeExperience = Math.floor(this.productionRates.experience * totalBonus);
// const activeEnergy = this.productionRates.energy * totalBonus * 0.1; // Energy is handled differently
// Add resources
if (activeCredits > 0) {
this.game.systems.economy.addCredits(activeCredits, 'idle');
}
if (activeExperience > 0) {
this.game.systems.player.addExperience(activeExperience);
}
// Regenerate energy
this.game.systems.player.restoreEnergy(this.productionRates.energy);
// Reset accumulated time, keeping any remainder
this.accumulatedTime -= 1.0;
// Debugging: Log when resources are added
// console.debug(`[IDLE] Added ${activeCredits} credits and ${activeExperience} XP. Accumulated time: ${this.accumulatedTime.toFixed(2)}s`);
}
// Update last active time for offline calculations
this.lastActiveTime = Date.now();
}
// Upgrade production rates
upgradeProduction(type) {
const upgradeCosts = {
credits: 100,
experience: 150,
energy: 80
};
const cost = upgradeCosts[type];
if (!cost || this.game.systems.economy.credits < cost) {
return false;
}
this.game.systems.economy.removeCredits(cost);
switch (type) {
case 'credits':
this.productionRates.credits += 2;
break;
case 'experience':
this.productionRates.experience += 1;
break;
case 'energy':
this.productionRates.energy += 0.2;
break;
}
this.game.showNotification(`Production upgraded: ${type}!`, 'success', 3000);
return true;
}
// Bonus management
setBonus(type, value) {
if (this.bonuses[type] !== undefined) {
this.bonuses[type] = value;
this.game.showNotification(`${type} bonus set to ${value}x`, 'info', 3000);
}
}
// Achievement checking
checkAchievements() {
const achievements = [
{
id: 'idle_warrior',
name: 'Idle Warrior',
description: 'Earn 1,000,000 credits from idle',
condition: () => this.achievements.totalIdleCredits >= 1000000,
reward: { gems: 50, experience: 1000 }
},
{
id: 'time_master',
name: 'Time Master',
description: 'Accumulate 24 hours of offline time',
condition: () => this.achievements.totalOfflineTime >= 24 * 60 * 60 * 1000,
reward: { gems: 25, experience: 500 }
},
{
id: 'marathon_idle',
name: 'Marathon Idle',
description: 'Be offline for more than 12 hours at once',
condition: () => this.achievements.maxOfflineSession >= 12 * 60 * 60 * 1000,
reward: { gems: 100, experience: 2000 }
}
];
achievements.forEach(achievement => {
if (achievement.condition()) {
this.unlockAchievement(achievement);
}
});
}
unlockAchievement(achievement) {
this.game.showNotification(`Achievement Unlocked: ${achievement.name}!`, 'success', 5000);
this.game.showNotification(achievement.description, 'info', 3000);
// Give rewards
if (achievement.reward.gems) {
this.game.systems.economy.addGems(achievement.reward.gems, 'achievement');
}
if (achievement.reward.experience) {
this.game.systems.player.addExperience(achievement.reward.experience);
}
}
// UI updates
updateUI() {
const offlineTimeElement = document.getElementById('offlineTime');
const offlineResourcesElement = document.getElementById('offlineResources');
const claimOfflineBtn = document.getElementById('claimOfflineBtn');
if (offlineTimeElement) {
const totalRewards = this.offlineRewards.credits +
this.offlineRewards.experience +
(this.offlineRewards.items.length * 100);
offlineTimeElement.textContent = totalRewards > 0 ? 'Available' : 'None';
}
if (offlineResourcesElement) {
const totalRewards = this.offlineRewards.credits +
this.offlineRewards.experience +
(this.offlineRewards.items.length * 100);
offlineResourcesElement.textContent = this.game.formatNumber(totalRewards);
}
if (claimOfflineBtn) {
const hasRewards = this.offlineRewards.credits > 0 ||
this.offlineRewards.experience > 0 ||
this.offlineRewards.items.length > 0;
claimOfflineBtn.disabled = !hasRewards;
}
}
// Save/Load
save() {
return {
lastActiveTime: this.lastActiveTime,
productionRates: this.productionRates,
bonuses: this.bonuses,
achievements: this.achievements,
offlineRewards: this.offlineRewards
};
}
load(data) {
if (data.lastActiveTime) this.lastActiveTime = data.lastActiveTime;
if (data.productionRates) this.productionRates = { ...this.productionRates, ...data.productionRates };
if (data.bonuses) this.bonuses = { ...this.bonuses, ...data.bonuses };
if (data.achievements) this.achievements = { ...this.achievements, ...data.achievements };
if (data.offlineRewards) this.offlineRewards = data.offlineRewards;
}
}