Visual Enchancements
This commit is contained in:
Degradin 2025-01-12 23:44:41 +03:00
parent aac3c0f21c
commit 4f1e3943b4
2 changed files with 407 additions and 405 deletions

204
bot.js
View File

@ -3,7 +3,7 @@ const { Telegraf, Scenes, session, Markup, Stage } = require('telegraf');
const { Op } = require('sequelize'); const { Op } = require('sequelize');
const schedule = require('node-schedule'); const schedule = require('node-schedule');
const sequelize = require('./db'); // Подключение базы данных const sequelize = require('./db'); // Подключение базы данных
// Подключаем обработчики // Подключаем обработчики
const commands = require('./commands'); const commands = require('./commands');
const utils = require('./utils'); const utils = require('./utils');
const handlers = require('./handlers'); const handlers = require('./handlers');
@ -25,21 +25,21 @@ const {
SkillsModel, SkillsModel,
DailyModel DailyModel
} = global.config } = global.config
const bot = new Telegraf(process.env.BOT_TOKEN) const bot = new Telegraf(process.env.BOT_TOKEN)
const rpg = require('./rpg'); // Подключение RPG-механик const rpg = require('./rpg'); // Подключение RPG-механик
const crime = require('./scenes/crime') const crime = require('./scenes/crime')
const pocketsteal = require('./scenes/pocketsteal') const pocketsteal = require('./scenes/pocketsteal')
const shop = require('./scenes/shop') const shop = require('./scenes/shop')
const pve = require('./scenes/pve') const pve = require('./scenes/pve')
const newpve = require('./scenes/newpve') const newpve = require('./scenes/newpve')
const stage = new Scenes.Stage([crime, pocketsteal, shop, pve, newpve]); const stage = new Scenes.Stage([crime, pocketsteal, shop, pve, newpve]);
const start = async () => { const start = async () => {
try { try {
// Подключаемся к базе данных // Подключаемся к базе данных
await sequelize.authenticate(); await sequelize.authenticate();
console.log('Подключение к базе данных успешно!'); console.log('Подключение к базе данных успешно!');
// Синхронизация моделей, если нужно // Синхронизация моделей, если нужно
await sequelize.sync({ alter: true }); await sequelize.sync({ alter: true });
console.log('Синхронизация моделей завершена.'); console.log('Синхронизация моделей завершена.');
@ -52,29 +52,29 @@ const newpve = require('./scenes/newpve')
} }
bot.telegram.setMyCommands([{ bot.telegram.setMyCommands([{
command: "pay", command: "pay",
description: "Перевести указанному пользователю сумму." description: "Перевести указанному пользователю сумму."
}, },
{ {
command: "buy", command: "buy",
description: "Приобрести указанное имущество." description: "Приобрести указанное имущество."
}, },
{ {
command: "business", command: "business",
description: "Создать организацию." description: "Создать организацию."
}, },
{ {
command: "invite", command: "invite",
description: "Пригласить пользователя в организацию." description: "Пригласить пользователя в организацию."
}, },
{ {
command: "percent", command: "percent",
description: "Установить пользователю процент заработка." description: "Установить пользователю процент заработка."
}, },
{ {
command: "report", command: "report",
description: "Создать жалобу/обращение/идею." description: "Создать жалобу/обращение/идею."
} }
]) ])
bot.use(stage.middleware()) bot.use(stage.middleware())
@ -82,25 +82,25 @@ bot.use(rpg)
bot.use( bot.use(
session({ session({
getSessionKey: (ctx) => { getSessionKey: (ctx) => {
if ((ctx.from && ctx.chat && ctx.chat.id === ctx.from.id) || (!ctx.chat && ctx.from)) { if ((ctx.from && ctx.chat && ctx.chat.id === ctx.from.id) || (!ctx.chat && ctx.from)) {
return `user:${ctx.from.id}` return `user:${ctx.from.id}`
} else if (ctx.from && ctx.chat) { } else if (ctx.from && ctx.chat) {
return `${ctx.from.id}:${ctx.chat.id}` return `${ctx.from.id}:${ctx.chat.id}`
}
return ctx.update.update_id
} }
return ctx.update.update_id
}
}) })
) )
bot.use(stage) bot.use(stage)
bot.use(utils.stats) bot.use(utils.stats)
bot.use(async (ctx, next) => { bot.use(async (ctx, next) => {
bot.context.config = require('./ctxconfig.json') bot.context.config = require('./ctxconfig.json')
let id = ctx.from.id let id = ctx.from.id
let username = ctx.from.username let username = ctx.from.username
if(username == null) username = ctx.from.id if (username == null) username = ctx.from.id
switch(ctx.updateType){ switch (ctx.updateType) {
case `message`: case `message`:
console.log(utils.getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text) console.log(utils.getCurrentTime() + `: ` + username + `: ` + ctx.update.message.text)
break; break;
@ -124,9 +124,9 @@ bot.use(async (ctx, next) => {
name: ctx.from.first_name name: ctx.from.first_name
}) })
} else { } else {
user.name = ctx.from.first_name user.name = ctx.from.first_name
if(user.username === null) user.username = ctx.from.id if (user.username === null) user.username = ctx.from.id
user.save() user.save()
} }
if (property === null) { if (property === null) {
await PropertyModel.create({ await PropertyModel.create({
@ -145,45 +145,45 @@ bot.use(async (ctx, next) => {
//if (whitelist.includes(id) == false) return ctx.reply(`У вас пока нет доступа к боту. Следите за обновлениями в группе: t.me/CampFireGameBotNews`) //if (whitelist.includes(id) == false) return ctx.reply(`У вас пока нет доступа к боту. Следите за обновлениями в группе: t.me/CampFireGameBotNews`)
if (block) { if (block) {
const currentTime = Math.trunc(Date.now() / 1000); // Получаем текущее время в секундах const currentTime = Math.trunc(Date.now() / 1000); // Получаем текущее время в секундах
if (block.isBlocked && block.time > currentTime) { if (block.isBlocked && block.time > currentTime) {
const remainingTime = Math.trunc((block.time - currentTime) / 60); // Рассчитываем оставшееся время const remainingTime = Math.trunc((block.time - currentTime) / 60); // Рассчитываем оставшееся время
return ctx.reply( return ctx.reply(
`📛 У вас активная блокировка по причине: ${block.reason}.\n⏲️ Оставшееся время: ${remainingTime} мин.` `📛 У вас активная блокировка по причине: ${block.reason}.\n⏲️ Оставшееся время: ${remainingTime} мин.`
); );
} }
// Если блокировка истекла или отключена // Если блокировка истекла или отключена
block.isBlocked = false; block.isBlocked = false;
await block.save(); // Обязательно используем `await` для сохранения изменений await block.save(); // Обязательно используем `await` для сохранения изменений
} }
const start = Date.now() const start = Date.now()
const timeoutPromise = new Promise((resolve, reject) => { const timeoutPromise = new Promise((resolve, reject) => {
setTimeout(() => { setTimeout(() => {
reject(new Error('timeout')) reject(new Error('timeout'))
}, 1000 * 5) }, 1000 * 5)
}) })
const nextPromise = next() const nextPromise = next()
.then(() => { .then(() => {
const ms = Date.now() - start const ms = Date.now() - start
}) })
.catch((error) => {
handleError(error, ctx)
})
return Promise.race([timeoutPromise, nextPromise])
.catch((error) => { .catch((error) => {
if (error.message === 'timeout') { handleError(error, ctx)
console.error('timeout', ctx.update)
return false
}
return true
}) })
return Promise.race([timeoutPromise, nextPromise])
.catch((error) => {
if (error.message === 'timeout') {
console.error('timeout', ctx.update)
return false
}
return true
})
}) })
bot.command('start', async (ctx) => { bot.command('start', async (ctx) => {
@ -221,7 +221,7 @@ bot.hears('Криминал', async (ctx) => {
}) })
bot.hears('промка', async(ctx) => { bot.hears('промка', async (ctx) => {
generatePromo() generatePromo()
}); });
@ -343,13 +343,13 @@ bot.action(/{"action": "sueta_*/, async (ctx) => {
console.log(data.car) console.log(data.car)
let user = await UserModel.findByPk(ctx.from.id) let user = await UserModel.findByPk(ctx.from.id)
let property = await PropertyModel.findByPk(ctx.from.id) let property = await PropertyModel.findByPk(ctx.from.id)
switch(data.action){ switch (data.action) {
case `sueta_accept`: case `sueta_accept`:
user.money += data.carprice user.money += data.carprice
await ctx.editMessageText(` ${data.carprice}`) await ctx.editMessageText(` ${data.carprice}`)
break; break;
case `sueta_refuse`: case `sueta_refuse`:
user.money += Math.round(property.car.price/2) user.money += Math.round(property.car.price / 2)
property.car = { property.car = {
name: data.carname, name: data.carname,
price: data.carprice price: data.carprice
@ -440,7 +440,7 @@ bot.command('daily_bonus', async (ctx) => {
message += `🏗 Материалы: ${reward.materials}\n`; message += `🏗 Материалы: ${reward.materials}\n`;
} else { } else {
totalMoney += reward.materials; // Материалы заменяются на деньги totalMoney += reward.materials; // Материалы заменяются на деньги
} }
// Добавляем деньги // Добавляем деньги
user.money += totalMoney; user.money += totalMoney;
@ -502,14 +502,14 @@ bot.hears('🏗️ Предприятия', async (ctx) => {
bot.action('enterprise_menu', async (ctx) => { bot.action('enterprise_menu', async (ctx) => {
const user = await UserModel.findByPk(ctx.from.id); const user = await UserModel.findByPk(ctx.from.id);
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } }); const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
const enterprises = await EnterpriseModel.findAll({ const enterprises = await EnterpriseModel.findAll({
where: { playerId: user.telegram_id } where: { playerId: user.telegram_id }
}); });
let message = `🏗️ Меню предприятий:\n`; let message = `🏗️ Меню предприятий:\n`;
message += `У вас: ${enterprises.length} предприятий.\n`; message += `У вас: ${enterprises.length} предприятий.\n`;
message += warehouse message += warehouse
? `🗄️ Единый склад: Доступен (Ёмкость: ${warehouse.capacity} ед.)\n` ? `🗄️ Единый склад: Доступен (Ёмкость: ${warehouse.capacity} ед.)\n`
: `🗄️ Единый склад: Не построен.\n`; : `🗄️ Единый склад: Не построен.\n`;
@ -553,11 +553,11 @@ bot.action('my_enterprises', async (ctx) => {
return await ctx.reply('У вас нет предприятий.'); return await ctx.reply('У вас нет предприятий.');
} }
let metallPrice = await ResourcePriceModel.findOne({ let metallPrice = await ResourcePriceModel.findOne({
where: { resource: "metall" } where: { resource: "metall" }
}); });
let message = `🏭 Мои предприятия:\n\n`; let message = `🏭 Мои предприятия:\n\n`;
const buttons = []; const buttons = [];
for (const enterprise of enterprises) { for (const enterprise of enterprises) {
const { id, name, level, efficiency, currentResources, resourceType, warehouseCapacity } = enterprise; const { id, name, level, efficiency, currentResources, resourceType, warehouseCapacity } = enterprise;
const resourcePrice = await ResourcePriceModel.findOne({ const resourcePrice = await ResourcePriceModel.findOne({
@ -574,7 +574,7 @@ bot.action('my_enterprises', async (ctx) => {
if (!truck) { if (!truck) {
enterpriseButtons.push({ text: `🛻 ID: ${id}`, callback_data: `hire_truck_${id}` }); enterpriseButtons.push({ text: `🛻 ID: ${id}`, callback_data: `hire_truck_${id}` });
}else{ } else {
enterpriseButtons.push({ text: `🚛 ID: ${id}`, callback_data: `upgrade_truck_${id}` }); enterpriseButtons.push({ text: `🚛 ID: ${id}`, callback_data: `upgrade_truck_${id}` });
} }
@ -586,7 +586,7 @@ bot.action('my_enterprises', async (ctx) => {
buttons.push(enterpriseButtons); buttons.push(enterpriseButtons);
} }
message += `\n\n📈 - Улучшить\n🛻 - Купить грузовик [~${utils.spaces(metallPrice.price*700)} руб.]\n🚛 - Улучшить грузовик\n💰 - Продать ресурсы с предприятия\n🔄 - Перевезти все на склад` message += `\n\n📈 - Улучшить\n🛻 - Купить грузовик [~${utils.spaces(metallPrice.price * 700)} руб.]\n🚛 - Улучшить грузовик\n💰 - Продать ресурсы с предприятия\n🔄 - Перевезти все на склад`
buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]); buttons.push([{ text: '⬅️ Назад', callback_data: 'enterprise_menu' }]);
return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize()); return await ctx.editMessageText(message, Markup.inlineKeyboard(buttons).resize());
@ -605,7 +605,7 @@ bot.action('build_enterprise', async (ctx) => {
}); });
if (enterprises.length >= 5) { if (enterprises.length >= 5) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Вы достигли максимального числа предприятий.', {show_alert: true}); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Вы достигли максимального числа предприятий.', { show_alert: true });
} }
// Получаем текущие цены из базы данных // Получаем текущие цены из базы данных
@ -642,7 +642,7 @@ bot.action(/build_(wood|coal|oil|metall|gold|diamond)/, async (ctx) => {
let user = await UserModel.findByPk(ctx.from.id) let user = await UserModel.findByPk(ctx.from.id)
let data = ctx.update.callback_query.data let data = ctx.update.callback_query.data
let type = data.split('_')[1] let type = data.split('_')[1]
// Получаем текущие цены из базы данных // Получаем текущие цены из базы данных
const resourcePrice = await ResourcePriceModel.findOne({ const resourcePrice = await ResourcePriceModel.findOne({
@ -652,7 +652,7 @@ bot.action(/build_(wood|coal|oil|metall|gold|diamond)/, async (ctx) => {
// Проверка, есть ли достаточно денег у пользователя // Проверка, есть ли достаточно денег у пользователя
if (user.money < price) { if (user.money < price) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для постройки предприятия. Необходимо ${price} руб.`, {show_alert: true}) return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для постройки предприятия. Необходимо ${price} руб.`, { show_alert: true })
} }
// Строим предприятие // Строим предприятие
@ -784,7 +784,7 @@ bot.action('transfer_resources', async (ctx) => {
const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } }); const warehouse = await WarehouseModel.findOne({ where: { playerId: user.telegram_id } });
if (!warehouse) { if (!warehouse) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id,'У вас нет единого склада.'); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'У вас нет единого склада.');
} }
const enterprises = await EnterpriseModel.findAll({ const enterprises = await EnterpriseModel.findAll({
@ -814,20 +814,20 @@ bot.action(/transfer_from_(\d+)/, async (ctx) => {
const { currentResources, resourceType, playerId } = enterprise; const { currentResources, resourceType, playerId } = enterprise;
if (currentResources === 0) { if (currentResources === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для перевода.'); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для перевода.');
} }
const warehouse = await WarehouseModel.findOne({ where: { playerId } }); const warehouse = await WarehouseModel.findOne({ where: { playerId } });
if (!warehouse) { if (!warehouse) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'У вас нет склада для перевода ресурсов.'); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'У вас нет склада для перевода ресурсов.');
} }
const freeCapacity = warehouse.capacity - getWarehouseUsedCapacity(warehouse); const freeCapacity = warehouse.capacity - getWarehouseUsedCapacity(warehouse);
const transferAmount = Math.min(currentResources, freeCapacity); const transferAmount = Math.min(currentResources, freeCapacity);
if (transferAmount === 0) { if (transferAmount === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Склад заполнен. Перевод невозможен.'); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Склад заполнен. Перевод невозможен.');
} }
// Перевод ресурсов // Перевод ресурсов
@ -873,7 +873,7 @@ bot.action(/upgrade_(\d+)/, async (ctx) => {
}); });
let upgradeCost = resourcePrice.price * 1.5 * 10 * 24 * 7 // Стоимость улучшения зависит от уровня let upgradeCost = resourcePrice.price * 1.5 * 10 * 24 * 7 // Стоимость улучшения зависит от уровня
if (user.money < upgradeCost) { if (user.money < upgradeCost) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для прокачки предприятия. Необходимо ${upgradeCost} руб.`) return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас недостаточно средств для прокачки предприятия. Необходимо ${upgradeCost} руб.`)
} }
// Прокачка: повышение уровня и эффективности // Прокачка: повышение уровня и эффективности
@ -994,7 +994,7 @@ bot.action(/sell_all_(\d+)/, async (ctx) => {
const totalPrice = currentResources * resourcePrice.price; const totalPrice = currentResources * resourcePrice.price;
if (currentResources === 0) { if (currentResources === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.'); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.');
} }
await ctx.reply( await ctx.reply(
@ -1021,7 +1021,7 @@ bot.action(/confirm_ressell_(\d+)/, async (ctx) => {
const totalPrice = currentResources * resourcePrice.price; const totalPrice = currentResources * resourcePrice.price;
if (currentResources === 0) { if (currentResources === 0) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.'); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'На предприятии нет ресурсов для продажи.');
} }
// Обновление баланса игрока // Обновление баланса игрока
@ -1038,7 +1038,7 @@ bot.action(/confirm_ressell_(\d+)/, async (ctx) => {
); );
// Гарантируем, что цена не упадет ниже 50% от базовой цены // Гарантируем, что цена не упадет ниже 50% от базовой цены
resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5)); resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
await resourcePrice.save(); await resourcePrice.save();
updateResourcePricesMessage(); updateResourcePricesMessage();
await ctx.editMessageText(`Вы успешно продали ${currentResources} ед. ${getEnterpriseEmoji(resourceType)} за ${totalPrice} руб.`); await ctx.editMessageText(`Вы успешно продали ${currentResources} ед. ${getEnterpriseEmoji(resourceType)} за ${totalPrice} руб.`);
@ -1093,7 +1093,7 @@ bot.command('sellstorage', async (ctx) => {
// Гарантируем, что цена не упадет ниже 50% от базовой цены // Гарантируем, что цена не упадет ниже 50% от базовой цены
resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5)); resourcePrice.price = Math.max(resourcePrice.price, Math.round(resourcePrice.basePrice * 0.5));
await resourcePrice.save(); await resourcePrice.save();
updateResourcePricesMessage(); updateResourcePricesMessage();
return await ctx.reply( return await ctx.reply(
@ -1119,16 +1119,16 @@ bot.action(/hire_truck_(\d+)/, async (ctx) => {
}); });
if (existingTruck) { if (existingTruck) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас уже есть грузовик для предприятия ${enterprise.name}.`); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `У вас уже есть грузовик для предприятия ${enterprise.name}.`);
} }
const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: 'metall' } }); const resourcePrice = await ResourcePriceModel.findOne({ where: { resource: 'metall' } });
if (!resourcePrice) { if (!resourcePrice) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Не удалось получить цену ресурса.'); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, 'Не удалось получить цену ресурса.');
} }
if (user.money < resourcePrice.price*700) { if (user.money < resourcePrice.price * 700) {
return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Недостаточно средств. Стоимость грузовика: ${utils.spaces(resourcePrice.price*700)} руб.`); return await ctx.telegram.answerCbQuery(ctx.callbackQuery.id, `Недостаточно средств. Стоимость грузовика: ${utils.spaces(resourcePrice.price * 700)} руб.`);
} }
await user.update({ money: user.money - (resourcePrice.price*700) }) await user.update({ money: user.money - (resourcePrice.price * 700) })
// Создаем новый грузовик // Создаем новый грузовик
const newTruck = await TruckModel.create({ const newTruck = await TruckModel.create({
enterpriseId: enterprise.id, enterpriseId: enterprise.id,
@ -1190,12 +1190,12 @@ const recoverResourcePrices = async () => {
if (resource.price > resource.basePrice * 2.1) { if (resource.price > resource.basePrice * 2.1) {
resource.price = Math.round(resource.basePrice * 0.79764918); // Устанавливаем цену на уровне 1.5 базовой resource.price = Math.round(resource.basePrice * 0.79764918); // Устанавливаем цену на уровне 1.5 базовой
} }
// Гарантируем, что цена остаётся в диапазоне [50% basePrice, 150% basePrice] // Гарантируем, что цена остаётся в диапазоне [50% basePrice, 150% basePrice]
resource.price = Math.max(resource.price, Math.round(resource.basePrice * 0.5)); // Минимум resource.price = Math.max(resource.price, Math.round(resource.basePrice * 0.5)); // Минимум
resource.price = Math.min(resource.price, Math.round(resource.basePrice * 3)); // Максимум resource.price = Math.min(resource.price, Math.round(resource.basePrice * 3)); // Максимум
await resource.save(); // Сохраняем после всех корректировок await resource.save(); // Сохраняем после всех корректировок
} }
}; };
@ -1408,7 +1408,7 @@ schedule.scheduleJob('5 * * * *', resourceTransportation); // Каждый ча
bot.command('force_prod', async (ctx) => { bot.command('force_prod', async (ctx) => {
resourceProduction() resourceProduction()
return await ctx.reply(`Принудительно добыто.`) return await ctx.reply(`Принудительно добыто.`)
}) })
@ -1447,7 +1447,7 @@ const spinSlots = async (ctx, bet, user) => {
let resultMessage = `🎰 Итог:\n${finalIcons.join(' | ')}\n\n`; let resultMessage = `🎰 Итог:\n${finalIcons.join(' | ')}\n\n`;
if (winMultiplier > 0) { if (winMultiplier > 0) {
const winnings = bet * winMultiplier; const winnings = bet * winMultiplier;
utils.giveExp(user, winMultiplier*10) utils.giveExp(user, winMultiplier * 10)
user.money += winnings; user.money += winnings;
await user.save(); await user.save();
console.log(`Win: ${winnings}`) console.log(`Win: ${winnings}`)
@ -1574,7 +1574,7 @@ bot.hears('🎰 Рулетка', async (ctx) => {
const redNumbers = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35]; const redNumbers = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35];
// Все четные числа (черные) // Все четные числа (черные)
const blackNumbers = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36]; const blackNumbers = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36];
// Рулетка: делаем случайный выбор // Рулетка: делаем случайный выбор
const randomIndex = Math.floor(Math.random() * 37); // от 0 до 36 const randomIndex = Math.floor(Math.random() * 37); // от 0 до 36
return randomIndex; return randomIndex;

608
rpg.js

File diff suppressed because it is too large Load Diff