diff --git a/bot.js b/bot.js index babc871..9470767 100644 --- a/bot.js +++ b/bot.js @@ -24,6 +24,7 @@ const { ReportModel, BlockModel, PromocodeModel, + SkillsModel, mainChat, adminList, expToUp, @@ -67,7 +68,11 @@ const { fastblock, createPromo, genPromo, - organizationCreate + organizationCreate, + shot, + outmenu, + lobbyCreate, + lobbyMenu } = require('./commands') const { spaces, @@ -88,24 +93,42 @@ const { const { handleError } = require('./handlers') -const crimeScene = require("./scenes/crime"); -const heistScene = require("./scenes/heist"); -const sequelize = require('./db'); -const { Op } = require('sequelize'); -const fs = require('fs'); -const { createCanvas, loadImage } = require('canvas'); -const shortid = require('shortid'); -const voucher_codes = require('voucher-code-generator'); -const bot = new Telegraf(process.env.BOT_TOKEN) -const stage = new Scenes.Stage([crimeScene, heistScene]); + const sequelize = require('./db'); + const { Op } = require('sequelize'); + const fs = require('fs'); + const { createCanvas, loadImage } = require('canvas'); + const shortid = require('shortid'); + const voucher_codes = require('voucher-code-generator'); + const bot = new Telegraf(process.env.BOT_TOKEN) + const crime = require('./scenes/crime') + const pocketsteal = require('./scenes/pocketsteal') + const shop = require('./scenes/shop') + const pve = require('./scenes/pve') + const stage = new Scenes.Stage([crime, pocketsteal, shop, pve]); -const start = async () => { + const start = async () => { try { await sequelize.authenticate() await sequelize.sync() + } catch (e) { console.log('Подключение к бд сломалось', e) } + try { + await sequelize.authenticate() + await UserModel.sync({ alter: true }) + await WorldModel.sync({ alter: true }) + await JobModel.sync({ alter: true }) + await PropertyModel.sync({ alter: true }) + await BusinessModel.sync({ alter: true }) + await ReportModel.sync({ alter: true }) + await BlockModel.sync({ alter: true }) + await PromocodeModel.sync() + await SkillsModel.sync({ alter: true }) + console.log('Синхронизация завершена',) + } catch (error) { + console.log('Ошибка синхронизации', error) + } } bot.telegram.setMyCommands([{ @@ -134,8 +157,21 @@ bot.telegram.setMyCommands([{ } ]) -bot.use(session({ collectionName: 'sessions' })); bot.use(stage.middleware()) + +bot.use( + session({ + getSessionKey: (ctx) => { + if ((ctx.from && ctx.chat && ctx.chat.id === ctx.from.id) || (!ctx.chat && ctx.from)) { + return `user:${ctx.from.id}` + } else if (ctx.from && ctx.chat) { + return `${ctx.from.id}:${ctx.chat.id}` + } + return ctx.update.update_id + } + }) + ) + bot.use(stage) bot.use(stats) bot.use(async (ctx, next) => { @@ -156,6 +192,7 @@ bot.use(async (ctx, next) => { let user = await UserModel.findByPk(id); let block = await BlockModel.findByPk(id); let property = await PropertyModel.findByPk(id); + let skill = await SkillsModel.findByPk(ctx.from.id) if (!user) ctx.reply(`❕ Первичная регистрация профиля.`); if (user === null) { await UserModel.create({ @@ -172,7 +209,16 @@ bot.use(async (ctx, next) => { await PropertyModel.create({ telegram_id: id }) - } else {} + } + if (skill === null) { + await SkillsModel.create({ + telegram_id: id, + stealing: { + level: 1, + exp: 0 + } + }) + } //if (whitelist.includes(id) == false) return ctx.reply(`У вас пока нет доступа к боту. Следите за обновлениями в группе: t.me/CampFireGameBotNews`) if (block !== null) { if (block.isBlocked == true && block.time > Date.now() / 1000) return ctx.reply(`📛 У вас активная блокировка по причине: ${block.reason}.\n⏲️ Оставшееся время: ${Math.trunc((block.time - Date.now()/1000)/60)} мин.`) diff --git a/commands/profile.js b/commands/profile.js index dac1476..7d6ef3a 100644 --- a/commands/profile.js +++ b/commands/profile.js @@ -21,12 +21,14 @@ module.exports = async (ctx) => { 💰 Баланс ₽${spacesWithMarkdown(user.money)} + Ð${spacesWithMarkdown(user.dirtymoney)} + 💳: ${user.stealedcards} 🔵 Имущество 🏠 Жилье: ${property.house == 0 ? "Бездомный" : property.house.name} 🚗 Автомобиль: ${property.car == 0 ? "Пешком" : escape(property.car.name)} 📱 Телефон: ${property.mobile == 0 ? "Нет" : property.mobile.name} - 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : property.weapon.name} + 🔫 Оружие: ${property.weapon == 0 ? "Безоружный" : escape(property.weapon.name)} 🥼 Экипировка: ${property.equipment == 0 ? "Нет" : property.equipment.name} `); } \ No newline at end of file diff --git a/commands/property/hatkeisList.js b/commands/property/hatkeisList.js index b536b71..412ad89 100644 --- a/commands/property/hatkeisList.js +++ b/commands/property/hatkeisList.js @@ -1,3 +1,6 @@ +const { + Markup +} = require('telegraf') const { weaponshop } = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') @@ -8,11 +11,22 @@ const { } = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils') module.exports = async (ctx) => { - let text = `[Hatkeis Gunsmith](https://telegra.ph/Hatkeis-Gunsmith-09-27)` + let text = `[Hatkeis Gunsmith](https://telegra.ph/Hatkeis-Gunsmith-09-27)\n` let shop = `\n Вы подходите к зданию с вывеской "Ништяки Хаткейса".\n Вот ассортимент на сегодня\n` - for (i = 0; i < 10; i++) { - shop += `${i}. ${weaponshop[i].name} (₽${spaces(weaponshop[i].price)})\n` + let prodArray = [] + for (i in weaponshop) { + prodArray.push({text: i, callback_data: `{"action": "buy", "type": "equipment", "value": "${i}"}`}) + shop += `${i}. ${weaponshop[i].name} (¤${spaces(weaponshop[i].price)})\n` } - weaponShopUpdate() - return await ctx.replyWithMarkdownV2(text + escape(shop), {disable_web_page_preview: true}) + prodArray.push({text: `Назад`, callback_data: `shopmenu`}) + let rows = [] + while (prodArray.length > 0) { + rows.push(prodArray.splice(0, 5)) // разбиваем на подмассивы по 5 кнопок + } + return await ctx.replyWithMarkdownV2(text + escape(shop), + { + reply_markup: { + inline_keyboard: rows + }, + disable_web_page_preview: true}) } \ No newline at end of file diff --git a/config/index.js b/config/index.js index 3e8a5e5..5626216 100644 --- a/config/index.js +++ b/config/index.js @@ -1,5 +1,4 @@ module.exports = { - testScene : require("../scenes/test"), weaponshop : require('../json/weaponshop.json'), slots : require('../json/slots.json'), rarecars : require('../json/rarecars.json'), @@ -17,10 +16,10 @@ module.exports = { ReportModel : require('../models/report.model'), BlockModel : require('../models/block.model'), PromocodeModel : require('../models/promocode.model'), + SkillsModel: require('../models/skills.model'), + LobbyModel: require('../models/lobby.model'), mainChat : -1001895132127, adminList : [275416286], expToUp : [0, 10, 20, 40, 60, 100, 250, 370, 450, 575, 666, 777, 860, 999, 1000, 1177, 1234, 1350, 1488, 1515, 1610], topSym : ['🥇', '🥈', '🥉', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'], - promoTopicId: 1807, - gameTopicId: 1808 } \ No newline at end of file diff --git a/json/weaponshop.json b/json/weaponshop.json index dea5b33..39e09fa 100644 --- a/json/weaponshop.json +++ b/json/weaponshop.json @@ -1,56 +1,56 @@ { "0": { - "name": "HK UMP", - "price": 33999, - "damage": 0.028, + "name": "G36C", + "price": 38999, + "damage": 0.035, "type": "weapon" }, "1": { - "name": "Glock 17", - "price": 7999, - "damage": 0.013, - "type": "weapon" - }, - "2": { - "name": "HK UMP", - "price": 33999, - "damage": 0.028, - "type": "weapon" - }, - "3": { - "name": "АКС74У", - "price": 34999, - "damage": 0.031, - "type": "weapon" - }, - "4": { "name": "M1911", "price": 13000, "damage": 0.018, "type": "weapon" }, + "2": { + "name": "АК101", + "price": 49999, + "damage": 0.04, + "type": "weapon" + }, + "3": { + "name": "ТТ", + "price": 12000, + "damage": 0.15, + "type": "weapon" + }, + "4": { + "name": "ПП19 `Бизон`", + "price": 24999, + "damage": 0.023, + "type": "weapon" + }, "5": { - "name": "Шлем танкиста", + "name": "Бронежилет M2", "price": 1000, "type": "equipment" }, "6": { - "name": "Бронежилет M5", + "name": "Бронежилет M6", "price": 1000, "type": "equipment" }, "7": { - "name": "Бронежилет M4", + "name": "Картонные накладки", "price": 1000, "type": "equipment" }, "8": { - "name": "Бронежилет M5", + "name": "Бронежилет M2", "price": 1000, "type": "equipment" }, "9": { - "name": "Кольчуга", + "name": "Бронежилет M5", "price": 1000, "type": "equipment" } diff --git a/media/image.png b/media/image.png index facd116..4e95ab3 100644 Binary files a/media/image.png and b/media/image.png differ diff --git a/models/lobby.model.js b/models/lobby.model.js new file mode 100644 index 0000000..b862f83 --- /dev/null +++ b/models/lobby.model.js @@ -0,0 +1,12 @@ +const sequelize = require('../db'); +const {DataTypes} = require('sequelize'); + +const Lobby = sequelize.define('lobby', { + id: {type: DataTypes.INTEGER, primaryKey: true, unique: true, autoIncrement: true}, + name: {type: DataTypes.STRING, defaultValue: "Неидентифицированное лобби"}, + leader: {type: DataTypes.BIGINT, defaultValue: 0}, + bank: {type: DataTypes.INTEGER, defaultValue: 0}, + users: {type: DataTypes.ARRAY(DataTypes.BIGINT)} +}) + +module.exports = Lobby; diff --git a/models/skills.model.js b/models/skills.model.js new file mode 100644 index 0000000..44ac9a1 --- /dev/null +++ b/models/skills.model.js @@ -0,0 +1,16 @@ +const sequelize = require('../db'); +const {DataTypes} = require('sequelize'); + +const Skills = sequelize.define('skills', { + telegram_id: {type: DataTypes.BIGINT, primaryKey: true, unique: true}, + stealing: {type: DataTypes.JSON, defaultValue: { + level: 1, + exp: 0 + }}, + lockpick: {type: DataTypes.JSON, defaultValue: { + level: 1, + exp: 0 + }} +}) + +module.exports = Skills; diff --git a/models/user.model.js b/models/user.model.js index 0c08407..21b6cdb 100644 --- a/models/user.model.js +++ b/models/user.model.js @@ -7,8 +7,12 @@ const User = sequelize.define('user', { name: {type: DataTypes.STRING}, status: {type: DataTypes.STRING, defaultValue: 'user'}, level: {type: DataTypes.INTEGER, defaultValue: 1}, + hp: {type: DataTypes.INTEGER, defaultValue: 100}, + armor: {type: DataTypes.INTEGER, defaultValue: 0}, exp: {type: DataTypes.INTEGER, defaultValue: 0}, money: {type: DataTypes.INTEGER, defaultValue: 0}, + dirtymoney: {type: DataTypes.INTEGER, defaultValue: 0}, + stealedcards: {type: DataTypes.INTEGER, defaultValue: 0}, bonus: {type: DataTypes.INTEGER, defaultValue: 0}, bonustime: {type: DataTypes.INTEGER, defaultValue: 0}, job: {type: DataTypes.INTEGER, defaultValue: 0}, @@ -21,7 +25,9 @@ const User = sequelize.define('user', { } }, worktime: {type: DataTypes.INTEGER, defaultValue: 0}, - slottime: {type: DataTypes.INTEGER, defaultValue: 0} + slottime: {type: DataTypes.INTEGER, defaultValue: 0}, + shoprobcd: {type: DataTypes.INTEGER, defaultValue: 0}, + pocketstealcd: {type: DataTypes.INTEGER, defaultValue: 0} }) module.exports = User; diff --git a/presets/weapons.json b/presets/weapons.json index fc68af6..fd6b1be 100644 --- a/presets/weapons.json +++ b/presets/weapons.json @@ -2,81 +2,103 @@ "1": { "name": "ТТ", "price": 12000, + "damage": 0.15, "type": "weapon" }, "2": { "name": "Glock 17", "price": 7999, + "damage": 0.013, "type": "weapon" }, "3": { "name": "G36C", "price": 38999, + "damage": 0.035, "type": "weapon" }, "4": { "name": "M1911", "price": 13000, + "damage": 0.018, "type": "weapon" }, "5": { "name": "ПМ", "price": 13000, + "damage": 0.01, "type": "weapon" }, "6": { "name": "SIG MCX .300", "price": 133999, + "damage": 0.066, "type": "weapon" }, "7": { "name": "АК101", "price": 49999, + "damage": 0.04, "type": "weapon" }, "8": { "name": "HK UMP", "price": 33999, + "damage": 0.028, "type": "weapon" }, "9": { "name": "ПП19 `Бизон`", "price": 24999, + "damage": 0.023, "type": "weapon" }, "10": { "name": "АКС74У", "price": 34999, + "damage": 0.031, "type": "weapon" }, "11": { "name": "M4A1", "price": 56999, + "damage": 0.045, "type": "weapon" }, "12": { "name": "CheyTac M200 `Intervention`", "price": 1400000, + "damage": 0.1, "type": "weapon" }, "13": { "name": "SR25", "price": 259999, + "damage": 0.062, "type": "weapon" }, "14": { "name": "ВСС `Винторез`", "price": 120999, + "damage": 0.062, "type": "weapon" }, "15": { "name": "HK417", "price": 388999, + "damage": 0.087, "type": "weapon" }, "16": { "name": "СВД", "price": 199999, + "damage": 0.073, + "type": "weapon" + }, + "17": { + "name": "АКМ", + "price": 60000, + "damage": 0.05, "type": "weapon" } } \ No newline at end of file diff --git a/scenes/crime.js b/scenes/crime.js index 977a720..3738bc8 100644 --- a/scenes/crime.js +++ b/scenes/crime.js @@ -1,52 +1,49 @@ const { + Telegraf, Scenes, Markup } = require('telegraf') - +const bot = new Telegraf(process.env.BOT_TOKEN) +const { + slots, + phones, + UserModel, + WorldModel, + SkillsModel, + PropertyModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { + spaces, + getSlot, + giveExp, + rand, + random, + setCooldown +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils'); const crime = new Scenes.BaseScene('Crime'); -crime.enter((ctx) => { +crime.enter( async (ctx) => { ctx.reply('Scene: Выберите ограбление', Markup.inlineKeyboard([ - [ - {text: 'Карманные кражи [SOLO]', callback_data: `POCKET_ACTION`}, - {text: 'Магазин', callback_data: `heist`}, - {text: 'Банкомат', callback_data: `heist`}, - {text: 'Банковское отделение', callback_data: `heist`}, - {text: 'Угон', callback_data: `heist`}, - {text: 'Ювелирка', callback_data: `heist`}, - {text: 'Банк', callback_data: `heist`} - ] + [{text: 'Карманные кражи [7 lvl.][SOLO]', callback_data: `POCKET_ACTION`}], + [{text: 'Магазин [8 lvl.][SOLO/DUO]', callback_data: `SHOP_ACTION`}], + [{text: 'Банкомат', callback_data: `WIP`}], + [{text: 'Банковское отделение', callback_data: `WIP`}], + [{text: 'Угон', callback_data: `WIP`}], + [{text: 'Ювелирка', callback_data: `WIP`}], + [{text: 'Банк', callback_data: `WIP`}] ])) }); -crime.action(`POCKET_ACTION`, (ctx) => { - ctx.editMessageText('Scene: Выберите объект', Markup.inlineKeyboard([ - [ - {text: 'Карман', callback_data: `POCKET_TARGET`}, - {text: 'Бумажник', callback_data: `heist`}, - {text: 'Сумка', callback_data: `heist`} - ] -])) +crime.action(`POCKET_ACTION`, async (ctx) => { + return ctx.scene.enter('POCKET_STEAL') }); -crime.action(`POCKET_TARGET`, (ctx) => { - if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); - ctx.editMessageText('Scene: В кармане обнаружено', Markup.inlineKeyboard([ - [ - {text: 'Деньги', callback_data: `MONEY`}, - {text: 'Телефон', callback_data: `PHONE`} - ] -])) +crime.action(`SHOP_ACTION`, async (ctx) => { + return ctx.scene.enter('SHOP_ROBBERY') }); -crime.action(`MONEY`, (ctx) => { - if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); - return ctx.editMessageText('Scene: Успех MONEY') -}); - -crime.action(`PHONE`, (ctx) => { - if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); - return ctx.editMessageText('Scene: Успех PHONE') +crime.action(`WIP`, async (ctx) => { + ctx.reply(`Еще не доступно.`) }); crime.leave((ctx) => { diff --git a/scenes/heist.js b/scenes/heist.js deleted file mode 100644 index f119105..0000000 --- a/scenes/heist.js +++ /dev/null @@ -1,56 +0,0 @@ -const { - Scenes, - Markup -} = require('telegraf') - -const heist = new Scenes.BaseScene('HEIST'); - -heist.enter((ctx) => { - ctx.reply('Scene: Выберите ограбление', Markup.inlineKeyboard([ - [ - {text: 'Карманные кражи', callback_data: `POCKET_ACTION`}, - {text: 'Магазин', callback_data: `heist`}, - {text: 'Банкомат', callback_data: `heist`}, - {text: 'Банковское отделение', callback_data: `heist`}, - {text: 'Угон', callback_data: `heist`}, - {text: 'Ювелирка', callback_data: `heist`}, - {text: 'Банк', callback_data: `heist`} - ] - ])) -}); - -heist.action(`POCKET_ACTION`, (ctx) => { - ctx.editMessageText('Scene: Выберите объект', Markup.inlineKeyboard([ - [ - {text: 'Карман', callback_data: `POCKET_TARGET`}, - {text: 'Бумажник', callback_data: `heist`}, - {text: 'Сумка', callback_data: `heist`} - ] -])) -}); - -heist.action(`POCKET_TARGET`, (ctx) => { - if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); - ctx.editMessageText('Scene: В кармане обнаружено', Markup.inlineKeyboard([ - [ - {text: 'Деньги', callback_data: `MONEY`}, - {text: 'Телефон', callback_data: `PHONE`} - ] -])) -}); - -heist.action(`MONEY`, (ctx) => { - if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); - return ctx.editMessageText('Scene: Успех MONEY') -}); - -heist.action(`PHONE`, (ctx) => { - if(Math.random() < 0.5) return ctx.editMessageText('Scene: Замечен'); - return ctx.editMessageText('Scene: Успех PHONE') -}); - -heist.leave((ctx) => { - console.log('Завершено'); -}); - -module.exports = heist \ No newline at end of file diff --git a/scenes/index.js b/scenes/index.js index 0b16fe7..606ba89 100644 --- a/scenes/index.js +++ b/scenes/index.js @@ -6,12 +6,30 @@ const { Markup } = require('telegraf') -const heistStart = require('./heist') -const testStart = require('./test') +const crime = require('./crime') +console.log(crime) +const pocketsteal = require('./pocketsteal') +console.log(pocketsteal) +let test = [crime, pocketsteal] +console.log(test) -const stage = new Scenes.Stage( - [heistStart] - ) +const stage = new Scenes.Stage([ + crime, + pocketsteal +]) + +stage.use((ctx, next) => { + if (!ctx.session.scene) ctx.session.scene = {} + return next() +}) + +stage.hears(([ + 'Криминал' +]), async (ctx, next) => { + await ctx.scene.leave() + ctx.session.scene = null + await next() +}) module.exports = stage \ No newline at end of file diff --git a/scenes/pocketsteal.js b/scenes/pocketsteal.js new file mode 100644 index 0000000..d63043a --- /dev/null +++ b/scenes/pocketsteal.js @@ -0,0 +1,154 @@ +const { + Telegraf, + Scenes, + Markup +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { +slots, +phones, +UserModel, +WorldModel, +SkillsModel, +PropertyModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { +spaces, +getSlot, +giveExp, +rand, +random, +setCooldown +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils'); +const steal = new Scenes.BaseScene('POCKET_STEAL'); + +steal.enter(async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let pocketsteal = user.pocketstealcd + if(user.level < 7) return ctx.editMessageText('Доступно с 7 уровня!') + let cooldown = setCooldown(user, 3600, pocketsteal) + if (user.pocketstealcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`); + user.pocketstealcd = cooldown.endTime + user.save() + ctx.editMessageText('Выберите объект', Markup.inlineKeyboard([ + [ + {text: 'Карман', callback_data: `POCKET_TARGET`}, + {text: 'Бумажник', callback_data: `POCKET_WALLET`}, + {text: 'Сумка', callback_data: `POCKET_BAG`} + ] +])) +}); + +steal.action(`POCKET_TARGET`, async (ctx) => { + ctx.editMessageText('В кармане обнаружено', Markup.inlineKeyboard([ + [ + {text: 'Деньги', callback_data: `MONEY_IN_POCKET`}, + {text: 'Телефон', callback_data: `PHONE`} + ] +])) +}); + +steal.action(`MONEY_IN_POCKET`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance < 20) return ctx.editMessageText('Вы были замечены во время кражи.'); + let moneyIn = rand(5, 1000) + user.dirtymoney += moneyIn + user.save() + return ctx.editMessageText(`Вы успешно украли Ð${spaces(moneyIn)} из кармана.`) +}); + +steal.action(`PHONE`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id); + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance < 60) return ctx.editMessageText('Вы были замечены во время кражи.'); + let randPhone = rand(1,10) + if (property.mobile.name) { + let dirtyMoney = Math.round(phones[randPhone].price/100*70) + user.dirtymoney += dirtyMoney + return await ctx.reply(`Вы сбыли украденный ${phones[randPhone].name} за Ð${dirtyMoney}`) + } + property.mobile = phones[randPhone] + await user.save() + await property.save() + return ctx.editMessageText(`Вы успешно украли ${phones[randPhone].name} из кармана.`) +}); + +steal.action(`POCKET_WALLET`, async (ctx) => { + ctx.editMessageText('В бумажнике обнаружено', Markup.inlineKeyboard([ + [ + {text: 'Деньги', callback_data: `MONEY_IN_WALLET`}, + {text: 'Карточка', callback_data: `CARD_IN_WALLET`} + ] +])) +}); + +steal.action(`MONEY_IN_WALLET`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance < 40) return ctx.editMessageText('Вы были замечены во время кражи.'); + let moneyIn = rand(1000, 10000) + user.dirtymoney += moneyIn + user.save() + return ctx.editMessageText(`Вы успешно украли Ð${spaces(moneyIn)} из бумажника.`) +}); + +steal.action(`CARD_IN_WALLET`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance < 50) return ctx.editMessageText('Вы были замечены во время кражи.'); + user.stealedcards += 1 + user.save() + return ctx.editMessageText(`Вы успешно украли 💳 из бумажника.`) +}); + +steal.action(`POCKET_BAG`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + console.log(chance) + if(chance < 60) return ctx.editMessageText('Вы были замечены во время кражи.'); + let times = rand(2,20) + let moneyIn = 0 + let text = `` + let values = 0 + + for(i=1; i<=times; i++){ + switch(i) { + case 2: + values = rand(10000, 50000) + moneyIn += values + text += `+ Ð${spaces(values)}\n` + break; + case 7: + values = rand(10000, 100000) + moneyIn += values + text += `+ Ð${spaces(values)}\n` + break; + default: + values = rand(100, 3000) + moneyIn += values + text += `+ Ð${spaces(values)}\n` + break; + } + } + user.dirtymoney += moneyIn + user.save() + return ctx.editMessageText(`Вы успешно украли сумку и сбыли все ценности из нее:\n${text}\nОбщий куш: Ð${spaces(moneyIn)}`) +}); + +steal.leave((ctx) => { + console.log('Завершено'); +}); + +module.exports = steal \ No newline at end of file diff --git a/scenes/pve.js b/scenes/pve.js new file mode 100644 index 0000000..1c46ee6 --- /dev/null +++ b/scenes/pve.js @@ -0,0 +1,138 @@ +const { + Telegraf, + Scenes, + Markup +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { +slots, +phones, +UserModel, +WorldModel, +SkillsModel, +PropertyModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { +spaces, +getSlot, +giveExp, +rand, +random, +setCooldown +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils'); +const pve = new Scenes.BaseScene('PVE'); + +pve.enter(async (ctx) => { + let property = await PropertyModel.findByPk(ctx.from.id) + ctx.reply(`Ваш противник:\n${ctx.session.enemy.name}\nЗдоровье: ${ctx.session.enemy.hp}\nБроня: ${ctx.session.enemy.armor}`, Markup.inlineKeyboard([ + [ + {text: `${property.weapon.name}`, callback_data: `attack`} + ] +])); +}); + +pve.action('attack', async (ctx) => { + let enemyHP = ctx.session.enemy.hp + let enemyArmor = ctx.session.enemy.armor + let property = await PropertyModel.findByPk(ctx.from.id) + let result = await ctx.replyWithDice({emoji: `🎯`}) + switch(result.dice.value){ + case 6: + enemyHP = enemyHP - (property.weapon.damage*1000)*10 + setTimeout(() => { + ctx.reply(`Enemy Head: HP:${enemyHP} Armor: ${enemyArmor}`) + }, 1900) + break; + case 5: + if(enemyArmor > 0){ + enemyArmor = enemyArmor - (property.weapon.damage*1000)*5 + if(enemyArmor < 0) enemyHP = enemyHP + enemyArmor + setTimeout(() => { + ctx.reply(`Enemy Chest: HP:${enemyHP} Armor: ${enemyArmor}`) + }, 1900) + }else{ + enemyHP = enemyHP - (property.weapon.damage*1000)*5 + setTimeout(() => { + ctx.reply(`Enemy Chest: HP:${enemyHP} Armor: ${enemyArmor}`) + }, 1900) + } + break; + case 4: + if(enemyArmor > 0){ + enemyArmor = enemyArmor - (property.weapon.damage*1000)*3 + if(enemyArmor < 0) enemyHP = enemyHP + enemyArmor + setTimeout(() => { + ctx.reply(`Enemy Stom: HP:${enemyHP} Armor: ${enemyArmor}`) + }, 1900) + }else{ + enemyHP = enemyHP - (property.weapon.damage*1000)*3 + setTimeout(() => { + ctx.reply(`Enemy Stom: HP:${enemyHP} Armor: ${enemyArmor}`) + }, 1900) + } + break; + case 3: + enemyHP = enemyHP - (property.weapon.damage*1000)/2 + setTimeout(() => { + ctx.reply(`Enemy Arms: HP:${enemyHP} Armor: ${enemyArmor}`) + }, 1900) + break; + case 2: + enemyHP = enemyHP - (property.weapon.damage*1000)/1.5 + setTimeout(() => { + ctx.reply(`Enemy Legs: HP:${enemyHP} Armor: ${enemyArmor}`) + }, 1900) + break; + case 1: + setTimeout(() => { + ctx.reply(`Промах, лох`) + }, 1900) + break; + } + ctx.session.enemy.hp = enemyHP + ctx.session.enemy.armor = enemyArmor + if (enemyHP <= 0) { + console.log(ctx.session) + switch(ctx.session.stage){ + case 'SHOP_KILL_CASHIER': case 'SHOP_GUARD_KILL': case 'SHOP_GUARD_STEALTH': + ctx.session.__scenes = { current: 'SHOP_ROBBERY', state: {} } + return ctx.sendMessage('Охранник обезврежен, вы подходите к кассиру:', Markup.inlineKeyboard([ + [{text: 'Убить кассира и забрать все из кассы', callback_data: `SHOP_KILL_CASHIER`}], + //[{text: 'Приказать кассиру сдать кассу [Угроза]', callback_data: `SHOP_THREAT`}], + //[{text: 'Приказать кассиру сдать кассу [Убеждение]', callback_data: `SHOP_CONVICTION`}] + ])) + case 'SHOP_CASH_SMASH': + ctx.session.__scenes = { current: 'SHOP_ROBBERY', state: {} } + return ctx.sendMessage('Вы завершили перестрелку с полицией, пора валить.', Markup.inlineKeyboard([ + [{text: 'Завершить ограбление', callback_data: `SHOP_END`}] + ])) + default: + return ctx.sendMessage('Ошибка выхода из сцены => DEBUG', Markup.inlineKeyboard([ + [{text: 'Завершить ограбление [Магазин]', callback_data: `SHOP_END`}] + ])) +} + } else { + // Противник еще жив, отправляем сообщение с обновленным HP и кнопкой для атаки + let enemyDmg = rand(0, 10) + ctx.session.user.hp -= enemyDmg + if(ctx.session.user.hp <= 0) { + ctx.editMessageText(`${ctx.session.enemy.name} наносит вам ${enemyDmg} урона.\n Осталось HP: ${ctx.session.user.hp}\nВы критически ранены!`, Markup.inlineKeyboard([ + [ + {text: 'Завершить ограбление', callback_data: `SHOP_END`} + ] + ])) + } + ctx.sendMessage(`${ctx.session.enemy.name} наносит вам ${enemyDmg} урона.\n Осталось HP: ${ctx.session.user.hp}`) + ctx.editMessageText(`Ваш противник:\n${ctx.session.enemy.name}\nЗдоровье: ${ctx.session.enemy.hp}\nБроня: ${ctx.session.enemy.armor}`, Markup.inlineKeyboard([ + [ + {text: `${property.weapon.name}`, callback_data: `attack`} + ] + ])); + } +}); + +pve.leave((ctx) => { + console.log('Завершено'); +}); + +module.exports = pve \ No newline at end of file diff --git a/scenes/shop.js b/scenes/shop.js new file mode 100644 index 0000000..786ab39 --- /dev/null +++ b/scenes/shop.js @@ -0,0 +1,295 @@ +const { + Telegraf, + Scenes, + Markup +} = require('telegraf') +const bot = new Telegraf(process.env.BOT_TOKEN) +const { +slots, +phones, +UserModel, +WorldModel, +SkillsModel, +PropertyModel +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/config') +const { +spaces, +getSlot, +giveExp, +rand, +random, +setCooldown +} = require('/workspace/degradin/Dev/Telegram/CampFire Play/utils'); +const shop = new Scenes.BaseScene('SHOP_ROBBERY'); + +bot.on('callback_query', (ctx) => { + const buttonId = ctx.update.callback_query; + console.log(buttonId) +}); + +shop.enter(async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let property = await PropertyModel.findByPk(ctx.from.id); + if(user.level < 8) return ctx.editMessageText('Доступно с 8 уровня!') + if(property.weapon == 0) return ctx.editMessageText('Для данного задания нужен ствол.') + let shoprobcd = user.shoprobcd + let cooldown = setCooldown(user, 3600, shoprobcd) + if (user.shoprobcd > cooldown.currentTime) return ctx.editMessageText(`📛 Данное действие будет доступно через ${cooldown.timeLeftInMinutes} мин.`); + user.shoprobcd = cooldown.endTime + user.save() + ctx.editMessageText('Выберите режим', Markup.inlineKeyboard([ + [ + {text: 'SOLO', callback_data: `SHOP_SOLO`}, + {text: 'DUO', callback_data: `SHOP_DUO`}, + {text: 'GROUP', callback_data: `SHOP_GROUP`} + ] +])) +}); + +shop.action(`SHOP_DUO`, async (ctx) => { + ctx.reply(`Еще не доступно.`) +}); + +shop.action(`SHOP_GROUP`, async (ctx) => { + ctx.reply(`Еще не доступно.`) +}); + +shop.action(`SHOP_SOLO`, async (ctx) => { + let property = await PropertyModel.findByPk(ctx.from.id); + if(property.equipment != 0){ + ctx.session.user = { + hp: 100, + armor: property.equipment.armor + } + }else{ + ctx.session.user = { + hp: 100, + armor: 0 + } + } + + ctx.editMessageText('Стадии:', Markup.inlineKeyboard([ + [ + {text: 'Вход', callback_data: `SHOP_ENTER`}, + //{text: 'Охранник [DEV]', callback_data: `SHOP_ENTER`}, + //{text: 'Отчет', callback_data: `SHOP_CASH_BREAK_SUCCESS`} + ] +])) +}); + +shop.action(`SHOP_ENTER`, async (ctx) => { + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance < 70) { + return ctx.editMessageText('Вы заметили охранника, с ним нужно что-то сделать...', Markup.inlineKeyboard([ + [{text: 'Избавиться от охранника [Скрытность]', callback_data: `SHOP_GUARD_STEALTH`}], + [{text: 'Убить охранника [Владение оружием]', callback_data: `SHOP_GUARD_KILL`}] + ])) + } + return ctx.editMessageText('Стадии:', Markup.inlineKeyboard([ + [{text: 'Убить кассира и забрать все из кассы', callback_data: `SHOP_KILL_CASHIER`}], + //[{text: 'Приказать кассиру сдать кассу [Угроза]', callback_data: `SHOP_THREAT`}], + //[{text: 'Приказать кассиру сдать кассу [Убеждение]', callback_data: `SHOP_CONVICTION`}] +])) +}); + +shop.action(`SHOP_GUARD`, async (ctx) => { + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + return ctx.editMessageText('Стадии:', Markup.inlineKeyboard([ + [{text: 'Избавиться от охранника [Скрытность]', callback_data: `SHOP_GUARD_STEALTH`}], + [{text: 'Убить охранника [Владение оружием]', callback_data: `SHOP_GUARD_KILL`}] +])) +}); + +shop.action(`SHOP_GUARD_STEALTH`, async (ctx) => { + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance < 40) { + ctx.session.stage = 'SHOP_GUARD_STEALTH' + ctx.reply(`Нападение!`) + ctx.session.enemy = { + name: 'Охранник', + hp: 100, + armor: 20 + } + return ctx.scene.enter('PVE') + } + return ctx.editMessageText('Охранник обезврежен, вы подходите к кассиру:', Markup.inlineKeyboard([ + [{text: 'Убить кассира и забрать все из кассы', callback_data: `SHOP_KILL_CASHIER`}], + //[{text: 'Приказать кассиру сдать кассу [Угроза]', callback_data: `SHOP_THREAT`}], + //[{text: 'Приказать кассиру сдать кассу [Убеждение]', callback_data: `SHOP_CONVICTION`}] +])) +}); + +shop.action(`SHOP_GUARD_KILL`, async (ctx) => { + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance > 10) { + ctx.session.stage = 'SHOP_GUARD_KILL' + ctx.session.enemy = { + name: 'Охранник', + hp: 100, + armor: 20 + } + return ctx.scene.enter('PVE') + } + return ctx.editMessageText('Охранник обезврежен, вы подходите к кассиру:', Markup.inlineKeyboard([ + [{text: 'Убить кассира и забрать все из кассы', callback_data: `SHOP_KILL_CASHIER`}], + //[{text: 'Приказать кассиру сдать кассу [Угроза]', callback_data: `SHOP_THREAT`}], + //[{text: 'Приказать кассиру сдать кассу [Убеждение]', callback_data: `SHOP_CONVICTION`}] +])) +}); + +shop.action(`SHOP_KILL_CASHIER`, async (ctx) => { + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.stealing.level + if(chance < 60 && !ctx.session.enemy) { + ctx.session.stage = 'SHOP_KILL_CASHIER' + ctx.editMessageText('Вы заметили охранника, с ним нужно что-то сделать...'); + ctx.session.enemy = { + name: 'Охранник', + hp: 100, + armor: 20 + } + return ctx.scene.enter('PVE') + } + return ctx.editMessageText('Стадии:', Markup.inlineKeyboard([ + [{text: 'Взлом кассы', callback_data: `SHOP_CASH_BREAK`}], + [{text: 'Разбить кассу', callback_data: `SHOP_CASH_SMASH`}] +])) +}); + +shop.action(`SHOP_CASH_BREAK`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + chance += skill.lockpick.level + let cashIn = rand(1000, 10000) + let timer = 1000 + if(chance < 99) { + const keyboard = generateKeyboard(); + ctx.deleteMessage() + return ctx.reply('Взлом замка:', keyboard); + //ctx.editMessageText('Вы начали взлом кассы.'); + //return ctx.scene.enter('LOCKPICK') + } + for(i=0; i { + cashIn += rand(1000, 10000) + ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${cashIn}`) + }, timer) + timer += 500 + } +setTimeout(() => { +user.dirtymoney += cashIn +user.save() +return ctx.editMessageText(`Вы достали из кассы Ð${cashIn}, пора валить.`, Markup.inlineKeyboard([ + [{text: 'Завершить ограбление', callback_data: `SHOP_END`}] +])) +}, timer+300) +}); + +shop.action(`SHOP_CASH_SMASH`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let skill = await SkillsModel.findByPk(ctx.from.id) + let chance = rand(0, 100) + if(chance < 50) { + ctx.editMessageText('Вы разбили кассовый аппарат, и сработала сигнализация.') + ctx.session.stage = 'SHOP_CASH_SMASH' + ctx.session.enemy = { + name: 'Полицейский', + hp: 100, + armor: 100 + } + return ctx.scene.enter('PVE') + } + return ctx.editMessageText('Вы разбили кассовый аппарат и достали кэш, пора валить.', Markup.inlineKeyboard([ + [{text: 'Завершить ограбление', callback_data: `SHOP_END`}] +])) +}); + +shop.action(`SHOP_CASH_BREAK_SUCCESS`, async (ctx) => { + let user = await UserModel.findByPk(ctx.from.id) + let cashIn = rand(1000, 10000) + let timer = 100 + for(i=0; i { + cashIn += rand(1000, 10000) + ctx.editMessageText(`⏏️ Вы достали из кассы: Ð${cashIn}`) + }, timer) + timer += 500 + } + setTimeout(() => { + user.dirtymoney += cashIn + user.save() + return ctx.editMessageText(`Вы достали из кассы Ð${cashIn}, пора валить.`, Markup.inlineKeyboard([ + [{text: 'Завершить ограбление', callback_data: `SHOP_END`}] +])) +}, timer+300) +}); + +shop.action(`SHOP_END`, async (ctx) => { + ctx.editMessageText('Ограбление завершено!') + return ctx.scene.leave(); +}); + +shop.action(/lock_*/, (ctx) => { + const buttonId = ctx.update.callback_query.data; + ctx.answerCbQuery(`Штифт не сдвинулся.`); + removeButton(ctx, buttonId); +}); + +function generateKeyboard() { + const buttonsCount = 10; + const buttons = []; + const winButton = 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}` }) + } + } + let rows = [] + while (buttons.length > 0) { + rows.push(buttons.splice(0, 5)) // разбиваем на подмассивы по 5 кнопок + } + return { + reply_markup: { + inline_keyboard: rows, + }, + }; +} + +shop.leave((ctx) => { + console.log('Завершено'); +}); + +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; + } + } + } + + if (keyboard.flat().length === 0) { + console.log(`Lockpick completed`) + } else { + console.log(keyboard) + ctx.editMessageText('Взлом замка:', Markup.inlineKeyboard(keyboard)); + } +} + +module.exports = shop \ No newline at end of file