Files
Hommie_RPG_Game/js/game/Events.js
Maxim Dolgolyov fb5f09212b Initial commit: 3D Hommie RPG game
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 01:04:09 +03:00

231 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
}
}