Merge branch 'main' of https://git.campfiregg.ru/degradin/CampFirePlay
This commit is contained in:
commit
1d95c720b5
528
bot.js
528
bot.js
@ -18,7 +18,6 @@ const {
|
|||||||
PromocodeModel,
|
PromocodeModel,
|
||||||
EnterpriseModel,
|
EnterpriseModel,
|
||||||
WarehouseModel,
|
WarehouseModel,
|
||||||
TruckModel,
|
|
||||||
SaleModel,
|
SaleModel,
|
||||||
ResourcePriceModel,
|
ResourcePriceModel,
|
||||||
SkillsModel,
|
SkillsModel,
|
||||||
@ -373,13 +372,42 @@ bot.hears('🏗️ Предприятия', async (ctx) => {
|
|||||||
if (warehouse) {
|
if (warehouse) {
|
||||||
buttons.push([{ text: '🚛 Управление складом', callback_data: 'manage_warehouse' }]);
|
buttons.push([{ text: '🚛 Управление складом', callback_data: 'manage_warehouse' }]);
|
||||||
} else {
|
} else {
|
||||||
buttons.push([{ text: '🗄️ Построить склад', callback_data: 'open_warehouse' }]);
|
buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Возвращаем меню с кнопками
|
// Возвращаем меню с кнопками
|
||||||
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
|
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
|
||||||
});
|
});
|
||||||
|
bot.action('enterprise_menu', async (ctx) => {
|
||||||
|
const user = await UserModel.findByPk(ctx.from.id);
|
||||||
|
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
|
||||||
|
|
||||||
|
const enterprises = await EnterpriseModel.findAll({
|
||||||
|
where: { playerId: user.telegram_id }
|
||||||
|
});
|
||||||
|
|
||||||
|
let message = `🏗️ Меню предприятий:\n`;
|
||||||
|
message += `У вас: ${enterprises.length} предприятий.\n`;
|
||||||
|
message += warehouse
|
||||||
|
? `🗄️ Единый склад: Доступен (Ёмкость: ${warehouse.capacity} ед.)\n`
|
||||||
|
: `🗄️ Единый склад: Не построен.\n`;
|
||||||
|
|
||||||
|
const buttons = [];
|
||||||
|
|
||||||
|
// Добавляем кнопки для предприятий
|
||||||
|
buttons.push([{ text: '🏭 Мои предприятия', callback_data: 'my_enterprises' }]);
|
||||||
|
buttons.push([{ text: '🛠️ Построить предприятие', callback_data: 'build_enterprise' }]);
|
||||||
|
|
||||||
|
// Кнопка для управления или постройки склада
|
||||||
|
if (warehouse) {
|
||||||
|
buttons.push([{ text: '🚛 Управление складом', callback_data: 'manage_warehouse' }]);
|
||||||
|
} else {
|
||||||
|
buttons.push([{ text: '🗄️ Построить склад', callback_data: 'buy_warehouse' }]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Возвращаем меню с кнопками
|
||||||
|
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
|
||||||
|
});
|
||||||
|
|
||||||
// Функция для преобразования типа ресурса в эмодзи
|
// Функция для преобразования типа ресурса в эмодзи
|
||||||
function getEnterpriseEmoji(resourceType) {
|
function getEnterpriseEmoji(resourceType) {
|
||||||
@ -407,38 +435,20 @@ bot.action('my_enterprises', async (ctx) => {
|
|||||||
let message = `🏭 Мои предприятия:\n\n`;
|
let message = `🏭 Мои предприятия:\n\n`;
|
||||||
const buttons = [];
|
const buttons = [];
|
||||||
|
|
||||||
for (const enterprise of enterprises) {
|
enterprises.forEach((enterprise) => {
|
||||||
const { id, name, level, efficiency, currentResources, resourceType, warehouseCapacity } = enterprise;
|
message += `🔹 ${enterprise.name} (Уровень: ${enterprise.level}, Эффективность: ${enterprise.efficiency} ед/ч)\n`;
|
||||||
|
buttons.push([
|
||||||
|
{ text: `📈 Улучшить ${enterprise.name}`, callback_data: `upgrade_${enterprise.id}` },
|
||||||
|
{ text: `🚛 Управлять ${enterprise.name}`, callback_data: `manage_${enterprise.id}` }
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
message += `🔹 [ID: ${id}] ${getEnterpriseEmoji(resourceType)} ${name} st. ${level}\n └── ${currentResources}/${warehouseCapacity} [${efficiency} ед/ч]\n\n`;
|
buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
|
||||||
|
|
||||||
const truck = await TruckModel.findOne({ where: { enterpriseId: id } });
|
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
|
||||||
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
|
|
||||||
|
|
||||||
const enterpriseButtons = [
|
|
||||||
{ text: `ID: 📈 ${id}`, callback_data: `upgrade_${id}` },
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!truck) {
|
|
||||||
enterpriseButtons.push({ text: `🛻 ID: ${id}`, callback_data: `hire_truck_${id}` });
|
|
||||||
}else{
|
|
||||||
enterpriseButtons.push({ text: `🚛 ID: ${id}`, callback_data: `upgrade_truck_${id}` });
|
|
||||||
}
|
|
||||||
|
|
||||||
enterpriseButtons.push({ text: `💰 ID: ${id}`, callback_data: `sell_all_${id}` });
|
|
||||||
|
|
||||||
if (warehouse) {
|
|
||||||
enterpriseButtons.push({ text: `🔄 ID: ${id}`, callback_data: `transfer_from_${id}` });
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons.push(enterpriseButtons);
|
|
||||||
}
|
|
||||||
message += '\n\n[📈 - Улучшить]\n[🛻 - Нанять грузовик]\n 🚛 - Улучшить грузовик\n[💰 - Продать ресурсы с предприятия]\n[🔄 - Перевезти все на склад]'
|
|
||||||
buttons.push([{ text: '⬅️ Назад', callback_data: 'back_to_menu' }]);
|
|
||||||
|
|
||||||
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Построение предприятия
|
// Построение предприятия
|
||||||
bot.action('build_enterprise', async (ctx) => {
|
bot.action('build_enterprise', async (ctx) => {
|
||||||
try {
|
try {
|
||||||
@ -475,7 +485,7 @@ bot.action('build_enterprise', async (ctx) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message += '\nВыберите тип предприятия:';
|
message += '\nВыберите тип предприятия:';
|
||||||
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
|
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка в build_enterprise:', error);
|
console.error('Ошибка в build_enterprise:', error);
|
||||||
return await ctx.reply('Произошла ошибка при обработке запроса. Попробуйте снова.');
|
return await ctx.reply('Произошла ошибка при обработке запроса. Попробуйте снова.');
|
||||||
@ -508,7 +518,7 @@ bot.action(/build_(wood|coal|oil|metall|gold|diamond)/, async (ctx) => {
|
|||||||
// Снимаем деньги с баланса
|
// Снимаем деньги с баланса
|
||||||
await user.update({ money: user.money - price })
|
await user.update({ money: user.money - price })
|
||||||
|
|
||||||
return await ctx.reply(`Предприятие ${enterprise.name} (ID: ${enterprise.id}) построено!`)
|
return await ctx.editMessageText(`Предприятие ${enterprise.name} (ID: ${enterprise.id}) построено!`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Функция для расчета стоимости предприятия
|
// Функция для расчета стоимости предприятия
|
||||||
@ -555,7 +565,7 @@ bot.action('buy_warehouse', async (ctx) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
await user.update({ money: user.money - 500000 })
|
await user.update({ money: user.money - 500000 })
|
||||||
return await ctx.reply(`Вы успешно купили единый склад!`)
|
return await ctx.editMessageText(`Вы успешно купили единый склад!`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Управление складом
|
// Управление складом
|
||||||
@ -583,21 +593,45 @@ bot.action('manage_warehouse', async (ctx) => {
|
|||||||
[{ text: '🚚 Купить транспорт', callback_data: 'buy_truck' }]
|
[{ text: '🚚 Купить транспорт', callback_data: 'buy_truck' }]
|
||||||
];
|
];
|
||||||
|
|
||||||
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
|
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bot.action('warehouse_management', async (ctx) => {
|
||||||
|
let user = await UserModel.findByPk(ctx.from.id)
|
||||||
|
let warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } })
|
||||||
|
|
||||||
|
if (!warehouse) {
|
||||||
|
return await ctx.reply(`У вас нет склада. Вы можете купить его за 500,000 руб.`, Markup.inlineKeyboard([
|
||||||
|
[{ text: 'Купить склад', callback_data: 'buy_warehouse' }]
|
||||||
|
]).resize())
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = `
|
||||||
|
🏗️ Единый склад
|
||||||
|
Емкость: ${warehouse.capacity} ед.
|
||||||
|
Ресурсы:
|
||||||
|
🌲 Дерево: ${warehouse.wood || 0}
|
||||||
|
⛏️ Уголь: ${warehouse.coal || 0}
|
||||||
|
🛢️ Нефть: ${warehouse.oil || 0}
|
||||||
|
🛠️ Металл: ${warehouse.metall || 0}
|
||||||
|
💰 Золото: ${warehouse.gold || 0}
|
||||||
|
💎 Алмазы: ${warehouse.diamond || 0}
|
||||||
|
`
|
||||||
|
return await ctx.editMessageText(message, Markup.inlineKeyboard([
|
||||||
|
[{ text: 'Управление транспортом', callback_data: 'manage_trucks' }],
|
||||||
|
[{ text: 'Продать ресурсы', callback_data: 'sell_from_warehouse' }]
|
||||||
|
]).resize())
|
||||||
|
})
|
||||||
|
|
||||||
// Управление предприятием
|
// Управление предприятием
|
||||||
bot.action(/manage_(\d+)/, async (ctx) => {
|
bot.action(/manage_(\d+)/, async (ctx) => {
|
||||||
let enterpriseId = ctx.match[1]
|
let enterpriseId = ctx.match[1]
|
||||||
let enterprise = await EnterpriseModel.findByPk(enterpriseId)
|
let enterprise = await EnterpriseModel.findByPk(enterpriseId)
|
||||||
|
|
||||||
if (!enterprise) return await ctx.reply(`Предприятие не найдено.`)
|
if (!enterprise) return await ctx.reply(`Предприятие не найдено.`)
|
||||||
const buttons = [
|
|
||||||
[{ text: 'Продать ресурсы', callback_data: 'sell_resources' }],
|
|
||||||
[{ text: 'Нанять грузовик', callback_data: 'hire_truck' }]
|
|
||||||
];
|
|
||||||
// Логика управления предприятием (например, прокачка или продажа ресурсов)
|
// Логика управления предприятием (например, прокачка или продажа ресурсов)
|
||||||
return await ctx.reply(`Вы управляете предприятием ${enterprise.name} (ID: ${enterprise.id}).`, Markup.inlineKeyboard(buttons).resize())
|
return await ctx.editMessageText(`Вы управляете предприятием ${enterprise.name} (ID: ${enterprise.id}).`)
|
||||||
})
|
})
|
||||||
bot.action('transfer_resources', async (ctx) => {
|
bot.action('transfer_resources', async (ctx) => {
|
||||||
const user = await UserModel.findByPk(ctx.from.id);
|
const user = await UserModel.findByPk(ctx.from.id);
|
||||||
@ -619,47 +653,30 @@ bot.action('transfer_resources', async (ctx) => {
|
|||||||
return [{ text: `🏭 ${ent.name}`, callback_data: `transfer_from_${ent.id}` }];
|
return [{ text: `🏭 ${ent.name}`, callback_data: `transfer_from_${ent.id}` }];
|
||||||
});
|
});
|
||||||
|
|
||||||
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
|
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
|
||||||
});
|
});
|
||||||
|
|
||||||
// Перевозка с конкретного предприятия
|
// Перевозка с конкретного предприятия
|
||||||
bot.action(/transfer_from_(\d+)/, async (ctx) => {
|
bot.action(/transfer_from_(\d+)/, async (ctx) => {
|
||||||
const enterpriseId = ctx.match[1];
|
const enterpriseId = ctx.match[1];
|
||||||
|
const user = await UserModel.findByPk(ctx.from.id);
|
||||||
|
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
|
||||||
|
|
||||||
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
|
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
|
||||||
|
|
||||||
if (!enterprise) {
|
if (!enterprise) {
|
||||||
return await ctx.reply('Предприятие не найдено.');
|
return await ctx.editMessageText('Предприятие не найдено.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currentResources, resourceType, playerId } = enterprise;
|
let message = `🚛 Перевозка с предприятия ${enterprise.name}:\n`;
|
||||||
|
message += `🌲 Дерево: ${enterprise.wood || 0}\n`;
|
||||||
|
message += `⛏️ Уголь: ${enterprise.coal || 0}\n`;
|
||||||
|
message += `🛢️ Нефть: ${enterprise.oil || 0}\n`;
|
||||||
|
message += `⚙️ Металл: ${enterprise.metall || 0}\n`;
|
||||||
|
message += `🥇 Золото: ${enterprise.gold || 0}\n`;
|
||||||
|
message += `💎 Алмазы: ${enterprise.diamond || 0}\n`;
|
||||||
|
message += `\nВведите количество ресурса для перевозки.`;
|
||||||
|
|
||||||
if (currentResources === 0) {
|
return await ctx.reply(message);
|
||||||
return await ctx.reply('На предприятии нет ресурсов для перевода.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const warehouse = await WarehouseModel.findOne({ where: { playerId } });
|
|
||||||
|
|
||||||
if (!warehouse) {
|
|
||||||
return await ctx.reply('У вас нет склада для перевода ресурсов.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const freeCapacity = warehouse.capacity - getWarehouseUsedCapacity(warehouse);
|
|
||||||
const transferAmount = Math.min(currentResources, freeCapacity);
|
|
||||||
|
|
||||||
if (transferAmount === 0) {
|
|
||||||
return await ctx.reply('Склад заполнен. Перевод невозможен.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Перевод ресурсов
|
|
||||||
warehouse[resourceType] = (warehouse[resourceType] || 0) + transferAmount;
|
|
||||||
enterprise.currentResources -= transferAmount;
|
|
||||||
|
|
||||||
await warehouse.save();
|
|
||||||
await enterprise.save();
|
|
||||||
|
|
||||||
return await ctx.reply(
|
|
||||||
`Успешно переведено ${transferAmount} ед. ${resourceType} с предприятия в склад.`
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
bot.command('ent_rename', async (ctx) => {
|
bot.command('ent_rename', async (ctx) => {
|
||||||
@ -697,7 +714,7 @@ bot.action('upgrade_enterprise', async (ctx) => {
|
|||||||
buttons.push({ text: `Прокачать ${enterprise.name}`, callback_data: `upgrade_${enterprise.id}` })
|
buttons.push({ text: `Прокачать ${enterprise.name}`, callback_data: `upgrade_${enterprise.id}` })
|
||||||
})
|
})
|
||||||
|
|
||||||
return await ctx.reply(`Выберите предприятие для прокачки:`, Markup.inlineKeyboard(buttons).resize())
|
return await ctx.editMessageText(`Выберите предприятие для прокачки:`, Markup.inlineKeyboard(buttons).resize())
|
||||||
})
|
})
|
||||||
|
|
||||||
bot.action(/upgrade_(\d+)/, async (ctx) => {
|
bot.action(/upgrade_(\d+)/, async (ctx) => {
|
||||||
@ -721,229 +738,73 @@ bot.action(/upgrade_(\d+)/, async (ctx) => {
|
|||||||
// Снимаем деньги с баланса
|
// Снимаем деньги с баланса
|
||||||
await user.update({ balance: user.balance - upgradeCost })
|
await user.update({ balance: user.balance - upgradeCost })
|
||||||
|
|
||||||
return await ctx.reply(`Предприятие ${enterprise.name} успешно прокачано! Уровень: ${enterprise.level}, Производительность: ${enterprise.efficiency} ед/ч.`)
|
return await ctx.editMessageText(`Предприятие ${enterprise.name} успешно прокачано! Уровень: ${enterprise.level}, Производительность: ${enterprise.efficiency} ед/ч.`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Показ списка предприятий
|
|
||||||
bot.action('sell_resources', async (ctx) => {
|
bot.action('sell_resources', async (ctx) => {
|
||||||
const user = await UserModel.findByPk(ctx.from.id);
|
let user = await UserModel.findByPk(ctx.from.id)
|
||||||
const enterprises = await EnterpriseModel.findAll({
|
let enterprises = await EnterpriseModel.findAll({
|
||||||
where: { playerId: user.telegram_id }
|
where: {
|
||||||
});
|
playerId: user.telegram_id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if (enterprises.length === 0) {
|
if (enterprises.length === 0) return await ctx.reply(`У вас нет предприятий для продажи ресурсов.`)
|
||||||
return await ctx.reply('У вас нет предприятий для продажи ресурсов.');
|
|
||||||
|
let buttons = []
|
||||||
|
enterprises.forEach(enterprise => {
|
||||||
|
buttons.push({ text: `Продать ресурсы с ${enterprise.name}`, callback_data: `sell_${enterprise.id}` })
|
||||||
|
})
|
||||||
|
|
||||||
|
return await ctx.editMessageText(`Выберите предприятие для продажи ресурсов:`, Markup.inlineKeyboard(buttons).resize())
|
||||||
|
})
|
||||||
|
|
||||||
|
bot.action(/sell_(\d+)/, async (ctx) => {
|
||||||
|
let user = await UserModel.findByPk(ctx.from.id)
|
||||||
|
let enterpriseId = ctx.match[1]
|
||||||
|
let enterprise = await EnterpriseModel.findByPk(enterpriseId)
|
||||||
|
|
||||||
|
if (!enterprise) return await ctx.reply(`Предприятие не найдено.`)
|
||||||
|
|
||||||
|
// Логика продажи ресурсов с предприятия
|
||||||
|
const resourceQuantity = await ResourceModel.findOne({
|
||||||
|
where: { playerId: user.telegram_id, type: enterprise.resourceType }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!resourceQuantity || resourceQuantity.quantity <= 0) {
|
||||||
|
return await ctx.reply(`У вас нет ресурсов для продажи на предприятии ${enterprise.name}.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
let message = 'Список ваших предприятий и их ресурсы:\n\n';
|
const salePrice = getResourcePrice(enterprise.resourceType) // Цена за единицу ресурса
|
||||||
enterprises.forEach((enterprise, index) => {
|
const totalSale = salePrice * resourceQuantity.quantity
|
||||||
message += `${index + 1}. ${enterprise.name} (${enterprise.resourceType}): ${enterprise.currentResources} единиц\n`;
|
|
||||||
});
|
|
||||||
|
|
||||||
message += `\nЧтобы продать ресурсы, используйте команду:\n/sellres <номер_предприятия> <количество>\nПример: /sellres 1 50`;
|
// Обновляем количество ресурсов
|
||||||
return await ctx.reply(message);
|
await ResourceModel.update(
|
||||||
});
|
{ quantity: 0 }, // Все ресурсы продаются
|
||||||
|
{ where: { playerId: user.telegram_id, type: enterprise.resourceType } }
|
||||||
|
)
|
||||||
|
|
||||||
// Обработка продажи ресурсов
|
// Добавляем деньги пользователю
|
||||||
bot.command('sellres', async (ctx) => {
|
await user.update({ balance: user.balance + totalSale })
|
||||||
const user = await UserModel.findByPk(ctx.from.id);
|
|
||||||
const [enterpriseId, amountToSell] = ctx.message.text.split(' ').slice(1);
|
|
||||||
|
|
||||||
if (!enterpriseId || !amountToSell) {
|
return await ctx.reply(`Вы продали все ресурсы с ${enterprise.name} за ${totalSale} монет.`)
|
||||||
return await ctx.reply('Неверный формат команды. Пример: /sellres 1 50');
|
})
|
||||||
}
|
|
||||||
|
|
||||||
const enterprise = await EnterpriseModel.findByPk(enterpriseId, {
|
|
||||||
where: { playerId: user.telegram_id }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!enterprise) {
|
|
||||||
return await ctx.reply('Предприятие с таким id не найдено.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const amount = parseInt(amountToSell, 10);
|
|
||||||
|
|
||||||
if (isNaN(amount) || amount <= 0) {
|
|
||||||
return await ctx.reply('Укажите корректное количество для продажи.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enterprise.currentResources < amount) {
|
|
||||||
return await ctx.reply(
|
|
||||||
`На предприятии ${enterprise.name} недостаточно ресурсов. Доступно: ${enterprise.currentResources} единиц.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const resourcePrice = await ResourcePriceModel.findOne({
|
|
||||||
where: { resource: enterprise.resourceType }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!resourcePrice) {
|
|
||||||
return await ctx.reply('Не удалось получить цену ресурса.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalSale = Math.floor(amount * resourcePrice.price);
|
|
||||||
|
|
||||||
// Обновляем данные
|
|
||||||
enterprise.currentResources -= amount;
|
|
||||||
await enterprise.save();
|
|
||||||
|
|
||||||
user.money += totalSale;
|
|
||||||
await user.save();
|
|
||||||
|
|
||||||
// Инфляция: уменьшение цены ресурса
|
|
||||||
resourcePrice.price = Math.round(
|
|
||||||
resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * amount)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Гарантируем, что цена не упадет ниже 50% от базовой цены
|
|
||||||
resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
|
|
||||||
|
|
||||||
await resourcePrice.save();
|
|
||||||
|
|
||||||
return await ctx.reply(
|
|
||||||
`Вы продали ${amount} единиц ${enterprise.resourceType} с предприятия ${enterprise.name} за ${totalSale} монет.\nТекущая цена за единицу: ${resourcePrice.price.toFixed(0)} монет.`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Восстановление цен ресурсов
|
|
||||||
const recoverResourcePrices = async () => {
|
|
||||||
const resources = await ResourcePriceModel.findAll();
|
|
||||||
|
|
||||||
for (const resource of resources) {
|
|
||||||
if (resource.price < resource.basePrice) {
|
|
||||||
resource.price = Math.min(
|
|
||||||
resource.price + resource.basePrice * resource.recoveryRate,
|
|
||||||
resource.basePrice // Не превышать базовую цену
|
|
||||||
);
|
|
||||||
await resource.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Запускаем процесс восстановления цен каждые 15 минут
|
|
||||||
setInterval(recoverResourcePrices, 15 * 60 * 1000);
|
|
||||||
|
|
||||||
bot.action(/sell_all_(\d+)/, async (ctx) => {
|
|
||||||
const enterpriseId = ctx.match[1];
|
|
||||||
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
|
|
||||||
|
|
||||||
if (!enterprise) {
|
|
||||||
return await ctx.reply('Предприятие не найдено.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const { currentResources, resourceType, playerId } = enterprise;
|
|
||||||
const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });
|
|
||||||
const totalPrice = currentResources * resourcePrice.price;
|
|
||||||
|
|
||||||
if (currentResources === 0) {
|
|
||||||
return await ctx.reply('На предприятии нет ресурсов для продажи.');
|
|
||||||
}
|
|
||||||
|
|
||||||
await ctx.reply(
|
|
||||||
`Вы уверены, что хотите продать все ${currentResources} ед. ${resourceType} за ${totalPrice} руб.? Это необратимо!\n\nРекомендуем воспользоваться командой /sell для более гибкого управления продажами.`,
|
|
||||||
Markup.inlineKeyboard([
|
|
||||||
[
|
|
||||||
{ text: '✅ Продать всё', callback_data: `confirm_ressell_${enterpriseId}` },
|
|
||||||
{ text: '❌ Отмена', callback_data: 'cancel' }
|
|
||||||
]
|
|
||||||
])
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
bot.action(/confirm_ressell_(\d+)/, async (ctx) => {
|
|
||||||
const enterpriseId = ctx.match[1];
|
|
||||||
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
|
|
||||||
|
|
||||||
if (!enterprise) {
|
|
||||||
return await ctx.reply('Предприятие не найдено.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const { currentResources, resourceType, playerId } = enterprise;
|
|
||||||
const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: resourceType } });
|
|
||||||
const totalPrice = currentResources * resourcePrice.price;
|
|
||||||
|
|
||||||
if (currentResources === 0) {
|
|
||||||
return await ctx.reply('На предприятии нет ресурсов для продажи.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обновление баланса игрока
|
|
||||||
const user = await UserModel.findByPk(playerId);
|
|
||||||
user.money += totalPrice;
|
|
||||||
enterprise.currentResources = 0;
|
|
||||||
|
|
||||||
await user.save();
|
|
||||||
await enterprise.save();
|
|
||||||
// Инфляция: уменьшение цены ресурса
|
|
||||||
resourcePrice.price = Math.round(
|
|
||||||
resourcePrice.price * Math.exp(-resourcePrice.fluctuationRate * amount)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Гарантируем, что цена не упадет ниже 50% от базовой цены
|
|
||||||
resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
|
|
||||||
|
|
||||||
await resourcePrice.save();
|
|
||||||
|
|
||||||
await ctx.reply(`Вы успешно продали ${currentResources} ед. ${resourceType} за ${totalPrice} руб.`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Найм грузовика
|
|
||||||
bot.action('hire_truck', async (ctx) => {
|
bot.action('hire_truck', async (ctx) => {
|
||||||
const user = await UserModel.findByPk(ctx.from.id);
|
let user = await UserModel.findByPk(ctx.from.id)
|
||||||
|
let warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } })
|
||||||
|
|
||||||
// Получаем список предприятий пользователя
|
if (!warehouse) return await ctx.reply(`У вас нет склада для найма грузовиков.`)
|
||||||
const enterprises = await EnterpriseModel.findAll({
|
|
||||||
where: { playerId: user.telegram_id }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (enterprises.length === 0) {
|
// Логика найма грузовика
|
||||||
return await ctx.reply('У вас нет предприятий для найма грузовиков.');
|
let truck = await TruckModel.create({
|
||||||
}
|
warehouseId: warehouse.id,
|
||||||
|
|
||||||
// Создаем кнопки для выбора предприятия
|
|
||||||
const buttons = enterprises.map((enterprise) => [
|
|
||||||
{ text: `Нанять для ${enterprise.name}`, callback_data: `hire_truck_${enterprise.id}` }
|
|
||||||
]);
|
|
||||||
|
|
||||||
return await ctx.reply(
|
|
||||||
'Выберите предприятие для найма грузовика:',
|
|
||||||
Markup.inlineKeyboard(buttons).resize()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Обработка найма грузовика для выбранного предприятия
|
|
||||||
bot.action(/hire_truck_(\d+)/, async (ctx) => {
|
|
||||||
const user = await UserModel.findByPk(ctx.from.id);
|
|
||||||
const enterpriseId = ctx.match[1];
|
|
||||||
|
|
||||||
// Находим предприятие
|
|
||||||
const enterprise = await EnterpriseModel.findByPk(enterpriseId);
|
|
||||||
|
|
||||||
if (!enterprise || enterprise.playerId != user.telegram_id) {
|
|
||||||
return await ctx.reply('Предприятие не найдено или вам не принадлежит.');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Проверяем, есть ли уже грузовик для этого предприятия
|
|
||||||
const existingTruck = await TruckModel.findOne({
|
|
||||||
where: { enterpriseId: enterprise.id }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (existingTruck) {
|
|
||||||
return await ctx.reply(`У вас уже есть грузовик для предприятия ${enterprise.name}.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Создаем новый грузовик
|
|
||||||
const newTruck = await TruckModel.create({
|
|
||||||
enterpriseId: enterprise.id,
|
|
||||||
capacity: 10, // Начальная вместимость
|
capacity: 10, // Начальная вместимость
|
||||||
efficiency: 1 // Начальная эффективность
|
efficiency: 1 // Начальная эффективность
|
||||||
});
|
})
|
||||||
|
|
||||||
return await ctx.reply(
|
|
||||||
`Вы успешно наняли грузовик для предприятия ${enterprise.name}!`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
return await ctx.reply(`Вы наняли грузовик для транспортировки ресурсов!`)
|
||||||
|
})
|
||||||
|
|
||||||
async function initializePrices() {
|
async function initializePrices() {
|
||||||
const resources = [
|
const resources = [
|
||||||
@ -978,82 +839,91 @@ setInterval(async () => {
|
|||||||
}
|
}
|
||||||
}, 60000) // Обновляем цены каждые 60 секунд
|
}, 60000) // Обновляем цены каждые 60 секунд
|
||||||
|
|
||||||
// Функция добычи ресурсов
|
|
||||||
const resourceProduction = async () => {
|
const resourceProduction = async () => {
|
||||||
try {
|
try {
|
||||||
// Получаем все предприятия
|
// Получаем все предприятия без фильтрации по пользователю
|
||||||
const enterprises = await EnterpriseModel.findAll();
|
const enterprises = await EnterpriseModel.findAll();
|
||||||
|
|
||||||
for (const enterprise of enterprises) {
|
for (const enterprise of enterprises) {
|
||||||
const {
|
const { id, efficiency, warehouseCapacity, resourceType, playerId, level, currentResources } = enterprise;
|
||||||
id,
|
|
||||||
efficiency,
|
|
||||||
warehouseCapacity,
|
|
||||||
resourceType,
|
|
||||||
currentResources,
|
|
||||||
level,
|
|
||||||
playerId
|
|
||||||
} = enterprise;
|
|
||||||
|
|
||||||
// Расчёт добытых ресурсов
|
// Рассчитываем добычу ресурсов
|
||||||
const producedResources = efficiency * level;
|
const producedResources = efficiency * level;
|
||||||
|
|
||||||
// Проверяем ёмкость склада предприятия
|
// Проверяем, не превышает ли общая сумма ресурсов ёмкость склада
|
||||||
if (currentResources + producedResources <= warehouseCapacity) {
|
if (currentResources + producedResources <= warehouseCapacity) {
|
||||||
enterprise.currentResources += producedResources;
|
enterprise.currentResources = currentResources + producedResources;
|
||||||
await enterprise.save();
|
await enterprise.save();
|
||||||
console.log(
|
console.log(`Предприятие ${id}: добыто ${producedResources} единиц ${resourceType}.`);
|
||||||
`Предприятие ${id}: добыто ${producedResources} единиц ${resourceType}.`
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
console.log(`Предприятие ${id}: склад заполнен.`);
|
console.log(`Предприятие ${id}: склад заполнен.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Получаем универсальный склад, если он есть
|
||||||
|
const Warehouse = await WarehouseModel.findOne({
|
||||||
|
where: { playerId: playerId } // Привязка к игроку через playerId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Warehouse) {
|
||||||
|
const transportableAmount = Math.min(
|
||||||
|
enterprise.currentResources,
|
||||||
|
universalWarehouse.remainingCapacity
|
||||||
|
);
|
||||||
|
|
||||||
|
if (transportableAmount > 0) {
|
||||||
|
// Перемещаем ресурсы
|
||||||
|
enterprise.currentResources -= transportableAmount;
|
||||||
|
Warehouse.resources[resourceType] =
|
||||||
|
(Warehouse.resources[resourceType] || 0) + transportableAmount;
|
||||||
|
|
||||||
|
await enterprise.save();
|
||||||
|
await Warehouse.save();
|
||||||
|
|
||||||
|
console.log(`Предприятие ${id}: перевезено ${transportableAmount} единиц ${resourceType} на универсальный склад.`);
|
||||||
|
} else {
|
||||||
|
console.log(`Универсальный склад игрока ${playerId} заполнен.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Ошибка добычи ресурсов:', error);
|
console.error('Ошибка добычи ресурсов:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Функция транспортировки ресурсов
|
|
||||||
|
// Запуск функции каждый час
|
||||||
|
setInterval(resourceProduction, 60 * 60 * 1000);
|
||||||
|
|
||||||
|
// Функция добычи ресурсов
|
||||||
const resourceTransportation = async () => {
|
const resourceTransportation = async () => {
|
||||||
try {
|
try {
|
||||||
// Получаем все предприятия
|
|
||||||
const enterprises = await EnterpriseModel.findAll();
|
const enterprises = await EnterpriseModel.findAll();
|
||||||
|
|
||||||
for (const enterprise of enterprises) {
|
for (const enterprise of enterprises) {
|
||||||
const {
|
const { id, resourceType, currentResources, playerId } = enterprise;
|
||||||
id,
|
|
||||||
resourceType,
|
|
||||||
currentResources,
|
|
||||||
playerId
|
|
||||||
} = enterprise;
|
|
||||||
|
|
||||||
if (currentResources > 0) {
|
if (currentResources > 0) {
|
||||||
// Получаем грузовики, привязанные к предприятию
|
// Получаем склад игрока
|
||||||
const trucks = await TruckModel.findAll({
|
|
||||||
where: { enterpriseId: id }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (trucks.length === 0) {
|
|
||||||
console.log(
|
|
||||||
`Предприятие ${id}: нет доступных грузовиков для транспортировки.`
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Получаем универсальный склад игрока
|
|
||||||
const warehouse = await WarehouseModel.findOne({
|
const warehouse = await WarehouseModel.findOne({
|
||||||
where: { playerId }
|
where: { playerId }
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!warehouse) {
|
if (!warehouse) {
|
||||||
console.log(
|
console.log(`У игрока ${playerId} нет склада.`);
|
||||||
`Предприятие ${id}: у игрока ${playerId} нет универсального склада.`
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Транспортировка ресурсов
|
// Получаем грузовики, привязанные к этому складу
|
||||||
|
const trucks = await Truck.findAll({
|
||||||
|
where: { warehouseId: warehouse.id }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (trucks.length === 0) {
|
||||||
|
console.log(`На складе ${warehouse.id} нет доступных грузовиков.`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Транспортируем ресурсы
|
||||||
let totalTransported = 0;
|
let totalTransported = 0;
|
||||||
for (const truck of trucks) {
|
for (const truck of trucks) {
|
||||||
const transportableAmount = Math.min(
|
const transportableAmount = Math.min(
|
||||||
@ -1064,8 +934,7 @@ const resourceTransportation = async () => {
|
|||||||
|
|
||||||
if (transportableAmount > 0) {
|
if (transportableAmount > 0) {
|
||||||
// Обновляем данные склада
|
// Обновляем данные склада
|
||||||
warehouse[resourceType] =
|
warehouse[resourceType] = (warehouse[resourceType] || 0) + transportableAmount;
|
||||||
(warehouse[resourceType] || 0) + transportableAmount;
|
|
||||||
|
|
||||||
// Уменьшаем ресурсы на предприятии
|
// Уменьшаем ресурсы на предприятии
|
||||||
enterprise.currentResources -= transportableAmount;
|
enterprise.currentResources -= transportableAmount;
|
||||||
@ -1075,22 +944,18 @@ const resourceTransportation = async () => {
|
|||||||
|
|
||||||
totalTransported += transportableAmount;
|
totalTransported += transportableAmount;
|
||||||
|
|
||||||
console.log(
|
console.log(`Грузовик ${truck.id} перевёз ${transportableAmount} единиц ${resourceType}.`);
|
||||||
`Грузовик ${truck.id} перевёз ${transportableAmount} единиц ${resourceType}.`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Прекращаем, если ресурсы закончились
|
// Прекращаем, если на предприятии закончились ресурсы
|
||||||
if (enterprise.currentResources === 0) break;
|
if (enterprise.currentResources === 0) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalTransported === 0) {
|
if (totalTransported === 0) {
|
||||||
console.log(
|
console.log(`Склад ${warehouse.id} заполнен. Ресурсы не перевезены.`);
|
||||||
`Предприятие ${id}: склад заполнен, транспортировка невозможна.`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(`Предприятие ${id}: нет ресурсов для транспортировки.`);
|
console.log(`Предприятие ${id} не имеет доступных ресурсов для транспортировки.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1104,8 +969,7 @@ const getWarehouseUsedCapacity = (warehouse) => {
|
|||||||
return resources.reduce((sum, resource) => sum + (warehouse[resource] || 0), 0);
|
return resources.reduce((sum, resource) => sum + (warehouse[resource] || 0), 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Запускаем процессы каждый час
|
// Запускаем процесс транспортировки каждый час
|
||||||
setInterval(resourceProduction, 60 * 60 * 1000);
|
|
||||||
setInterval(resourceTransportation, 60 * 60 * 1000);
|
setInterval(resourceTransportation, 60 * 60 * 1000);
|
||||||
|
|
||||||
|
|
||||||
|
1
db.js
1
db.js
@ -7,7 +7,6 @@ const sequelize = new Sequelize(
|
|||||||
process.env.DB_PASSWORD, // Пароль
|
process.env.DB_PASSWORD, // Пароль
|
||||||
{
|
{
|
||||||
host: process.env.DB_HOST, // Хост
|
host: process.env.DB_HOST, // Хост
|
||||||
port: process.env.DB_PORT, // Порт
|
|
||||||
dialect: 'postgres', // Диалект базы данных
|
dialect: 'postgres', // Диалект базы данных
|
||||||
logging: false, // Отключение логирования запросов в консоль
|
logging: false, // Отключение логирования запросов в консоль
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user