CampFirePlay/rpg.js
Degradin 125b782a64 v5.2-rc
Crime update
2025-01-10 00:54:54 +03:00

1377 lines
53 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.

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,
InventoryModel,
ItemsModel,
StolenCardsModel,
WorldModel,
PropertyModel,
AFKPropertyModel,
BusinessModel,
BlockModel,
EnterpriseModel,
WarehouseModel,
TruckModel,
ResourcePriceModel,
SkillsModel,
DailyModel
} = global.config
const rpg = new Composer();
rpg.use(async (ctx, next) => {
let id = ctx.from.id;
let username = ctx.from.username;
if (username == null) username = ctx.from.id;
const currentTime = utils.getCurrentTime();
switch (ctx.updateType) {
case 'message':
console.log(`${currentTime}: [RPG] ${username}: ${ctx.update.message.text}`);
break;
case 'callback_query':
console.log(`${currentTime}: [RPG] ${username}: ${ctx.update.callback_query.data}`);
break;
case 'edited_message':
console.log(`${currentTime}: [RPG] ${username} edited: ${ctx.update.edited_message.text}`);
break;
default:
console.log(`${currentTime}: [RPG] Unknown update type:`, ctx.update);
}
await next(); // Передаем управление следующему middleware
});
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')],
[Markup.button.callback('💰 Магазин', 'shop')],
])
);
}
});
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.InventoryModel.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); // Ищем карточку в базе данных
const inventory = await InventoryModel.findAll({ where: { telegram_id: ctx.from.id } }); // Загружаем предметы из инвентаря
if (!card) {
return ctx.answerCbQuery('Карточка не найдена.');
}
// Проверяем наличие "Эмулятора картридера" в инвентаре
const emulator = inventory.find((item) => item.name === 'Эмулятор картридера');
if (!emulator) {
return ctx.reply('Для запуска брутфорса вам нужен "Эмулятор картридера".');
}
// Удаляем "Эмулятор картридера" из инвентаря
await InventoryModel.destroy({ where: { id: emulator.id } });
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
━━━━━━━━━━━━━━━━━━━━
${card.bankName.toUpperCase()}
━━━━━━━━━━━━━━━━━━━━
Номер: ${card.cardNumber}
CVV: ${card.cvv}
Владелец: ${card.holderName.toUpperCase()}
Срок действия: ${card.expiresDate}
━━━━━━━━━━━━━━━━━━━━
Попробуйте подобрать правильный ПИН-код. У вас есть ${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
━━━━━━━━━━━━━━━━━━━━
${card.bankName.toUpperCase()}
━━━━━━━━━━━━━━━━━━━━
Номер: ${card.cardNumber}
CVV: ${card.cvv}
Владелец: ${card.holderName.toUpperCase()}
Срок действия: ${card.expiresDate}
━━━━━━━━━━━━━━━━━━━━
Попробуйте подобрать правильный ПИН-код. У вас есть ${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(
`💳 Брутфорс карты\n
━━━━━━━━━━━━━━━━━━━━
${card.bankName.toUpperCase()}
━━━━━━━━━━━━━━━━━━━━
Номер: ${card.cardNumber}
CVV: ${card.cvv}
Владелец: ${card.holderName.toUpperCase()}
Срок действия: ${card.expiresDate}
━━━━━━━━━━━━━━━━━━━━
✅ Взлом успешен! Вы получили Ð${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 = await InventoryModel.findAll({ where: { telegram_id: ctx.from.id } });
if (inventory.length === 0) {
return ctx.reply('Ваш инвентарь пуст.');
}
let message = '*Ваш инвентарь:*\n\n';
// Группируем предметы по их состоянию (снаряженные/обычные)
const equippedItems = inventory.filter((item) => item.equipped);
const unequippedItems = inventory.filter((item) => !item.equipped);
if (equippedItems.length > 0) {
message += '🛡️ *Снаряженные предметы:*\n';
equippedItems.forEach((item) => {
message += `- ${item.name} (${item.type})\n`;
});
message += '\n';
}
if (unequippedItems.length > 0) {
message += '🎒 *Предметы в инвентаре:*\n';
unequippedItems.forEach((item) => {
message += `- ${item.name} (${item.type})\n`;
});
message += '\n';
}
// Кнопки для взаимодействия
const buttons = [
...unequippedItems.map((item) =>
Markup.button.callback(`🎯 Использовать ${item.name}`, `use_item_${item.id}`)
),
...equippedItems.map((item) =>
Markup.button.callback(`🚫 Снять ${item.name}`, `unequip_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 item = await InventoryModel.findByPk(itemId);
if (!item || item.telegram_id != ctx.from.id) {
return ctx.reply('Этот предмет не найден в вашем инвентаре.');
}
const character = await CharacterModel.findByPk(ctx.from.id);
if (!character) {
return ctx.reply('Персонаж не найден.');
}
if (item.equipped) {
return ctx.reply(`${item.name} уже снаряжен.`);
}
// Применяем эффекты предмета
if (item.effectData) {
const resultMessages = processEffects(character, item.effectData, true);
await ctx.reply(resultMessages);
}
// Снаряжаем предмет
item.equipped = true;
await item.save();
ctx.reply(`Вы успешно снарядили ${item.name}.`);
});
rpg.action(/unequip_item_(\d+)/, async (ctx) => {
const itemId = parseInt(ctx.match[1], 10);
const character = await CharacterModel.findByPk(ctx.from.id);
const item = await InventoryModel.findByPk(itemId);
if (!item || item.telegram_id != ctx.from.id) {
return ctx.reply('Этот предмет не найден в вашем инвентаре.');
}
if (!item.equipped) {
return ctx.reply(`${item.name} не снаряжен.`);
}
if (item.effectData) {
const resultMessages = processEffects(character, item.effectData, false);
await ctx.reply(resultMessages);
}
item.equipped = false;
await item.save();
ctx.reply(`Вы успешно сняли ${item.name}.`);
});
rpg.action('shop', async (ctx) => {
const items = await ItemsModel.findAll();
if (items.length === 0) {
return ctx.reply('Магазин пуст!');
}
let message = 'Добро пожаловать в магазин! Здесь вы можете купить предметы:\n\n';
// Генерируем кнопки, каждая кнопка будет в отдельной строке
const buttons = items.map((item) => [
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 item = await ItemsModel.findByPk(itemId);
if (!item) {
return ctx.reply('Предмет не найден.');
}
const character = await CharacterModel.findByPk(ctx.from.id);
if (!character) {
return ctx.reply('Персонаж не найден.');
}
if (character.balance < item.price) {
return ctx.reply('У вас недостаточно средств для покупки этого предмета.');
}
// Снимаем деньги с баланса
character.balance -= item.price;
// Добавляем предмет в инвентарь
await InventoryModel.create({
telegram_id: ctx.from.id,
name: item.name,
description: item.description,
effectData: item.effectData,
price: item.price,
rarity: item.rarity,
type: item.type,
duration: item.duration,
equipped: false,
});
await character.save();
ctx.reply(`Вы успешно купили ${item.name} за ${item.price}₽!`);
});
////////////////////////////////////////////////////////////////////////////////////////////
CharacterModel.prototype.addEquippedItem = async function (item) {
// Проверяем, находится ли предмет в инвентаре персонажа
const inventoryItem = await InventoryModel.findOne({
where: { telegram_id: this.telegram_id, id: item.id },
});
if (!inventoryItem) {
throw new Error('Предмет не найден в вашем инвентаре.');
}
// Проверяем, не снаряжен ли уже этот предмет
if (inventoryItem.equipped) {
throw new Error('Этот предмет уже снаряжен.');
}
// Снаряжаем предмет
inventoryItem.equipped = true;
await inventoryItem.save();
// Применяем эффекты предмета
let resultMessages = [];
if (inventoryItem.effectData) {
resultMessages = processEffects(this, inventoryItem.effectData, true);
await this.save(); // Сохраняем изменения в характеристиках персонажа
}
return resultMessages;
};
CharacterModel.prototype.removeEquippedItem = async function (item) {
// Проверяем, находится ли предмет в инвентаре персонажа
const inventoryItem = await InventoryModel.findOne({
where: { telegram_id: this.telegram_id, id: item.id },
});
if (!inventoryItem || !inventoryItem.equipped) {
throw new Error('Этот предмет не снаряжен.');
}
// Снимаем предмет
inventoryItem.equipped = false;
await inventoryItem.save();
// Убираем эффекты предмета
let resultMessages = [];
if (inventoryItem.effectData) {
resultMessages = processEffects(this, inventoryItem.effectData, false);
await this.save(); // Сохраняем изменения в характеристиках персонажа
}
return resultMessages;
};
const processEffects = (character, effects, isEquipping) => {
let messages = [];
effects.forEach((effect) => {
if (!isEquipping) {
// Снимаем эффекты
switch (effect.type) {
case 'damage_boost':
character.force = Math.max(0, character.force - effect.amount);
character.save()
messages.push(`Ваш урон уменьшен на ${effect.amount}.`);
break;
case 'max_health_boost':
character.max_hp = Math.max(1, character.max_hp - effect.amount);
character.save()
messages.push(`Ваше максимальное здоровье уменьшено на ${effect.amount}.`);
break;
case 'stamina_penalty':
character.max_stamina += effect.amount;
character.save()
messages.push(`Ваша выносливость увеличена на ${effect.amount}.`);
break;
default:
messages.push('Неизвестный эффект при снятии.');
}
} else {
// Применяем эффекты
switch (effect.type) {
case 'heal':
character.hp = Math.min(character.max_hp, character.hp + effect.amount);
character.save()
messages.push(`Вы восстановили ${effect.amount} HP.`);
break;
case 'damage_boost':
character.force += effect.amount;
character.save()
messages.push(`Ваш урон увеличен на ${effect.amount}.`);
break;
case 'max_health_boost':
character.max_hp += effect.amount;
character.save()
messages.push(`Ваше максимальное здоровье увеличено на ${effect.amount}.`);
break;
case 'stamina_penalty':
character.max_stamina -= effect.amount;
character.save()
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;