164 lines
8.1 KiB
JavaScript
164 lines
8.1 KiB
JavaScript
export class Achievements {
|
||
constructor(game) {
|
||
this.game = game;
|
||
this.unlocked = new Set();
|
||
|
||
this.list = [
|
||
// Выживание
|
||
{ id: 'first_day', title: 'Новая жизнь', desc: 'Прожить 1 день', icon: '🌅', category: 'survival' },
|
||
{ id: 'week_survivor', title: 'Недельный марафон', desc: 'Прожить 7 дней', icon: '📅', category: 'survival' },
|
||
{ id: 'month_survivor', title: 'Бывалый', desc: 'Прожить 28 дней', icon: '🏆', category: 'survival' },
|
||
{ id: 'winter_survivor', title: 'Морозоустойчивый', desc: 'Пережить зиму', icon: '❄️', category: 'survival' },
|
||
{ id: 'full_year', title: 'Годовщина', desc: 'Прожить все 4 сезона', icon: '🎊', category: 'survival' },
|
||
{ id: 'near_death', title: 'На грани', desc: 'Выжить при здоровье < 5', icon: '💀', category: 'survival' },
|
||
{ id: 'well_fed', title: 'Сытый', desc: 'Держать сытость на 100 в течение 5 минут', icon: '🍽️', category: 'survival' },
|
||
|
||
// Социальные
|
||
{ id: 'first_talk', title: 'Общительный', desc: 'Поговорить с 3 NPC', icon: '💬', category: 'social' },
|
||
{ id: 'all_npcs', title: 'Душа компании', desc: 'Поговорить со всеми NPC', icon: '🤝', category: 'social' },
|
||
{ id: 'best_friend', title: 'Лучший друг', desc: 'Приручить пса', icon: '🐕', category: 'social' },
|
||
{ id: 'respected', title: 'Уважаемый', desc: 'Достичь репутации 50+', icon: '⭐', category: 'social' },
|
||
{ id: 'beloved', title: 'Свой человек', desc: 'Достичь репутации 80+', icon: '💛', category: 'social' },
|
||
|
||
// Экономика
|
||
{ id: 'first_money', title: 'Первый рубль', desc: 'Заработать первые деньги', icon: '💰', category: 'economy' },
|
||
{ id: 'rich_100', title: 'Копилка', desc: 'Накопить 100₽', icon: '🪙', category: 'economy' },
|
||
{ id: 'rich_500', title: 'Состояние', desc: 'Накопить 500₽', icon: '💎', category: 'economy' },
|
||
{ id: 'rich_1000', title: 'Богач', desc: 'Накопить 1000₽', icon: '👑', category: 'economy' },
|
||
{ id: 'first_job_done', title: 'Трудяга', desc: 'Выполнить первую подработку', icon: '🔧', category: 'economy' },
|
||
{ id: 'jobs_10', title: 'Работяга', desc: 'Выполнить 10 подработок', icon: '🏗️', category: 'economy' },
|
||
{ id: 'bottle_king', title: 'Король бутылок', desc: 'Сдать 20 бутылок', icon: '🍾', category: 'economy' },
|
||
|
||
// Боевые
|
||
{ id: 'first_fight', title: 'Боец', desc: 'Отбиться от врага', icon: '👊', category: 'combat' },
|
||
{ id: 'fighter_5', title: 'Бывалый боец', desc: 'Победить 5 врагов', icon: '🥊', category: 'combat' },
|
||
{ id: 'survivor_combat', title: 'Несгибаемый', desc: 'Отбиться от 3 врагов подряд', icon: '🛡️', category: 'combat' },
|
||
|
||
// Исследование
|
||
{ id: 'explorer', title: 'Исследователь', desc: 'Посетить все локации', icon: '🗺️', category: 'explore' },
|
||
{ id: 'crafter', title: 'Мастер', desc: 'Создать 5 предметов', icon: '🔨', category: 'explore' },
|
||
{ id: 'skill_max', title: 'Эксперт', desc: 'Достичь 5 уровня любого навыка', icon: '📚', category: 'explore' },
|
||
{ id: 'fully_equipped', title: 'Экипированный', desc: 'Заполнить все слоты экипировки', icon: '🛡️', category: 'explore' },
|
||
{ id: 'shelter_built', title: 'Свой угол', desc: 'Построить укрытие', icon: '🏠', category: 'explore' },
|
||
];
|
||
}
|
||
|
||
// Вызывается из разных мест кода
|
||
check(id) {
|
||
if (this.unlocked.has(id)) return;
|
||
|
||
const achievement = this.list.find(a => a.id === id);
|
||
if (!achievement) return;
|
||
|
||
this.unlocked.add(id);
|
||
this.showPopup(achievement);
|
||
this.game.sound.playQuestComplete();
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 5);
|
||
}
|
||
|
||
// Проверки, вызываемые каждый тик
|
||
updateChecks() {
|
||
const player = this.game.player;
|
||
const day = this.game.gameDay;
|
||
|
||
// Выживание
|
||
if (day >= 2) this.check('first_day');
|
||
if (day >= 8) this.check('week_survivor');
|
||
if (day >= 29) this.check('month_survivor');
|
||
|
||
// Здоровье
|
||
if (player.stats.health > 0 && player.stats.health < 5) {
|
||
this.check('near_death');
|
||
}
|
||
|
||
// Деньги
|
||
if (player.stats.money >= 1) this.check('first_money');
|
||
if (player.stats.money >= 100) this.check('rich_100');
|
||
if (player.stats.money >= 500) this.check('rich_500');
|
||
if (player.stats.money >= 1000) this.check('rich_1000');
|
||
|
||
// Репутация
|
||
if (this.game.reputation.value >= 50) this.check('respected');
|
||
if (this.game.reputation.value >= 80) this.check('beloved');
|
||
|
||
// Пёс
|
||
if (this.game.dog.adopted) this.check('best_friend');
|
||
|
||
// Навыки
|
||
const skills = this.game.skills.skills;
|
||
for (const skill of Object.values(skills)) {
|
||
if (skill.level >= 5) {
|
||
this.check('skill_max');
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Экипировка
|
||
if (this.game.equipment.getFilledSlots() === 4) {
|
||
this.check('fully_equipped');
|
||
}
|
||
}
|
||
|
||
showPopup(achievement) {
|
||
let popup = document.getElementById('achievement-popup');
|
||
if (!popup) {
|
||
popup = document.createElement('div');
|
||
popup.id = 'achievement-popup';
|
||
popup.style.cssText = `
|
||
position: fixed;
|
||
top: -80px;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
background: linear-gradient(135deg, rgba(20,20,40,0.95), rgba(40,30,60,0.95));
|
||
border: 2px solid #ffd740;
|
||
border-radius: 8px;
|
||
padding: 12px 24px;
|
||
z-index: 60;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
transition: top 0.5s ease;
|
||
backdrop-filter: blur(8px);
|
||
box-shadow: 0 4px 20px rgba(255,215,64,0.3);
|
||
pointer-events: none;
|
||
`;
|
||
document.body.appendChild(popup);
|
||
}
|
||
|
||
popup.innerHTML = `
|
||
<span style="font-size:2rem;">${achievement.icon}</span>
|
||
<div>
|
||
<div style="font-size:0.7rem;color:#ffd740;font-weight:700;text-transform:uppercase;letter-spacing:0.1em;">Достижение разблокировано!</div>
|
||
<div style="font-size:1rem;font-weight:700;color:#fff;margin-top:2px;">${achievement.title}</div>
|
||
<div style="font-size:0.75rem;color:#aaa;">${achievement.desc}</div>
|
||
</div>
|
||
`;
|
||
|
||
// Анимация
|
||
setTimeout(() => popup.style.top = '20px', 50);
|
||
setTimeout(() => popup.style.top = '-80px', 4000);
|
||
}
|
||
|
||
getByCategory(category) {
|
||
return this.list.filter(a => a.category === category);
|
||
}
|
||
|
||
getProgress() {
|
||
return { unlocked: this.unlocked.size, total: this.list.length };
|
||
}
|
||
|
||
getSaveData() {
|
||
return { unlocked: [...this.unlocked] };
|
||
}
|
||
|
||
loadSaveData(data) {
|
||
if (data && data.unlocked) {
|
||
this.unlocked = new Set(data.unlocked);
|
||
}
|
||
}
|
||
|
||
reset() {
|
||
this.unlocked = new Set();
|
||
}
|
||
}
|