1285 lines
51 KiB
JavaScript
1285 lines
51 KiB
JavaScript
const { Telegraf, Scenes, session, Markup, Stage, Composer } = require('telegraf');
|
||
const schedule = require('node-schedule');
|
||
const { faker, fakerRU } = require('@faker-js/faker');
|
||
// Подключаем необходимые библиотеки
|
||
const { Op } = require('sequelize');
|
||
const sequelize = require('./db'); // Подключение базы данных
|
||
// Подключаем обработчики
|
||
const utils = require('./utils');
|
||
const handlers = require('./handlers');
|
||
const {
|
||
phones,
|
||
expToUp,
|
||
UserModel,
|
||
CharacterModel,
|
||
ItemsModel,
|
||
StolenCardsModel,
|
||
WorldModel,
|
||
PropertyModel,
|
||
AFKPropertyModel,
|
||
BusinessModel,
|
||
BlockModel,
|
||
EnterpriseModel,
|
||
WarehouseModel,
|
||
TruckModel,
|
||
ResourcePriceModel,
|
||
SkillsModel,
|
||
DailyModel
|
||
} = global.config
|
||
const rpg = new Composer();
|
||
|
||
|
||
rpg.hears('RPG', async (ctx) => {
|
||
let message = `Меню:\n`;
|
||
const buttons = [];
|
||
buttons.push([{ text: 'Мой Персонаж', callback_data: 'rpg_profile' }]);
|
||
return await ctx.reply(message, Markup.inlineKeyboard(buttons).resize());
|
||
});
|
||
|
||
rpg.action('rpg_profile', async (ctx) => {
|
||
const telegramId = ctx.from.id;
|
||
|
||
// Ищем персонажа
|
||
const character = await CharacterModel.findOne({ where: { telegram_id: telegramId } });
|
||
const stolenCards = await StolenCardsModel.findAll({
|
||
where: { userId: character.telegram_id }
|
||
});
|
||
|
||
if (!character) {
|
||
return ctx.reply('Персонаж не найден. Создайте нового персонажа, чтобы начать игру!');
|
||
}
|
||
|
||
// Формируем профиль
|
||
const profile = `
|
||
🎭 Профиль персонажа:
|
||
👤 Имя: ${character.name || 'Не указано'}
|
||
🏆 Уровень: ${character.level} (${character.exp}/${utils.spaces(expToUp[character.level])})
|
||
❤️ Здоровье: ${character.hp}/${character.max_hp}
|
||
💪 Сила (F): ${character.force}
|
||
🧠 Интеллект (I): ${character.intelligence}
|
||
🛡️ Устойчивость (R): ${character.resilience}
|
||
🔋 Выносливость (E): ${character.endurance}
|
||
🔥 Стамина: ${character.stamina}/${character.max_stamina}
|
||
💰 Грязные деньги: ${utils.spaces(character.dirtymoney)}
|
||
🃏 Карточки: ${stolenCards.length}
|
||
`;
|
||
|
||
// Отправляем сообщение
|
||
ctx.reply(profile.trim(), Markup.inlineKeyboard([
|
||
[Markup.button.callback('💼 Задачи', 'crime_missions')],
|
||
]));
|
||
});
|
||
|
||
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||
|
||
// Хранилище для отслеживания пользователей, которые уже прошли ввод
|
||
const usersCrimeNet = new Set();
|
||
|
||
rpg.hears('CampFireGG.Crime', async (ctx) => {
|
||
const userId = ctx.from.id;
|
||
const character = await CharacterModel.findOne({ where: { telegram_id: userId } });
|
||
if (!usersCrimeNet.has(userId) && userId != 275416286){
|
||
// Если пользователь вводит команду впервые
|
||
usersCrimeNet.add(userId);
|
||
const username = ctx.from.username || 'User';
|
||
const randomServer = `secure.net-${Math.floor(Math.random() * 99 + 1)}.campfiregg.crime`;
|
||
const sshCommand = `ssh ${username}@${randomServer}`;
|
||
|
||
// Сообщение для симуляции
|
||
const lines = [
|
||
`${sshCommand}`,
|
||
`> Connecting to secure servers with RSA key...`,
|
||
`> Authentication in progress...`,
|
||
`> User "${username}" identified.`,
|
||
`> Accessing CampFireGG.Crime...`,
|
||
`> Connection established. Welcome, ${username}.`,
|
||
];
|
||
|
||
// Отправляем первое сообщение
|
||
let sentMessage = await ctx.reply('> Initializing CampFireGG.Crime...');
|
||
|
||
// Симуляция показа строки ssh блоками
|
||
let currentText = '';
|
||
let index = 0;
|
||
|
||
while (index < lines[0].length) {
|
||
const blockSize = Math.floor(Math.random() * 3) + 2; // Генерируем блок от 2 до 4 символов
|
||
currentText += lines[0].slice(index, index + blockSize); // Добавляем блок текста
|
||
index += blockSize; // Увеличиваем индекс
|
||
await ctx.telegram.editMessageText(sentMessage.chat.id, sentMessage.message_id, undefined, currentText);
|
||
await delay(100); // Задержка между блоками
|
||
}
|
||
|
||
// Последующие строки добавляются полностью, по одной
|
||
for (let i = 1; i < lines.length; i++) {
|
||
await delay(1500); // Задержка между строками
|
||
currentText += `\n${lines[i]}`;
|
||
await ctx.telegram.editMessageText(sentMessage.chat.id, sentMessage.message_id, undefined, currentText);
|
||
}
|
||
|
||
// Финальное меню после задержки
|
||
await delay(2000);
|
||
const buttons = [
|
||
[Markup.button.callback('💼 Задачи', 'crime_missions')],
|
||
[Markup.button.callback('📊 Профиль', 'rpg_profile')],
|
||
];
|
||
|
||
//buttons.push([Markup.button.callback('💳 Карточки', 'view_cards')]);
|
||
|
||
// Добавляем кнопку сообщения, если уровень персонажа равен 1
|
||
if (character && character.level === 1) {
|
||
buttons.push([Markup.button.callback('📩 (1) Сообщение', '1st_message')]);
|
||
}
|
||
|
||
await ctx.telegram.editMessageText(
|
||
sentMessage.chat.id,
|
||
sentMessage.message_id,
|
||
undefined,
|
||
`🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`,
|
||
Markup.inlineKeyboard(buttons)
|
||
)} else {
|
||
// Показываем только меню, если команда уже была введена
|
||
await ctx.reply(
|
||
`🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`,
|
||
Markup.inlineKeyboard([
|
||
[Markup.button.callback('💼 Задачи', 'crime_missions')],
|
||
[Markup.button.callback('📊 Профиль', 'rpg_profile')],
|
||
//[Markup.button.callback('💳 Карточки', 'view_cards')],
|
||
[Markup.button.callback('💰 Инвентарь', 'inventory')],
|
||
])
|
||
);
|
||
}
|
||
});
|
||
|
||
rpg.action('1st_message', async (ctx) => {
|
||
await ctx.answerCbQuery();
|
||
const message = `👤 Сообщение от неизвестного пользователя:
|
||
\`\`\`
|
||
"Добро пожаловать в CampFireGG.Crime. Если ты здесь, значит, у тебя есть вопросы. Забудь о них. Просто слушай."
|
||
|
||
🔥 F.I.R.E — твой путь к успеху:
|
||
"Каждый из нас что-то может. Кто-то силён, кто-то вынослив, а кто-то дохуя умный. В мире CampFireGG.Crime это называется F.I.R.E. Запомни эти буквы — от них зависит твоя жизнь здесь."
|
||
|
||
Force: Твоя мощь. Определяет, сколько импакта ты можешь внести. Чем выше, тем проще ликвидировать цель.
|
||
|
||
Intelligence: Твой интеллект. Чем ты умнее, тем больше шансов, что операция пройдет гладко. А ещё мозги ускоряют твое обучение.
|
||
|
||
Resilience: Твоя стойкость. Сколько времени тебе нужно, чтобы встать на ноги после провала? Чем выше этот параметр, тем быстрее ты восстанавливаешься.
|
||
|
||
Endurance: Твоя выносливость. Без неё ты не сможешь много работать, а значит, и много зарабатывать.
|
||
|
||
💰 Деньги? Грязные. Иначе здесь не бывает.
|
||
"Всё, что ты заработаешь здесь, будет грязным. Потратить можно только здесь, но есть способ отмыть деньги и перенести их на свой основной счёт. Всё зависит от твоего желания и возможностей."
|
||
|
||
💳 Карты? Да, их можно обналичить.
|
||
"Карточки — это всегда плюс. Взломал, достал, получил деньги. Всё просто. Главное — не профукай их."
|
||
|
||
🕶️ Последний совет:
|
||
"Каждое действие — это риск. Чем больше ты идёшь на риск, тем больше получаешь. Но если ошибёшься, можешь встрять. Так что думай."
|
||
|
||
"Добро пожаловать. Удачи тебе, новобранец."
|
||
\`\`\`
|
||
`;
|
||
|
||
await ctx.replyWithMarkdownV2(message, { disable_web_page_preview: true });
|
||
});
|
||
|
||
rpg.action('view_cards', async (ctx) => {
|
||
try {
|
||
// Получаем пользователя по Telegram ID
|
||
const character = await CharacterModel.findByPk(ctx.from.id);
|
||
|
||
if (!character) {
|
||
return ctx.reply('Персонаж не найден!');
|
||
}
|
||
|
||
// Получаем все украденные карточки для этого пользователя
|
||
const stolenCards = await StolenCardsModel.findAll({
|
||
where: { userId: character.telegram_id }
|
||
});
|
||
|
||
if (stolenCards.length === 0) {
|
||
return ctx.reply('У вас нет украденных карточек.');
|
||
}
|
||
|
||
const buttons = [];
|
||
let message = 'Ваши украденные карты:\n\n';
|
||
|
||
stolenCards.forEach(card => {
|
||
const lastFourDigits = card.cardNumber.slice(-4); // Берем последние 4 цифры карточки
|
||
message += `🔒 Карта: *${lastFourDigits}\n`;
|
||
|
||
// Генерация кнопок для брутфорса и покупки за лимит
|
||
buttons.push([
|
||
Markup.button.callback(`💳 *${lastFourDigits}`, `brutecard_${card.id}`),
|
||
//Markup.button.callback(`💰 *${lastFourDigits}`, `limitbuy_${card.id}`)
|
||
]);
|
||
});
|
||
|
||
// Отправляем сообщение с кнопками
|
||
await ctx.reply(message, Markup.inlineKeyboard(buttons));
|
||
|
||
} catch (error) {
|
||
console.error('Ошибка при выводе карточек:', error);
|
||
await ctx.reply('Произошла ошибка при получении ваших карточек.');
|
||
}
|
||
});
|
||
|
||
rpg.action(/limitbuy_/, async (ctx) => {
|
||
try {
|
||
const cardId = ctx.match.input.split('_')[1]; // ID карточки
|
||
const card = await StolenCardsModel.findByPk(cardId); // Получаем карточку
|
||
|
||
if (!card) {
|
||
return ctx.answerCbQuery('Карточка не найдена.');
|
||
}
|
||
|
||
const character = await CharacterModel.findByPk(ctx.from.id); // Получаем персонажа
|
||
if (!character) {
|
||
return ctx.answerCbQuery('Персонаж не найден.');
|
||
}
|
||
|
||
// Получаем 10 случайных предметов из базы
|
||
const items = await ItemsModel.findAll({ limit: 10 });
|
||
|
||
// Если у пользователя нет записей о попытках, создаем их
|
||
if (!attempts[ctx.from.id]) {
|
||
attempts[ctx.from.id] = 0;
|
||
}
|
||
|
||
// Генерация кнопок с предметами
|
||
const buttons = [];
|
||
items.forEach(item => {
|
||
const buttonText = `${item.name} - ¥${item.price}`;
|
||
buttons.push([Markup.button.callback(buttonText, `purchase_${item.id}_${card.id}`)]);
|
||
});
|
||
|
||
await ctx.reply(
|
||
'Выберите товар для покупки:\nПопробуйте угадать лимит карты.\n\n',
|
||
Markup.inlineKeyboard(buttons)
|
||
);
|
||
} catch (error) {
|
||
console.error('Ошибка при обработке покупки через лимит:', error);
|
||
}
|
||
});
|
||
|
||
rpg.action(/purchase_/, async (ctx) => {
|
||
try {
|
||
const [_, itemId, cardId] = ctx.match.input.split('_');
|
||
const item = await ItemsModel.findByPk(itemId);
|
||
const card = await StolenCardsModel.findByPk(cardId);
|
||
const character = await CharacterModel.findByPk(ctx.from.id);
|
||
|
||
if (!item || !card || !character) {
|
||
return ctx.answerCbQuery('Ошибка при обработке покупки.');
|
||
}
|
||
|
||
|
||
// Проверяем, не исчерпаны ли попытки
|
||
if (attempts[ctx.from.id] >= 3) {
|
||
// Сбрасываем попытки и уничтожаем карточку
|
||
delete attempts[ctx.from.id];
|
||
await StolenCardsModel.destroy({ where: { id: cardId } });
|
||
|
||
return ctx.editMessageText(
|
||
'❌ Все попытки исчерпаны! Карточка стала недействительной.'
|
||
);
|
||
}
|
||
|
||
// Если баланс карты меньше, чем цена товара, увеличиваем количество попыток
|
||
if (card.balance < item.price) {
|
||
attempts[ctx.from.id]++;
|
||
await ctx.answerCbQuery(`Недостаточно средств! Попыток осталось: ${3 - ctx.session.attempts}`);
|
||
return ctx.editMessageText(`Вы выбрали товар за ¥${item.price}, но у вас недостаточно средств.`);
|
||
}
|
||
|
||
// Если баланс карты достаточно для покупки, добавляем предмет в инвентарь
|
||
character.inventory.push(item.id);
|
||
await character.save();
|
||
|
||
// Если товар электронный, начисляем процент от стоимости на счет
|
||
if (item.type === 'digital') {
|
||
const profit = Math.round(item.price * 0.2); // 20% от стоимости товара
|
||
character.dirtymoney += profit;
|
||
await character.save();
|
||
await ctx.answerCbQuery(`Вы приобрели ${item.name} и перепродали за ¥${profit}.`);
|
||
} else {
|
||
await ctx.answerCbQuery(`Вы купили ${item.name}.`);
|
||
}
|
||
|
||
// Блокируем карту после покупки
|
||
card.destroy({ where: { id: cardId } });
|
||
await card.save();
|
||
|
||
// Оповещаем пользователя
|
||
await ctx.editMessageText(`${item.name} успешно куплен! Карта заблокирована.`);
|
||
} catch (error) {
|
||
console.error('Ошибка при обработке покупки:', error);
|
||
}
|
||
});
|
||
|
||
rpg.action(/purchase_fail_/, async (ctx) => {
|
||
try {
|
||
const [_, itemId, cardId] = ctx.match.input.split('_');
|
||
const item = await ItemsModel.findByPk(itemId);
|
||
const card = await StolenCardsModel.findByPk(cardId);
|
||
|
||
if (!item || !card) {
|
||
return ctx.answerCbQuery('Ошибка при проверке предмета или карты.');
|
||
}
|
||
|
||
await ctx.answerCbQuery('Недостаточно средств для покупки.');
|
||
} catch (error) {
|
||
console.error('Ошибка при обработке неудачной покупки:', error);
|
||
}
|
||
});
|
||
|
||
|
||
// Обработка попытки взлома карточки
|
||
rpg.action(/brutecard_/, async (ctx) => {
|
||
const cardId = ctx.match.input.split('_')[1]; // Получаем ID карточки из callback_data
|
||
const card = await StolenCardsModel.findByPk(cardId); // Ищем карточку в базе данных
|
||
|
||
if (!card) {
|
||
return ctx.answerCbQuery('Карточка не найдена.');
|
||
}
|
||
|
||
const buttonsCount = 10; // Количество кнопок
|
||
const winButton = utils.rand(1, buttonsCount); // Выбираем случайную кнопку для успешного пина
|
||
const maxAttempts = 3; // Максимальное количество попыток
|
||
|
||
// Если у пользователя нет записей о попытках, создаем их
|
||
if (!attempts[ctx.from.id]) {
|
||
attempts[ctx.from.id] = 0;
|
||
}
|
||
|
||
// Генерация кнопок
|
||
const buttons = [];
|
||
for (let i = 1; i <= buttonsCount; i++) {
|
||
if (i === winButton) {
|
||
// Если это победная кнопка (правильный ПИН)
|
||
buttons.push({ text: `${card.pin}`, callback_data: `brute_success_${cardId}` });
|
||
} else {
|
||
// Если это неудачная кнопка (случайный ПИН)
|
||
buttons.push({ text: `${faker.finance.pin()}`, callback_data: `brute_fail_${cardId}` });
|
||
}
|
||
}
|
||
|
||
// Разбиваем кнопки на строки по 5 кнопок
|
||
const rows = [];
|
||
while (buttons.length > 0) {
|
||
rows.push(buttons.splice(0, 5)); // Разбиваем на подмассивы по 5 кнопок
|
||
}
|
||
|
||
// Сортируем кнопки случайным образом
|
||
const keyboard = Markup.inlineKeyboard(
|
||
rows.sort(() => Math.random() - 0.5).map((row) => row) // Сортируем строки кнопок случайным образом
|
||
);
|
||
|
||
// Отправляем сообщение с клавиатурой
|
||
await ctx.reply(
|
||
`💳 Брутфорс карты\n\nПопробуйте подобрать правильный ПИН-код. У вас есть ${maxAttempts - attempts[ctx.from.id]} попыток.`,
|
||
keyboard
|
||
);
|
||
});
|
||
|
||
// Обработка неудачной попытки взлома
|
||
rpg.action(/brute_fail_/, async (ctx) => {
|
||
const cardId = ctx.match.input.split('_')[2];
|
||
const maxAttempts = 3; // Максимальное количество попыток
|
||
|
||
// Увеличиваем количество попыток
|
||
attempts[ctx.from.id]++;
|
||
|
||
// Проверяем, не исчерпаны ли попытки
|
||
if (attempts[ctx.from.id] >= maxAttempts) {
|
||
// Сбрасываем попытки и уничтожаем карточку
|
||
delete attempts[ctx.from.id];
|
||
await StolenCardsModel.destroy({ where: { id: cardId } });
|
||
|
||
return ctx.editMessageText(
|
||
'❌ Все попытки исчерпаны! Карточка стала недействительной.'
|
||
);
|
||
}
|
||
|
||
// Ответ на нажатие кнопки
|
||
ctx.answerCbQuery(`❌ Неправильный ПИН. Попыток осталось: ${maxAttempts - attempts[ctx.from.id]}`);
|
||
|
||
// Обновляем клавиатуру
|
||
const card = await StolenCardsModel.findByPk(cardId);
|
||
const buttonsCount = 10;
|
||
const winButton = utils.rand(1, buttonsCount);
|
||
const buttons = [];
|
||
|
||
for (let i = 1; i <= buttonsCount; i++) {
|
||
if (i === winButton) {
|
||
buttons.push({ text: `${card.pin}`, callback_data: `brute_success_${cardId}` });
|
||
} else {
|
||
buttons.push({ text: `${faker.finance.pin()}`, callback_data: `brute_fail_${cardId}` });
|
||
}
|
||
}
|
||
|
||
const rows = [];
|
||
while (buttons.length > 0) {
|
||
rows.push(buttons.splice(0, 5));
|
||
}
|
||
|
||
const keyboard = Markup.inlineKeyboard(
|
||
rows.sort(() => Math.random() - 0.5).map((row) => row)
|
||
);
|
||
|
||
// Обновляем сообщение с клавиатурой
|
||
await ctx.editMessageText(
|
||
`💳 Взлом карточки\n\nПопробуйте подобрать правильный ПИН-код. У вас есть ${maxAttempts - attempts[ctx.from.id]} попыток.`,
|
||
keyboard
|
||
);
|
||
});
|
||
|
||
// Обработка успешной попытки взлома
|
||
rpg.action(/brute_success_/, async (ctx) => {
|
||
|
||
const cardId = ctx.match.input.split('_')[2];
|
||
console.log(cardId)
|
||
const card = await StolenCardsModel.findByPk(cardId);
|
||
console.log(card)
|
||
if (!card) {
|
||
return ctx.answerCbQuery('Карточка не найдена.');
|
||
}
|
||
delete attempts[ctx.from.id];
|
||
const amount = card.balance; // Сумма денег за карточку
|
||
const character = await CharacterModel.findByPk(ctx.from.id);
|
||
|
||
// Увеличиваем грязные деньги пользователя
|
||
character.dirtymoney += amount;
|
||
await character.save();
|
||
|
||
// Удаляем карточку
|
||
await card.destroy();
|
||
|
||
// Отправляем сообщение о выигрыше
|
||
await ctx.editMessageText(
|
||
`✅ Взлом успешен! Вы получили Ð${amount} грязных денег.`
|
||
);
|
||
});
|
||
|
||
|
||
|
||
|
||
// Обработчики кнопок
|
||
rpg.action('crime_missions', async (ctx) => {
|
||
await ctx.answerCbQuery();
|
||
await ctx.editMessageText(`💼 **Задачи:**\n Для карманных краж тебе не нужно ничего, главное не попадись.\n А вот после ограбления магазина в переулке не спрячешься, без тачки на миссию нельзя.`,
|
||
Markup.inlineKeyboard([
|
||
[{text: 'Карманные кражи [1 lvl.]', callback_data: `POCKET_ACTION`}],
|
||
[{text: 'Магазин [5 lvl.]', callback_data: `SHOP_ACTION`}],
|
||
//[{text: 'Банкомат', callback_data: `WIP`}],
|
||
// [{text: 'Банковское отделение', callback_data: `WIP`}],
|
||
//[{text: 'Угон', callback_data: `WIP`}],
|
||
// [{text: 'Ювелирка', callback_data: `WIP`}],
|
||
//[{text: 'Банк', callback_data: `WIP`}],
|
||
[{text: '🔙 Back to Menu', callback_data: `crime_menu`}]
|
||
]),
|
||
);
|
||
});
|
||
|
||
rpg.action(`POCKET_ACTION`, async (ctx) => {
|
||
let user = await UserModel.findByPk(ctx.from.id)
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
let pocketsteal = character.pocketstealcd
|
||
if(character.level < 1) return ctx.editMessageText('Доступно с 1 уровня!')
|
||
if(character.stamina < 10) return ctx.editMessageText('Вы устали!')
|
||
let cooldown = utils.setCooldown(character, 3600, pocketsteal)
|
||
if (character.pocketstealcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`);
|
||
character.pocketstealcd = cooldown.endTime
|
||
character.stamina -= 10
|
||
character.save()
|
||
ctx.editMessageText('Выберите объект', Markup.inlineKeyboard([
|
||
[
|
||
{text: 'Карман', callback_data: `POCKET_TARGET`},
|
||
{text: 'Бумажник', callback_data: `POCKET_WALLET`},
|
||
{text: 'Сумка', callback_data: `POCKET_BAG`}
|
||
]
|
||
]))
|
||
});
|
||
|
||
rpg.action(`POCKET_TARGET`, async (ctx) => {
|
||
ctx.editMessageText('В кармане обнаружено', Markup.inlineKeyboard([
|
||
[
|
||
{text: 'Деньги', callback_data: `MONEY_IN_POCKET`},
|
||
{text: 'Телефон', callback_data: `PHONE`}
|
||
]
|
||
]))
|
||
});
|
||
|
||
rpg.action(`MONEY_IN_POCKET`, async (ctx) => {
|
||
// Получаем пользователя и его персонажа
|
||
//let user = await UserModel.findByPk(ctx.from.id);
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
|
||
if (!character) {
|
||
return ctx.editMessageText('У вас нет персонажа. Создайте его перед началом.');
|
||
}
|
||
|
||
// Расчёт шанса на успешную кражу
|
||
let baseChance = 40; // Базовый шанс
|
||
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
|
||
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
|
||
if (randomRoll > chance) {
|
||
Exp(ctx, character, 1)
|
||
return ctx.editMessageText('Вы были замечены во время кражи.');
|
||
}
|
||
// Успешная кража
|
||
let moneyIn = utils.rand(5, 1000);
|
||
Exp(ctx, character, character.intelligence + 3)
|
||
character.dirtymoney += moneyIn;
|
||
await character.save();
|
||
return ctx.editMessageText(`Вы успешно украли Ð${utils.spaces(moneyIn)} из кармана.`);
|
||
});
|
||
|
||
|
||
rpg.action(`PHONE`, async (ctx) => {
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
//let user = await UserModel.findByPk(ctx.from.id)
|
||
let property = await PropertyModel.findByPk(ctx.from.id);
|
||
// Расчёт шанса на успешную кражу
|
||
let baseChance = 20; // Базовый шанс
|
||
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
|
||
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
|
||
if(chance < randomRoll) {
|
||
Exp(ctx, character, 1)
|
||
return ctx.editMessageText('Вы были замечены во время кражи.')
|
||
}
|
||
let randPhone = utils.rand(1,10)
|
||
if (property.mobile.name) {
|
||
console.log(Math.round(phones[randPhone].price/100*70))
|
||
let dirtyMoney = Math.round(phones[randPhone].price/100*70)
|
||
console.log(character.intelligence + 10)
|
||
Exp(ctx, character, character.intelligence + 10)
|
||
character.dirtymoney += dirtyMoney
|
||
return await ctx.reply(`Вы сбыли украденный ${phones[randPhone].name} за Ð${utils.spaces(dirtyMoney)}`)
|
||
}
|
||
property.mobile = phones[randPhone]
|
||
await character.save()
|
||
await property.save()
|
||
return ctx.editMessageText(`Вы успешно украли ${phones[randPhone].name} из кармана.`)
|
||
});
|
||
|
||
rpg.action(`POCKET_WALLET`, async (ctx) => {
|
||
ctx.editMessageText('В бумажнике обнаружено', Markup.inlineKeyboard([
|
||
[
|
||
{text: 'Деньги', callback_data: `MONEY_IN_WALLET`},
|
||
{text: 'Карточка', callback_data: `CARD_IN_WALLET`}
|
||
]
|
||
]))
|
||
});
|
||
|
||
rpg.action(`MONEY_IN_WALLET`, async (ctx) => {
|
||
//let user = await UserModel.findByPk(ctx.from.id)
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
// Расчёт шанса на успешную кражу
|
||
let baseChance = 35; // Базовый шанс
|
||
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
|
||
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
|
||
if(chance < randomRoll) {
|
||
Exp(ctx, character, 1)
|
||
return ctx.editMessageText('Вы были замечены во время кражи.')
|
||
}
|
||
let moneyIn = utils.rand(1000, 10000)
|
||
Exp(ctx, character, character.intelligence + 5)
|
||
character.dirtymoney += moneyIn
|
||
character.save()
|
||
return ctx.editMessageText(`Вы успешно украли Ð${utils.spaces(moneyIn)} из бумажника.`)
|
||
});
|
||
|
||
rpg.action(`CARD_IN_WALLET`, async (ctx) => {
|
||
//let user = await UserModel.findByPk(ctx.from.id)
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
let baseChance = 20; // Базовый шанс
|
||
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
|
||
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
|
||
if(chance < randomRoll) {
|
||
Exp(ctx, character, 2)
|
||
return ctx.editMessageText('Вы были замечены во время кражи.')
|
||
}
|
||
Exp(ctx, character, character.intelligence + 7)
|
||
generateCard(ctx.from.id)
|
||
character.save()
|
||
return ctx.editMessageText(`Вы успешно украли 💳 из бумажника.`)
|
||
});
|
||
|
||
rpg.action(`POCKET_BAG`, async (ctx) => {
|
||
//let user = await UserModel.findByPk(ctx.from.id)
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
let baseChance = 20; // Базовый шанс
|
||
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
|
||
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
|
||
if(chance < randomRoll) {
|
||
Exp(ctx, character, 1)
|
||
return ctx.editMessageText('Вы были замечены во время кражи.')
|
||
}
|
||
let times = utils.rand(2,20)
|
||
let moneyIn = 0
|
||
let text = ``
|
||
let values = 0
|
||
|
||
for(i=1; i<=times; i++){
|
||
randomize = utils.rand(1,100)
|
||
switch(randomize) {
|
||
case 2:
|
||
values = utils.rand(10000, 50000)
|
||
moneyIn += values
|
||
text += `+ Ð${utils.spaces(values)}\n`
|
||
break;
|
||
case 7:
|
||
values = utils.rand(10000, 100000)
|
||
moneyIn += values
|
||
text += `+ Ð${utils.spaces(values)}\n`
|
||
break;
|
||
default:
|
||
values = utils.rand(100, 3000)
|
||
moneyIn += values
|
||
text += `+ Ð${utils.spaces(values)}\n`
|
||
break;
|
||
}
|
||
}
|
||
Exp(ctx, character, character.intelligence + times)
|
||
character.dirtymoney += moneyIn
|
||
character.save()
|
||
return ctx.editMessageText(`Вы успешно украли сумку и сбыли все ценности из нее:\n${text}\nОбщий куш: Ð${utils.spaces(moneyIn)}`)
|
||
});
|
||
|
||
rpg.action('crime_menu', async (ctx) => {
|
||
await ctx.answerCbQuery();
|
||
await ctx.editMessageText(
|
||
`💻 CampFireGG.Crime Menu`,
|
||
Markup.inlineKeyboard([
|
||
[Markup.button.callback('💼 Задачи', 'crime_missions')],
|
||
[Markup.button.callback('📊 Профиль', 'crime_stats')],
|
||
[Markup.button.callback('💰 ...', 'crime_market')],
|
||
])
|
||
);
|
||
});
|
||
|
||
rpg.action('SHOP_ACTION', async (ctx) => {
|
||
let user = await UserModel.findByPk(ctx.from.id)
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
let property = await PropertyModel.findByPk(ctx.from.id);
|
||
if(character.level < 5) return ctx.editMessageText('Доступно с 5 уровня!')
|
||
if(property.car1 == 0) return ctx.editMessageText('Для данного задания нужна тачка.')
|
||
if(character.stamina < 25) return ctx.editMessageText('Вы устали!')
|
||
let shoprobcd = character.shoprobcd
|
||
let cooldown = utils.setCooldown(character, 3600, shoprobcd)
|
||
if (character.shoprobcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`);
|
||
character.shoprobcd = cooldown.endTime
|
||
character.stamina -= 25
|
||
character.save()
|
||
return ctx.editMessageText('Стадии:', Markup.inlineKeyboard([
|
||
[{text: 'Взлом кассы', callback_data: `SHOP_CASH_BREAK`}],
|
||
[{text: 'Разбить кассу', callback_data: `SHOP_CASH_SMASH`}]
|
||
]))
|
||
});
|
||
|
||
rpg.action(`SHOP_CASH_BREAK`, async (ctx) => {
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
let baseChance = 20; // Базовый шанс
|
||
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
|
||
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
|
||
let cashIn = utils.rand(1000, 10000)
|
||
let timer = 1000
|
||
if(chance < randomRoll) {
|
||
const keyboard = generateKeyboard();
|
||
ctx.deleteMessage()
|
||
return ctx.reply('Касса закрыта, вы начали взлом замка:', keyboard);
|
||
//ctx.editMessageText('Вы начали взлом кассы.');
|
||
//return ctx.scene.enter('LOCKPICK')
|
||
}
|
||
for(i=0; i<utils.rand(character.endurance, character.endurance + 15);i++){
|
||
setTimeout(() => {
|
||
cashIn += utils.rand(1000, 10000)
|
||
ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`)
|
||
}, timer)
|
||
timer += 500
|
||
}
|
||
setTimeout(() => {
|
||
Exp(ctx, character, character.intelligence + 25)
|
||
character.dirtymoney += cashIn
|
||
character.save()
|
||
return ctx.editMessageText(`Вы достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([
|
||
[{text: 'Завершить ограбление', callback_data: `SHOP_END`}]
|
||
]))
|
||
}, timer+300)
|
||
});
|
||
|
||
rpg.action(`SHOP_CASH_SMASH`, async (ctx) => {
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
let baseChance = 20; // Базовый шанс
|
||
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
|
||
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
|
||
let cashIn = utils.rand(1000, 10000)
|
||
let timer = 1000
|
||
if(chance < randomRoll) {
|
||
Exp(ctx, character, 1)
|
||
return ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация. Вы сбежали.')
|
||
}
|
||
ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация.')
|
||
for(i=0; i<utils.rand(character.endurance, character.endurance + 8);i++){
|
||
setTimeout(() => {
|
||
cashIn += utils.rand(500, 5000)
|
||
ctx.editMessageText(`⏏️ Вы в спешке достали из кассы: Ð${utils.spaces(cashIn)}`)
|
||
}, timer)
|
||
timer += 500
|
||
}
|
||
setTimeout(() => {
|
||
Exp(ctx, character, character.intelligence + 10)
|
||
character.dirtymoney += cashIn
|
||
character.save()
|
||
return ctx.editMessageText(`Вы в спешке достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([
|
||
[{text: 'Завершить ограбление', callback_data: `SHOP_END`}]
|
||
]))
|
||
}, timer+300)
|
||
});
|
||
|
||
rpg.action(`SHOP_CASH_BREAK_SUCCESS`, async (ctx) => {
|
||
let user = await UserModel.findByPk(ctx.from.id)
|
||
let character = await CharacterModel.findByPk(ctx.from.id);
|
||
delete attempts[ctx.from.id];
|
||
let cashIn = utils.rand(1000, 10000)
|
||
let timer = 100
|
||
for(i=0; i<utils.rand(character.endurance, character.endurance + 15);i++){
|
||
setTimeout(() => {
|
||
cashIn += utils.rand(3000, 10000)
|
||
ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`)
|
||
}, timer)
|
||
timer += 500
|
||
}
|
||
setTimeout(() => {
|
||
Exp(ctx, character, character.intelligence + 30)
|
||
character.dirtymoney += cashIn
|
||
character.save()
|
||
return ctx.editMessageText(`Вы достали из кассы Ð${utils.spaces(cashIn)}, пора валить.`, Markup.inlineKeyboard([
|
||
[{text: 'Завершить ограбление', callback_data: `SHOP_END`}]
|
||
]))
|
||
}, timer+300)
|
||
});
|
||
|
||
rpg.action(`SHOP_END`, async (ctx) => {
|
||
return ctx.editMessageText('Ограбление завершено!')
|
||
});
|
||
|
||
const attempts = {}; // Храним количество попыток взлома для каждого пользователя
|
||
|
||
rpg.action(/lock_*/, async (ctx) => {
|
||
const userId = ctx.from.id;
|
||
const buttonId = ctx.update.callback_query.data;
|
||
|
||
// Если пользователя нет в списке попыток, добавляем его
|
||
if (!attempts[userId]) {
|
||
attempts[userId] = 0;
|
||
}
|
||
|
||
// Увеличиваем количество попыток
|
||
attempts[userId] += 1;
|
||
|
||
// Проверяем, не исчерпаны ли попытки
|
||
if (attempts[userId] >= 5) {
|
||
delete attempts[userId]; // Сбрасываем попытки после провала
|
||
return ctx.editMessageText('Взлом провалился. Замок остается нетронутым.');
|
||
}
|
||
|
||
// Ответ на нажатие кнопки
|
||
ctx.answerCbQuery(`Штифт не сдвинулся. Попыток осталось: ${5 - attempts[userId]}`);
|
||
removeButton(ctx, buttonId);
|
||
});
|
||
|
||
rpg.action('inventory', async (ctx) => {
|
||
try {
|
||
const character = await CharacterModel.findByPk(ctx.from.id);
|
||
|
||
if (!character) {
|
||
return ctx.reply('Персонаж не найден!');
|
||
}
|
||
|
||
const inventory = character.inventory || [];
|
||
const equippedItems = character.equippedItems || [];
|
||
|
||
// Если инвентарь пустой
|
||
if (inventory.length === 0 && equippedItems.length === 0) {
|
||
return ctx.reply('Ваш инвентарь пуст.');
|
||
}
|
||
|
||
let message = '*Ваш инвентарь:*\n\n';
|
||
|
||
// Снаряженные предметы
|
||
if (equippedItems.length > 0) {
|
||
message += '🛡️ *Снаряженные предметы:*\n';
|
||
for (const item of equippedItems) {
|
||
if (item) {
|
||
message += `- ${item.name} (${item.type})\n`;
|
||
}
|
||
}
|
||
message += '\n';
|
||
}
|
||
|
||
// Предметы в инвентаре
|
||
if (inventory.length > 0) {
|
||
message += '🎒 *Предметы в инвентаре:*\n';
|
||
for (const item of inventory) {
|
||
if (item) {
|
||
message += `- ${item.name} (${item.type})\n`;
|
||
}
|
||
}
|
||
message += '\n';
|
||
}
|
||
|
||
// Кнопки для взаимодействия
|
||
const buttons = [];
|
||
|
||
for (const item of inventory) {
|
||
if (item) {
|
||
buttons.push(
|
||
Markup.button.callback(`🎯 Использовать ${item.name}`, `use_item_${item.id}`)
|
||
);
|
||
}
|
||
}
|
||
|
||
for (const item of equippedItems) {
|
||
if (item) {
|
||
buttons.push(
|
||
Markup.button.callback(`🚫 Снять ${item.name}`, `use_item_${item.id}`)
|
||
);
|
||
}
|
||
}
|
||
|
||
await ctx.replyWithMarkdown(message, Markup.inlineKeyboard(buttons, { columns: 2 }));
|
||
} catch (error) {
|
||
console.error('Ошибка при выводе инвентаря:', error);
|
||
await ctx.reply('Произошла ошибка при отображении вашего инвентаря.');
|
||
}
|
||
});
|
||
|
||
rpg.action(/use_item_(\d+)/, async (ctx) => {
|
||
const itemId = parseInt(ctx.match[1], 10);
|
||
const character = await CharacterModel.findByPk(ctx.from.id);
|
||
const item = await ItemsModel.findByPk(itemId);
|
||
|
||
const inventory = character.inventory || [];
|
||
const isEquipped = character.equippedItems.some((equippedItem) => equippedItem.id === itemId); // Проверяем, снаряжен ли предмет
|
||
|
||
// Проверка наличия предмета в инвентаре
|
||
if (!inventory.some((invItem) => invItem.id === itemId) && !isEquipped) {
|
||
return ctx.reply('У вас нет этого предмета.');
|
||
}
|
||
|
||
// Если предмет уже снаряжен
|
||
if (isEquipped) {
|
||
// Снимаем предмет
|
||
const resultMessages = await character.removeEquippedItem(item); // Убираем предмет из снаряженных
|
||
return ctx.reply(`Вы сняли ${item.name}. ${resultMessages}`);
|
||
}
|
||
|
||
// Если предмет имеет временный эффект и уже активен
|
||
if (
|
||
item.effectData &&
|
||
Array.isArray(item.effectData) &&
|
||
item.effectData.some((effect) =>
|
||
character.activeEffects.some((activeEffect) => activeEffect.type === effect.type)
|
||
)
|
||
) {
|
||
return ctx.reply(`Эффект от ${item.name} уже активен.`);
|
||
}
|
||
|
||
// Обработка эффектов предмета
|
||
if (item.effectData && Array.isArray(item.effectData)) {
|
||
const resultMessages = processEffects(character, item.effectData, true); // true, так как мы снаряжаем предмет
|
||
|
||
// Удаляем предмет из инвентаря, если он одноразовый
|
||
if (item.type === 'consumable') {
|
||
await character.removeItemFromInventory(item);
|
||
}
|
||
|
||
// Если предмет не одноразовый, снаряжаем его
|
||
else {
|
||
await character.addEquippedItem(item); // Добавляем предмет в снаряженные
|
||
}
|
||
|
||
await character.save(); // Явно сохраняем изменения в базе данных
|
||
return ctx.reply(resultMessages);
|
||
}
|
||
|
||
ctx.reply('Этот предмет нельзя использовать.');
|
||
});
|
||
|
||
|
||
rpg.command('shop', async (ctx) => {
|
||
const character = await CharacterModel.findByPk(ctx.from.id);
|
||
|
||
if (!character) {
|
||
return ctx.reply('Персонаж не найден!');
|
||
}
|
||
|
||
const items = await ItemsModel.findAll();
|
||
|
||
if (items.length === 0) {
|
||
return ctx.reply('Магазин пуст!');
|
||
}
|
||
|
||
let message = 'Добро пожаловать в магазин! Здесь вы можете купить предметы:\n\n';
|
||
|
||
const buttons = items.map((item) => {
|
||
return [Markup.button.callback(`${item.name} - ${item.price}₽`, `buy_item_${item.id}`)];
|
||
});
|
||
|
||
await ctx.reply(message, Markup.inlineKeyboard(buttons));
|
||
});
|
||
|
||
rpg.action(/buy_item_(\d+)/, async (ctx) => {
|
||
const itemId = parseInt(ctx.match[1], 10);
|
||
const character = await CharacterModel.findByPk(ctx.from.id);
|
||
const item = await ItemsModel.findByPk(itemId);
|
||
|
||
if (!character || !item) {
|
||
return ctx.reply('Ошибка: Персонаж или предмет не найдены.');
|
||
}
|
||
|
||
if (character.balance < item.price) {
|
||
return ctx.reply('У вас недостаточно средств для покупки этого предмета.');
|
||
}
|
||
|
||
// Снимаем деньги с баланса персонажа
|
||
character.balance -= item.price;
|
||
|
||
// Добавляем предмет в инвентарь (в массив)
|
||
character.inventory = [...character.inventory, item];
|
||
|
||
await character.save();
|
||
|
||
// Отправляем сообщение об успешной покупке
|
||
await ctx.reply(`Вы успешно купили ${item.name} за ${item.price}₽!`);
|
||
|
||
// Можно добавить сюда логику для применения эффекта, если он есть
|
||
});
|
||
|
||
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
||
CharacterModel.prototype.addEquippedItem = async function(item) {
|
||
// Проверяем, есть ли уже предмет в инвентаре
|
||
const isInInventory = this.inventory.some((invItem) => invItem.id === item.id);
|
||
if (!isInInventory) {
|
||
return; // Предмет должен быть в инвентаре
|
||
}
|
||
|
||
// Проверяем, есть ли уже этот предмет в снаряженных
|
||
if (!this.equippedItems.some((equippedItem) => equippedItem.id === item.id)) {
|
||
this.equippedItems.push(item.id); // Добавляем только ID предмета
|
||
this.changed('equippedItems', true); // Помечаем, что поле изменилось
|
||
await this.save(); // Сохраняем изменения в базе данных
|
||
}
|
||
};
|
||
|
||
|
||
CharacterModel.prototype.removeEquippedItem = async function(item) {
|
||
// Проверяем, снаряжен ли предмет
|
||
if (this.equippedItems.some((equippedItem) => equippedItem.id === item.id)) {
|
||
// Убираем эффект, если он связан с данным предметом
|
||
if (item.effectData && Array.isArray(item.effectData)) {
|
||
const resultMessages = processEffects(this, item.effectData, false); // false, так как мы снимаем
|
||
this.changed('equippedItems', true); // Помечаем изменение массива снаряженных
|
||
await this.save();
|
||
return resultMessages;
|
||
}
|
||
|
||
// Удаляем предмет из снаряженных
|
||
this.equippedItems = this.equippedItems.filter((equippedItem) => equippedItem.id !== item.id);
|
||
this.changed('equippedItems', true); // Помечаем изменение массива снаряженных
|
||
await this.save(); // Сохраняем изменения в базе данных
|
||
}
|
||
return null;
|
||
};
|
||
|
||
|
||
|
||
const processEffects = (character, effects, isEquipping) => {
|
||
let messages = [];
|
||
|
||
effects.forEach((effect) => {
|
||
// Если предмет снимается (isEquipping = false), эффекты снимаются
|
||
if (!isEquipping) {
|
||
switch (effect.type) {
|
||
case 'damage_boost':
|
||
character.force -= effect.amount;
|
||
messages.push(`Ваш урон уменьшен на ${effect.amount}.`);
|
||
break;
|
||
|
||
case 'max_health_boost':
|
||
character.max_hp -= effect.amount;
|
||
messages.push(`Ваше максимальное здоровье уменьшено на ${effect.amount}.`);
|
||
break;
|
||
|
||
case 'stamina_penalty':
|
||
character.max_stamina += effect.amount;
|
||
messages.push(`Ваша выносливость увеличена на ${effect.amount}.`);
|
||
break;
|
||
|
||
default:
|
||
messages.push('Эффект не распознан при снятии.');
|
||
}
|
||
} else {
|
||
// Применяем эффект при снаряжении
|
||
switch (effect.type) {
|
||
case 'heal':
|
||
const maxHp = character.maxHp || 100;
|
||
character.hp = Math.min(maxHp, character.hp + effect.amount);
|
||
messages.push(`Вы восстановили ${effect.amount} HP.`);
|
||
break;
|
||
|
||
case 'damage_boost':
|
||
character.force += effect.amount;
|
||
messages.push(`Ваш урон увеличен на ${effect.amount}.`);
|
||
break;
|
||
|
||
case 'max_health_boost':
|
||
character.max_hp += effect.amount;
|
||
messages.push(`Ваше максимальное здоровье увеличено на ${effect.amount}.`);
|
||
break;
|
||
|
||
case 'stamina_penalty':
|
||
character.max_stamina -= effect.amount;
|
||
messages.push(`Ваша выносливость уменьшена на ${effect.amount}.`);
|
||
break;
|
||
|
||
default:
|
||
messages.push('Эффект не распознан при надевании.');
|
||
}
|
||
}
|
||
});
|
||
|
||
return messages.join('\n');
|
||
};
|
||
|
||
|
||
|
||
function generateKeyboard() {
|
||
const buttonsCount = 10;
|
||
const buttons = [];
|
||
const winButton = utils.rand(1, 10);
|
||
|
||
for (let i = 1; i <= buttonsCount; i++) {
|
||
if (i === winButton) {
|
||
buttons.push({ text: `🔒`, callback_data: `SHOP_CASH_BREAK_SUCCESS` });
|
||
} else {
|
||
buttons.push({ text: `🔒`, callback_data: `lock_${i}` });
|
||
}
|
||
}
|
||
|
||
const rows = [];
|
||
while (buttons.length > 0) {
|
||
rows.push(buttons.splice(0, 5)); // Разбиваем на подмассивы по 5 кнопок
|
||
}
|
||
console.log(rows)
|
||
return {
|
||
reply_markup: {
|
||
inline_keyboard: rows,
|
||
},
|
||
};
|
||
}
|
||
|
||
function removeButton(ctx, buttonId) {
|
||
const keyboard = ctx.update.callback_query.message.reply_markup.inline_keyboard;
|
||
|
||
for (let row of keyboard) {
|
||
for (let i = 0; i < row.length; i++) {
|
||
if (row[i].callback_data === buttonId) {
|
||
row[i].text = `🔓`;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
ctx.editMessageText('Взлом замка:', Markup.inlineKeyboard(keyboard).resize());
|
||
}
|
||
|
||
// Восстановление здоровья (HP)
|
||
async function recoverHealth() {
|
||
const characters = await CharacterModel.findAll({
|
||
where: {
|
||
hp: {
|
||
[Op.lt]: 100, // Восстанавливаем только тем, у кого HP меньше 100
|
||
},
|
||
},
|
||
});
|
||
|
||
for (const character of characters) {
|
||
const recoveryRate = character.resilience; // Восстановление 10 HP за интервал
|
||
character.hp = Math.min(character.hp + recoveryRate, 100); // Не превышаем максимум
|
||
await character.save();
|
||
}
|
||
}
|
||
|
||
// Восстановление выносливости (стамины)
|
||
async function recoverStamina() {
|
||
const characters = await CharacterModel.findAll({
|
||
where: {
|
||
stamina: {
|
||
[Op.lt]: 100, // Восстанавливаем только тем, у кого стамина меньше 100
|
||
},
|
||
},
|
||
});
|
||
|
||
for (const character of characters) {
|
||
const recoveryRate = character.endurance; // Восстановление 5 стамины за интервал
|
||
character.stamina = Math.min(character.stamina + recoveryRate, 100); // Не превышаем максимум
|
||
await character.save();
|
||
}
|
||
}
|
||
|
||
const reduceStealedCards = async () => {
|
||
try {
|
||
const characters = await CharacterModel.findAll();
|
||
|
||
for (const character of characters) {
|
||
const stolenCards = await StolenCardsModel.findAll({
|
||
where: { userId: character.telegram_id }
|
||
});
|
||
|
||
if (stolenCards.length > 0) {
|
||
// Для каждой карточки уменьшаем баланс на половину
|
||
for (const card of stolenCards) {
|
||
card.balance = Math.ceil(card.balance / 2); // Баланс делим на 2 и округляем вверх
|
||
await card.save(); // Сохраняем изменения карточки
|
||
}
|
||
|
||
// Удаляем половину карточек
|
||
const cardsToDelete = Math.ceil(stolenCards.length / 2);
|
||
const cardsToRemove = stolenCards.slice(0, cardsToDelete);
|
||
|
||
for (const card of cardsToRemove) {
|
||
await card.destroy(); // Удаляем карточки
|
||
}
|
||
|
||
console.log(`Карточки для персонажа ${character.id} успешно обновлены.`);
|
||
}
|
||
}
|
||
|
||
console.log('Карточки всех игроков успешно обновлены.');
|
||
} catch (error) {
|
||
console.error('Ошибка при обновлении карточек:', error);
|
||
}
|
||
};
|
||
|
||
|
||
async function generateCard(userId, balance) {
|
||
console.log(balance)
|
||
if(!Number(balance)){
|
||
balance = faker.finance.amount({dec: 0})*100
|
||
console.log('Random balance: ' + balance)
|
||
}else{
|
||
balance = Math.floor(balance);
|
||
console.log('Set balance: ' + balance)
|
||
}
|
||
const cardNumber = `${faker.finance.creditCardNumber()}`; // Генерация номера карты
|
||
const pin = `${faker.finance.pin()}`; // Четырехзначный ПИН
|
||
const cvv = `${faker.finance.creditCardCVV()}`; // Трехзначный CVV
|
||
const holderName = `${faker.person.firstName()} ${faker.person.lastName()}`; // Имя и фамилия
|
||
const bankName = faker.company.name(); // Название банка
|
||
const expiresDate = `${Math.floor(Math.random() * 12) + 1}/${2025 + Math.floor(Math.random() * 5)}`; // Срок действия
|
||
|
||
await StolenCardsModel.create({
|
||
userId,
|
||
balance,
|
||
cardNumber,
|
||
pin,
|
||
cvv,
|
||
holderName,
|
||
bankName,
|
||
expiresDate,
|
||
});
|
||
}
|
||
|
||
async function Exp(ctx, character, experience) {
|
||
character.exp += experience
|
||
await ctx.sendMessage(`❇️ +${experience} exp.`)
|
||
await character.save()
|
||
for(i in expToUp){
|
||
if (character.exp >= expToUp[character.level]) {
|
||
character.exp -= expToUp[character.level]
|
||
character.level += 1
|
||
await character.save()
|
||
await ctx.sendMessage(`⤴️ Уровень вашего персонажа повысился до ${character.level}!`)}
|
||
}
|
||
}
|
||
|
||
// Периодическое выполнение задач
|
||
function startRecoveryIntervals() {
|
||
const interval = 5 * 1000; // Интервал в миллисекундах (например, 1 минута)
|
||
setInterval(recoverHealth, interval);
|
||
setInterval(recoverStamina, interval);
|
||
}
|
||
|
||
// Планируем выполнение задачи каждый день в 12 ночи
|
||
schedule.scheduleJob('0 0 * * *', reduceStealedCards);
|
||
|
||
rpg.command('force_reduce', async (ctx) => {
|
||
reduceStealedCards()
|
||
return await ctx.reply(`Принудительно`)
|
||
})
|
||
|
||
rpg.command('steal_card', async (ctx) => {
|
||
await generateCard(ctx.from.id)
|
||
ctx.reply('💳 Вы украли новую карточку! Проверьте её в вашем инвентаре.');
|
||
});
|
||
|
||
|
||
startRecoveryIntervals()
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
const fillItemsTable = async () => {
|
||
try {
|
||
const items = [];
|
||
|
||
// Генерируем 10 случайных предметов
|
||
for (let i = 0; i < 10; i++) {
|
||
const item = {
|
||
name: fakerRU.commerce.productName(), // Название товара
|
||
description: fakerRU.lorem.sentence(), // Описание товара
|
||
price: fakerRU.commerce.price({ dec: 0 }), // Цена товара
|
||
rarity: 1, // Редкость (от 1 до 5)
|
||
type: 'other', // Тип предмета
|
||
};
|
||
|
||
items.push(item);
|
||
}
|
||
|
||
// Вставляем все 10 предметов в таблицу
|
||
await ItemsModel.bulkCreate(items);
|
||
console.log('Таблица предметов успешно заполнена!');
|
||
} catch (error) {
|
||
console.error('Ошибка при заполнении таблицы предметов:', error);
|
||
}
|
||
};
|
||
|
||
// Запускаем функцию
|
||
//fillItemsTable();
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
module.exports = rpg;
|