CampFirePlay/rpg.js
2025-01-08 20:01:54 +03:00

568 lines
23 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 { Op } = require('sequelize');
const sequelize = require('./db'); // Подключение базы данных
// Подключаем обработчики
const utils = require('./utils');
const handlers = require('./handlers');
const {
UserModel,
CharacterModel,
WorldModel,
JobModel,
PropertyModel,
AFKPropertyModel,
BusinessModel,
ReportModel,
BlockModel,
PromocodeModel,
EnterpriseModel,
WarehouseModel,
TruckModel,
SaleModel,
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
switch(ctx.updateType){
case `message`:
console.log(utils.getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text)
break;
case `callback_query`:
console.log(utils.getCurrentTime() + `: ${username}: ${ctx.update.callback_query.data}`)
break;
default:
console.log(ctx)
}
const start = Date.now()
const timeoutPromise = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('timeout'))
}, 1000 * 5)
})
const nextPromise = next()
.then(() => {
const ms = Date.now() - start
})
.catch((error) => {
handleError(error, ctx)
})
return Promise.race([timeoutPromise, nextPromise])
.catch((error) => {
if (error.message === 'timeout') {
console.error('timeout', ctx.update)
return false
}
return true
})
})
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 } });
if (!character) {
return ctx.reply('Персонаж не найден. Создайте нового персонажа, чтобы начать игру!');
}
// Формируем профиль
const profile = `
🎭 Профиль персонажа:
👤 Имя: ${character.name || 'Не указано'}
🏆 Уровень: ${character.level} (${character.exp}/${character.level * 100} опыта)
❤️ Здоровье: ${character.hp}/${character.max_hp}
💪 Сила (F): ${character.force}
🧠 Интеллект (I): ${character.intelligence}
🛡️ Устойчивость (R): ${character.resilience}
🔋 Выносливость (E): ${character.endurance}
🔥 Стамина: ${character.stamina}/${character.max_stamina}
💰 Грязные деньги: ${character.dirtymoney}
🃏 Карточки: ${character.stealedcards}
🎒 Инвентарь (${character.inventory.length}/10): ${character.inventory.map((item) => item.name).join(', ') || 'Пусто'}
`;
// Отправляем сообщение
ctx.reply(profile.trim(), Markup.inlineKeyboard([
[Markup.button.callback('💼 Задачи', 'crime_missions')],
]));
});
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Хранилище для отслеживания пользователей, которые уже прошли ввод
const usersCrimeNet = new Set();
const usersLocks = new Set();
rpg.hears('CampFireGG.Crime', async (ctx) => {
const userId = ctx.from.id;
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 Crime.net...');
// Симуляция показа строки 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);
await ctx.telegram.editMessageText(
sentMessage.chat.id,
sentMessage.message_id,
undefined,
`🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`,
Markup.inlineKeyboard([
[Markup.button.callback('💼 Задачи', 'crime_missions')],
[Markup.button.callback('📊 Профиль', 'rpg_profile')],
[Markup.button.callback('💰 ...', 'crime_market')],
])
)} else {
// Показываем только меню, если команда уже была введена
await ctx.reply(
`🚨 Добро пожаловать в CampFireGG.Crime 🚨\n\n`,
Markup.inlineKeyboard([
[Markup.button.callback('💼 Задачи', 'crime_missions')],
[Markup.button.callback('📊 Профиль', 'rpg_profile')],
[Markup.button.callback('💰 ...', 'crime_market')],
])
);
}
});
// Обработчики кнопок
rpg.action('crime_missions', async (ctx) => {
await ctx.answerCbQuery();
await ctx.editMessageText(`💼 **Задачи:**\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 = 20; // Базовый шанс
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
if (randomRoll > chance) {
return ctx.editMessageText('Вы были замечены во время кражи.');
}
// Успешная кража
let moneyIn = utils.rand(5, 1000);
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) return ctx.editMessageText('Вы были замечены во время кражи.');
let randPhone = utils.rand(1,10)
if (property.mobile.name) {
let dirtyMoney = Math.round(phones[randPhone].price/100*70)
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 = 20; // Базовый шанс
let chance = baseChance + character.intelligence * 2; // Увеличиваем шанс на 2% за каждый пункт "Разума".
let randomRoll = utils.rand(0, 100); // Случайное число от 0 до 100
if(chance < randomRoll) return ctx.editMessageText('Вы были замечены во время кражи.');
let moneyIn = utils.rand(1000, 10000)
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) return ctx.editMessageText('Вы были замечены во время кражи.');
character.stealedcards += 1
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) 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;
}
}
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(
`💻 **Crime.net Menu**`,
Markup.inlineKeyboard([
[Markup.button.callback('💼 Задачи', 'crime_missions')],
[Markup.button.callback('📊 Профиль', 'crime_stats')],
[Markup.button.callback('💰 ...', 'crime_market')],
])
);
});
rpg.action('SHOP_ACTION', async (ctx) => {
console.log('1')
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.weapon == 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(6,15);i++){
setTimeout(() => {
cashIn += utils.rand(1000, 10000)
ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`)
}, timer)
timer += 500
}
setTimeout(() => {
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) {
return ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация. Вы сбежали.')
}
ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация.')
for(i=0; i<utils.rand(3,10);i++){
setTimeout(() => {
cashIn += utils.rand(500, 5000)
ctx.editMessageText(`⏏️ Вы в спешке достали из кассы: Ð${utils.spaces(cashIn)}`)
}, timer)
timer += 500
}
setTimeout(() => {
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(6,15);i++){
setTimeout(() => {
cashIn += utils.rand(3000, 10000)
ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${utils.spaces(cashIn)}`)
}, timer)
timer += 500
}
setTimeout(() => {
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);
});
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));
}
// Восстановление здоровья (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();
}
}
// Периодическое выполнение задач
function startRecoveryIntervals() {
const interval = 5 * 1000; // Интервал в миллисекундах (например, 1 минута)
setInterval(recoverHealth, interval);
setInterval(recoverStamina, interval);
}
startRecoveryIntervals()
module.exports = rpg;