189 lines
7.1 KiB
JavaScript
189 lines
7.1 KiB
JavaScript
export class JobSystem {
|
||
constructor(game) {
|
||
this.game = game;
|
||
this.jobs = [];
|
||
this.activeJob = null;
|
||
this.jobTimer = 0;
|
||
this.completedToday = 0;
|
||
this.lastDay = 0;
|
||
}
|
||
|
||
init() {
|
||
this.generateJobs();
|
||
}
|
||
|
||
generateJobs() {
|
||
const allJobs = [
|
||
{ id: 'wash_car', name: 'Помыть машину', pay: 40, duration: 15, desc: 'Помыть машину на парковке', location: 'parking', skill: 'trading' },
|
||
{ id: 'unload', name: 'Разгрузить товар', pay: 80, duration: 25, desc: 'Разгрузить товар у магазина', location: 'shop', skill: 'survival' },
|
||
{ id: 'flyers', name: 'Раздать листовки', pay: 30, duration: 12, desc: 'Раздавать листовки на дороге', location: 'road', skill: 'begging' },
|
||
{ id: 'sweep', name: 'Подмести двор', pay: 25, duration: 10, desc: 'Навести порядок у церкви', location: 'church', skill: 'survival' },
|
||
{ id: 'help_granny', name: 'Помочь с сумками', pay: 35, duration: 15, desc: 'Донести сумки в парк', location: 'park', skill: 'survival' },
|
||
{ id: 'collect_trash', name: 'Собрать мусор', pay: 20, duration: 8, desc: 'Собрать мусор в парке', location: 'park', skill: 'scavenging' },
|
||
{ id: 'guard_stuff', name: 'Посторожить багаж', pay: 45, duration: 20, desc: 'Посторожить вещи на остановке', location: 'busstop', skill: 'survival' },
|
||
];
|
||
|
||
// Выбираем 3 случайных
|
||
const shuffled = allJobs.sort(() => Math.random() - 0.5);
|
||
this.jobs = shuffled.slice(0, 3).map(j => ({ ...j, available: true }));
|
||
}
|
||
|
||
getLocationPosition(loc) {
|
||
const positions = {
|
||
parking: { x: 40, z: -55 },
|
||
shop: { x: 20, z: -20 },
|
||
road: { x: 0, z: 0 },
|
||
church: { x: 70, z: 50 },
|
||
park: { x: -30, z: 40 },
|
||
busstop: { x: -38, z: -10 },
|
||
};
|
||
return positions[loc] || { x: 0, z: 0 };
|
||
}
|
||
|
||
getLocationName(loc) {
|
||
const names = {
|
||
parking: 'парковке',
|
||
shop: 'магазину',
|
||
road: 'дороге',
|
||
church: 'церкви',
|
||
park: 'парку',
|
||
busstop: 'остановке',
|
||
};
|
||
return names[loc] || 'месту';
|
||
}
|
||
|
||
showJobBoard() {
|
||
if (this.activeJob) {
|
||
this.game.notify('Вы уже выполняете работу!');
|
||
return;
|
||
}
|
||
|
||
const availableJobs = this.jobs.filter(j => j.available);
|
||
if (availableJobs.length === 0) {
|
||
this.game.ui.showDialog('Доска объявлений', 'Сейчас нет доступных подработок. Загляните завтра.', [
|
||
'Ладно'
|
||
], () => this.game.ui.hideDialog());
|
||
return;
|
||
}
|
||
|
||
const payMod = this.game.reputation.getJobPayModifier();
|
||
const choices = availableJobs.map(j => {
|
||
const pay = Math.floor(j.pay * payMod);
|
||
return `${j.name} — ${pay}₽ (${j.desc})`;
|
||
});
|
||
choices.push('Уйти');
|
||
|
||
this.game.sound.playDialogOpen();
|
||
this.game.ui.showDialog('Доска объявлений', 'Доступные подработки:', choices, (index) => {
|
||
if (index < availableJobs.length) {
|
||
this.startJob(availableJobs[index]);
|
||
}
|
||
this.game.ui.hideDialog();
|
||
});
|
||
}
|
||
|
||
startJob(job) {
|
||
this.activeJob = { ...job };
|
||
this.jobTimer = 0;
|
||
this.activeJob.isWorking = false;
|
||
this.activeJob.targetPos = this.getLocationPosition(job.location);
|
||
const locName = this.getLocationName(job.location);
|
||
this.game.notify(`Работа принята: ${job.name}. Идите к ${locName}!`);
|
||
}
|
||
|
||
update(dt) {
|
||
// Обновляем список работ при новом дне
|
||
if (this.game.gameDay !== this.lastDay) {
|
||
this.lastDay = this.game.gameDay;
|
||
this.completedToday = 0;
|
||
this.generateJobs();
|
||
}
|
||
|
||
if (!this.activeJob) return;
|
||
|
||
const player = this.game.player;
|
||
const pos = this.activeJob.targetPos;
|
||
const dx = player.position.x - pos.x;
|
||
const dz = player.position.z - pos.z;
|
||
const dist = Math.sqrt(dx * dx + dz * dz);
|
||
|
||
if (dist < 10) {
|
||
if (!this.activeJob.isWorking) {
|
||
this.activeJob.isWorking = true;
|
||
this.game.notify('Вы на месте. Работаете... (оставайтесь рядом)');
|
||
}
|
||
this.jobTimer += dt;
|
||
|
||
const progress = Math.min(1, this.jobTimer / this.activeJob.duration);
|
||
this.game.ui.updateJobProgress(progress, this.activeJob.name);
|
||
|
||
if (this.jobTimer >= this.activeJob.duration) {
|
||
this.completeJob();
|
||
}
|
||
} else if (this.activeJob.isWorking) {
|
||
this.activeJob.isWorking = false;
|
||
this.game.notify('Вы ушли с рабочего места! Вернитесь!', 'bad');
|
||
}
|
||
}
|
||
|
||
completeJob() {
|
||
const payMod = this.game.reputation.getJobPayModifier();
|
||
const pay = Math.floor(this.activeJob.pay * payMod);
|
||
|
||
this.game.player.stats.money += pay;
|
||
this.game.player.stats.mood = Math.min(100, this.game.player.stats.mood + 8);
|
||
this.game.sound.playCoin();
|
||
this.game.reputation.change(3);
|
||
this.game.skills.addXP(this.activeJob.skill || 'survival', 3);
|
||
this.game.notify(`Работа выполнена! +${pay}₽, +8 Настроение`, 'good');
|
||
this.game.questSystem.onEvent('complete_job');
|
||
this.game.totalJobsCompleted++;
|
||
|
||
// Ачивки
|
||
this.game.achievements.check('first_job_done');
|
||
if (this.game.totalJobsCompleted >= 10) {
|
||
this.game.achievements.check('jobs_10');
|
||
}
|
||
|
||
const idx = this.jobs.findIndex(j => j.id === this.activeJob.id);
|
||
if (idx >= 0) this.jobs[idx].available = false;
|
||
|
||
this.activeJob = null;
|
||
this.jobTimer = 0;
|
||
this.completedToday++;
|
||
this.game.ui.hideJobProgress();
|
||
}
|
||
|
||
cancelJob() {
|
||
if (this.activeJob) {
|
||
this.game.notify('Работа отменена.', 'bad');
|
||
this.game.reputation.change(-2);
|
||
this.activeJob = null;
|
||
this.jobTimer = 0;
|
||
this.game.ui.hideJobProgress();
|
||
}
|
||
}
|
||
|
||
getSaveData() {
|
||
return {
|
||
completedToday: this.completedToday,
|
||
lastDay: this.lastDay
|
||
};
|
||
}
|
||
|
||
loadSaveData(data) {
|
||
if (data) {
|
||
this.completedToday = data.completedToday || 0;
|
||
this.lastDay = data.lastDay || 0;
|
||
}
|
||
}
|
||
|
||
reset() {
|
||
this.activeJob = null;
|
||
this.jobTimer = 0;
|
||
this.completedToday = 0;
|
||
this.lastDay = 0;
|
||
this.generateJobs();
|
||
}
|
||
}
|