231 lines
10 KiB
JavaScript
231 lines
10 KiB
JavaScript
export class EventSystem {
|
||
constructor(game) {
|
||
this.game = game;
|
||
this.timer = 30 + Math.random() * 60;
|
||
this.eventCooldown = 0;
|
||
this.activeEvent = null;
|
||
}
|
||
|
||
update(dt) {
|
||
if (this.eventCooldown > 0) {
|
||
this.eventCooldown -= dt;
|
||
return;
|
||
}
|
||
|
||
this.timer -= dt;
|
||
if (this.timer <= 0) {
|
||
this.triggerRandom();
|
||
this.timer = 40 + Math.random() * 80;
|
||
}
|
||
}
|
||
|
||
triggerRandom() {
|
||
const hour = this.game.gameTime / 60;
|
||
const isNight = hour < 6 || hour > 21;
|
||
const player = this.game.player;
|
||
|
||
const events = [
|
||
{ weight: 10, fn: () => this.eventFoundWallet() },
|
||
{ weight: 8, fn: () => this.eventStrayDogFood() },
|
||
{ weight: 7, fn: () => this.eventOldFriend() },
|
||
{ weight: 6, fn: () => this.eventRainOfCoins() },
|
||
{ weight: 8, fn: () => this.eventKindStranger() },
|
||
{ weight: 5, fn: () => this.eventFoodTruck() },
|
||
{ weight: isNight ? 10 : 3, fn: () => this.eventColdWind() },
|
||
{ weight: isNight ? 8 : 2, fn: () => this.eventScaryNoise() },
|
||
{ weight: player.stats.mood < 30 ? 10 : 3, fn: () => this.eventMemory() },
|
||
{ weight: 4, fn: () => this.eventStreetMusician() },
|
||
{ weight: player.stats.health < 40 ? 8 : 2, fn: () => this.eventAmbulance() },
|
||
{ weight: 5, fn: () => this.eventNewspaper() },
|
||
{ weight: 6, fn: () => this.eventPigeons() },
|
||
{ weight: isNight ? 2 : 6, fn: () => this.eventSunshine() },
|
||
];
|
||
|
||
const totalWeight = events.reduce((s, e) => s + e.weight, 0);
|
||
let roll = Math.random() * totalWeight;
|
||
|
||
for (const event of events) {
|
||
roll -= event.weight;
|
||
if (roll <= 0) {
|
||
event.fn();
|
||
this.eventCooldown = 20;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
eventFoundWallet() {
|
||
const amount = 20 + Math.floor(Math.random() * 80);
|
||
this.game.ui.showDialog('Находка', `Вы нашли на земле кошелёк! Внутри ${amount}₽. Что делать?`, [
|
||
`Забрать деньги (+${amount}₽)`,
|
||
'Оставить на месте (может кто-то вернётся)',
|
||
], (i) => {
|
||
if (i === 0) {
|
||
this.game.player.stats.money += amount;
|
||
this.game.sound.playCoin();
|
||
this.game.notify(`+${amount}₽`, 'good');
|
||
this.game.player.stats.mood = Math.max(0, this.game.player.stats.mood - 2);
|
||
this.game.reputation.change(-5);
|
||
} else {
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 8);
|
||
this.game.notify('+8 Настроение. Вы поступили честно.', 'good');
|
||
this.game.reputation.change(10);
|
||
}
|
||
this.game.ui.hideDialog();
|
||
});
|
||
}
|
||
|
||
eventStrayDogFood() {
|
||
if (this.game.dog && this.game.dog.adopted) return;
|
||
const hasBread = this.game.inventory.getCount('bread') > 0;
|
||
const choices = hasBread
|
||
? ['Покормить хлебом', 'Прогнать']
|
||
: ['Погладить', 'Прогнать'];
|
||
|
||
this.game.ui.showDialog('Событие', 'Бездомный пёс подошёл к вам и смотрит голодными глазами...', choices, (i) => {
|
||
if (i === 0) {
|
||
if (hasBread) {
|
||
this.game.inventory.removeItem('bread', 1);
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 12);
|
||
this.game.notify('Пёс виляет хвостом! +12 Настроение', 'good');
|
||
// Приручить если ещё не приручен
|
||
if (this.game.dog && !this.game.dog.adopted) {
|
||
this.game.dog.adopt();
|
||
this.game.notify('Пёс решил остаться с вами!', 'good');
|
||
this.game.questSystem.onEvent('adopt_dog');
|
||
}
|
||
} else {
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 5);
|
||
this.game.notify('Пёс благодарно лизнул руку.', 'good');
|
||
}
|
||
} else {
|
||
this.game.notify('Пёс убежал с поджатым хвостом...');
|
||
this.game.player.stats.mood = Math.max(0, this.game.player.stats.mood - 3);
|
||
}
|
||
this.game.ui.hideDialog();
|
||
});
|
||
}
|
||
|
||
eventOldFriend() {
|
||
this.game.ui.showDialog('Событие', 'Вы встретили старого знакомого. Он узнал вас и выглядит смущённым...', [
|
||
'"Привет, давно не виделись..."',
|
||
'Отвернуться',
|
||
], (i) => {
|
||
if (i === 0) {
|
||
const roll = Math.random();
|
||
if (roll < 0.5) {
|
||
const amount = 50 + Math.floor(Math.random() * 100);
|
||
this.game.player.stats.money += amount;
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 10);
|
||
this.game.sound.playCoin();
|
||
this.game.notify(`Он дал вам ${amount}₽ и пожелал удачи.`, 'good');
|
||
} else {
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 5);
|
||
this.game.notify('Он обнял вас и пожелал сил. +5 Настроение', 'good');
|
||
}
|
||
} else {
|
||
this.game.player.stats.mood = Math.max(0, this.game.player.stats.mood - 5);
|
||
this.game.notify('Вы отвернулись. Стало грустно.', 'bad');
|
||
}
|
||
this.game.ui.hideDialog();
|
||
});
|
||
}
|
||
|
||
eventRainOfCoins() {
|
||
const amount = 5 + Math.floor(Math.random() * 15);
|
||
this.game.player.stats.money += amount;
|
||
this.game.sound.playCoin();
|
||
this.game.notify(`Кто-то обронил мелочь! +${amount}₽`, 'good');
|
||
}
|
||
|
||
eventKindStranger() {
|
||
this.game.ui.showDialog('Событие', 'К вам подошёл человек в дорогом пальто. "Я из благотворительной организации. Хотите горячий обед?"', [
|
||
'Да, спасибо!',
|
||
'Нет, обойдусь',
|
||
], (i) => {
|
||
if (i === 0) {
|
||
this.game.player.stats.hunger = Math.min(100, this.game.player.stats.hunger + 50);
|
||
this.game.player.stats.warmth = Math.min(100, this.game.player.stats.warmth + 15);
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 15);
|
||
this.game.sound.playEat();
|
||
this.game.notify('Вы сытно поели! +50 Сытость, +15 Тепло, +15 Настроение', 'good');
|
||
}
|
||
this.game.ui.hideDialog();
|
||
});
|
||
}
|
||
|
||
eventFoodTruck() {
|
||
this.game.notify('Фудтрак раздаёт бесплатную еду рядом!');
|
||
this.game.inventory.addItem('can', 1);
|
||
this.game.inventory.addItem('tea', 1);
|
||
this.game.sound.playPickup();
|
||
this.game.notify('Получено: Консервы, Чай', 'good');
|
||
}
|
||
|
||
eventColdWind() {
|
||
this.game.player.stats.warmth = Math.max(0, this.game.player.stats.warmth - 15);
|
||
this.game.player.stats.mood = Math.max(0, this.game.player.stats.mood - 5);
|
||
this.game.notify('Порыв ледяного ветра! -15 Тепло', 'bad');
|
||
}
|
||
|
||
eventScaryNoise() {
|
||
this.game.player.stats.mood = Math.max(0, this.game.player.stats.mood - 8);
|
||
this.game.notify('Странный шум в темноте... -8 Настроение', 'bad');
|
||
this.game.sound.playHurt();
|
||
}
|
||
|
||
eventMemory() {
|
||
const memories = [
|
||
'Вы вспомнили детство... тёплый дом, мамин суп...',
|
||
'В голове всплыло лицо старого друга... Где он сейчас?',
|
||
'Вы нашли в кармане старую фотографию. Сердце защемило.',
|
||
'Знакомая мелодия из окна... Вы когда-то танцевали под неё.',
|
||
];
|
||
const text = memories[Math.floor(Math.random() * memories.length)];
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 3);
|
||
this.game.notify(text);
|
||
}
|
||
|
||
eventStreetMusician() {
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 10);
|
||
this.game.notify('Уличный музыкант играет красивую мелодию. +10 Настроение', 'good');
|
||
}
|
||
|
||
eventAmbulance() {
|
||
this.game.ui.showDialog('Событие', 'Медработник-волонтёр заметил вас. "Давайте я вас осмотрю?"', [
|
||
'Да, пожалуйста',
|
||
'Не нужно',
|
||
], (i) => {
|
||
if (i === 0) {
|
||
this.game.player.stats.health = Math.min(100, this.game.player.stats.health + 30);
|
||
this.game.inventory.addItem('bandage', 1);
|
||
this.game.notify('+30 Здоровье. Получен: Бинт', 'good');
|
||
}
|
||
this.game.ui.hideDialog();
|
||
});
|
||
}
|
||
|
||
eventNewspaper() {
|
||
this.game.inventory.addItem('newspaper', 1);
|
||
this.game.sound.playPickup();
|
||
this.game.notify('Ветер принёс газету. Можно почитать.', 'good');
|
||
}
|
||
|
||
eventPigeons() {
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 3);
|
||
this.game.notify('Стая голубей приземлилась рядом. Маленькая радость.');
|
||
}
|
||
|
||
eventSunshine() {
|
||
this.game.player.stats.warmth = Math.min(100, this.game.player.stats.warmth + 8);
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 5);
|
||
this.game.notify('Тёплый луч солнца согрел лицо. +8 Тепло', 'good');
|
||
}
|
||
|
||
reset() {
|
||
this.timer = 30 + Math.random() * 60;
|
||
this.eventCooldown = 0;
|
||
this.activeEvent = null;
|
||
}
|
||
}
|