Update rpg.js
This commit is contained in:
parent
e0a4eb184d
commit
7b53c7ea08
337
rpg.js
337
rpg.js
@ -1997,6 +1997,39 @@ rpg.action(/viewlocation_\d+/, async (ctx) => {
|
||||
await ctx.editMessageText(description, keyboard);
|
||||
});
|
||||
|
||||
rpg.action(/explore_\d+/, async (ctx) => {
|
||||
const locationId = ctx.match[0].split("_")[1];
|
||||
const location = await Location.findByPk(locationId);
|
||||
|
||||
if (!location) {
|
||||
return ctx.reply("Локация не найдена.");
|
||||
}
|
||||
|
||||
const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
|
||||
|
||||
if (!character) {
|
||||
return ctx.reply("Персонаж не найден.");
|
||||
}
|
||||
|
||||
// Проверяем, не превышает ли уровень локации уровень персонажа на 3
|
||||
if (character.level < location.level || character.level > location.level + 3) {
|
||||
return ctx.reply("📛 Здесь слишком опасно.");
|
||||
}
|
||||
|
||||
// Проверяем стамину
|
||||
if (character.stamina < location.level) {
|
||||
return ctx.reply("📛 У вас недостаточно стамины для исследования.");
|
||||
}
|
||||
|
||||
character.stamina -= location.level; // Снимаем стамину за исследование
|
||||
await character.save();
|
||||
// У локации такой же свой массив лута как и у врагов, поэтому можно использовать ту же функцию dropLoot
|
||||
const loot = dropLoot(location.loot);
|
||||
const experience = Math.floor(Math.random() * 10) + 5; // Опыт за исследование
|
||||
await Exp(ctx, character, experience)
|
||||
await ctx.reply(`Вы исследовали локацию ${location.name} и нашли:\n${loot.join("\n")}\n\n`);
|
||||
});
|
||||
|
||||
rpg.action(/hunt_location_\d+/, async (ctx) => {
|
||||
const locationId = ctx.match[0].split('_')[2]; // Получаем ID локации
|
||||
const location = await Location.findByPk(locationId);
|
||||
@ -2244,8 +2277,6 @@ rpg.action(/attack_\d+/, async (ctx) => {
|
||||
const battleId = ctx.match[0].split("_")[1];
|
||||
const battle = await Battle.findByPk(battleId);
|
||||
|
||||
|
||||
|
||||
if (!battle || battle.status !== "active") {
|
||||
logs(ctx, "Сражение завершено или не существует", { battleId });
|
||||
return ctx.reply("Сражение завершено или не существует.");
|
||||
@ -2287,134 +2318,19 @@ rpg.action(/attack_\d+/, async (ctx) => {
|
||||
);
|
||||
});
|
||||
|
||||
// Обработка попадания
|
||||
rpg.action(/hit_\d+/, async (ctx) => {
|
||||
const battleId = ctx.match[0].split("_")[1];
|
||||
const battle = await Battle.findByPk(battleId);
|
||||
async function generateBattleButtons(character) {
|
||||
const buttons = [
|
||||
{
|
||||
text: "🗡️ Атака",
|
||||
callback_data: "hit",
|
||||
},
|
||||
{
|
||||
text: "🛡️ Защита",
|
||||
callback_data: "defend",
|
||||
},
|
||||
];
|
||||
|
||||
if (!battle || battle.status !== "active") {
|
||||
logs(ctx, "Сражение завершено или не существует", { battleId });
|
||||
return ctx.reply("Сражение завершено или не существует.");
|
||||
}
|
||||
|
||||
const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
|
||||
if (!character || battle.character != ctx.from.id) {
|
||||
logs(ctx, "Персонаж не найден или не участвует в битве", { telegramId: ctx.from.id, battleId });
|
||||
return ctx.reply("Это не ваша битва.");
|
||||
}
|
||||
|
||||
const enemy = await Enemy.findByPk(battle.enemy);
|
||||
if (!enemy) {
|
||||
logs(ctx, "Противник не найден", { enemyId: battle.enemy });
|
||||
return ctx.reply("Противник не найден.");
|
||||
}
|
||||
|
||||
// Урон
|
||||
const damage = Math.floor(Math.random() * (character.force || 10)) + 1;
|
||||
battle.enemy_hp -= damage;
|
||||
|
||||
// Логи
|
||||
battle.logs = battle.logs || [];
|
||||
battle.logs.push(`${character.name} нанес ${damage} урона врагу.`);
|
||||
await battle.save({ fields: ["enemy_hp", "logs"] });
|
||||
|
||||
// Проверка на победу
|
||||
if (battle.enemy_hp <= 0) {
|
||||
battle.status = "completed";
|
||||
await battle.save();
|
||||
let items = "";
|
||||
logs(ctx, "Победа персонажа", { enemy, battle });
|
||||
Exp(ctx, character, enemy.level * 5)
|
||||
character.enemiesKilled += 1;
|
||||
await character.save();
|
||||
let droppedItems = await dropItem(character, enemy.id);
|
||||
logs(ctx, "Предметы с врага", { droppedItems });
|
||||
if (droppedItems) {
|
||||
for (const item of droppedItems) {
|
||||
await InventoryModel.create({
|
||||
telegram_id: character.telegram_id,
|
||||
name: item.name,
|
||||
text_id: item.text_id,
|
||||
description: item.description,
|
||||
effectData: item.effectData,
|
||||
price: item.price,
|
||||
rarity: item.rarity,
|
||||
type: item.type,
|
||||
duration: item.duration,
|
||||
canBeEquipped: item.canBeEquipped,
|
||||
equipped: false,
|
||||
img: item.img
|
||||
});
|
||||
}
|
||||
items = droppedItems.map((item) => item.name).join(", ");
|
||||
}
|
||||
return ctx.editMessageText(
|
||||
`🎉 ${character.name} победил ${enemy.name}!\n\n📜 Логи битвы:\n${battle.logs.slice(-5).map((log) => `• ${log}`).join("\n")}\n🧩 Выпавшие предметы: ${items}`
|
||||
);
|
||||
}
|
||||
|
||||
await battle.save();
|
||||
|
||||
// Обновление сообщения с новыми кнопками
|
||||
const buttons = generateBattleButtons(character, battle); // Генерация новых кнопок
|
||||
const keyboard = Markup.inlineKeyboard(buttons);
|
||||
|
||||
const logMessage = battle.logs.slice(-5).map((log) => `• ${log}`).join("\n");
|
||||
|
||||
logs(ctx, "Попадание", { enemy, battle, damage });
|
||||
await ctx.editMessageText(
|
||||
`⚔️ Сражение с ${enemy.name}\n\n` +
|
||||
`❤️ Здоровье врага: ${battle.enemy_hp}/${enemy.hp}\n` +
|
||||
`⚔️ Урон врага: ${enemy.damage}\n\n` +
|
||||
`📜 Логи битвы:\n${logMessage|| "Пока ничего не произошло."}\n\n` +
|
||||
`🎯 Выберите цель для атаки:`,
|
||||
keyboard
|
||||
);
|
||||
});
|
||||
|
||||
function generateBattleButtons(character, battle) {
|
||||
let ctx = { from: { id: character.telegram_id } };
|
||||
const totalButtons = 10;
|
||||
const intelligenceFactor = Math.min(character.intelligence || 1, 100); // Ограничиваем интеллект значением 100 (или любым другим максимальным значением)
|
||||
const attackChance = (intelligenceFactor / 100); // Вероятность появления кнопки атаки
|
||||
const missChance = 1 - attackChance; // Вероятность промаха
|
||||
|
||||
const buttons = [];
|
||||
|
||||
// Обязательно добавляем одну кнопку с критическим ударом
|
||||
buttons.push({
|
||||
text: `🎯`, // Символ для критического удара
|
||||
callback_data: `critical_${battle.id}`,
|
||||
});
|
||||
|
||||
// Генерация оставшихся кнопок для битвы
|
||||
while (buttons.length < totalButtons) {
|
||||
if (Math.random() < attackChance) {
|
||||
// Кнопка атаки (с шансом, определяемым интеллектом)
|
||||
buttons.push({
|
||||
text: `🎯`, // Символ для атаки
|
||||
callback_data: `hit_${battle.id}`,
|
||||
});
|
||||
} else if (Math.random() < missChance) {
|
||||
// Кнопка промаха (с шансом появления промаха)
|
||||
buttons.push({
|
||||
text: "🎯", // Символ для промаха
|
||||
callback_data: `miss_${battle.id}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Перетасовывание кнопок
|
||||
const shuffledButtons = buttons.sort(() => Math.random() - 0.5);
|
||||
|
||||
// Разбиение кнопок на 2 строки (по 5 кнопок в каждой строке)
|
||||
const rows = [];
|
||||
for (let i = 0; i < shuffledButtons.length; i += 5) {
|
||||
rows.push(shuffledButtons.slice(i, i + 5));
|
||||
}
|
||||
|
||||
logs(ctx, "Генерация кнопок для битвы", { battle, keyboard: rows });
|
||||
return rows;
|
||||
return [buttons]; // Кнопки выводятся в одной строке
|
||||
}
|
||||
|
||||
|
||||
@ -2560,136 +2476,123 @@ async function testDropItemFast() {
|
||||
|
||||
//setTimeout(testDropItemFast, 3000);
|
||||
|
||||
|
||||
|
||||
// Обработка критического удара
|
||||
rpg.action(/critical_\d+/, async (ctx) => {
|
||||
const battleId = ctx.match[0].split("_")[1];
|
||||
const battle = await Battle.findByPk(battleId);
|
||||
|
||||
if (!battle || battle.status !== "active") {
|
||||
return ctx.reply("Сражение завершено или не существует.");
|
||||
}
|
||||
|
||||
rpg.action("attack", async (ctx) => {
|
||||
const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
|
||||
if (!character || battle.character != ctx.from.id) {
|
||||
return ctx.reply("Это не ваша битва.");
|
||||
}
|
||||
|
||||
const battle = await Battle.findOne({ where: { character: character.telegram_id, status: "active" } });
|
||||
const enemy = await Enemy.findByPk(battle.enemy);
|
||||
if (!enemy) {
|
||||
return ctx.reply("Противник не найден.");
|
||||
|
||||
if (!character || !battle || !enemy) {
|
||||
return ctx.reply("Ошибка: персонаж или битва не найдены.");
|
||||
}
|
||||
|
||||
// Критический урон
|
||||
const damage = Math.floor((character.force || 10) * 2);
|
||||
battle.enemy_hp -= damage;
|
||||
// Расчет шансов
|
||||
const hitChance = 50 + character.endurance / 10; // Шанс попадания
|
||||
const critChance = character.intelligence / 20; // Шанс крита
|
||||
const critMultiplier = 1.5 + character.force / 100; // Критический урон
|
||||
|
||||
// Логи
|
||||
// Генерация результата атаки
|
||||
const hitRoll = Math.random() * 100;
|
||||
let damage = 0;
|
||||
let result = "промах";
|
||||
|
||||
if (hitRoll <= hitChance) {
|
||||
// Попадание
|
||||
if (Math.random() * 100 <= critChance) {
|
||||
damage = Math.floor(character.force * critMultiplier); // Критический удар
|
||||
result = "критический удар";
|
||||
} else {
|
||||
damage = character.force; // Обычная атака
|
||||
result = "попадание";
|
||||
}
|
||||
battle.enemy_hp -= damage;
|
||||
} else {
|
||||
// Промах — враг делает ход
|
||||
await enemyTurn(ctx, character, battle);
|
||||
}
|
||||
|
||||
// Логи боя
|
||||
battle.logs = battle.logs || [];
|
||||
battle.logs.push(`Критический удар! ${character.name} нанес ${damage} урона врагу.`);
|
||||
battle.logs.push(`${character.name} нанес ${damage} урона (${result}).`);
|
||||
await battle.save({ fields: ["enemy_hp", "logs"] });
|
||||
|
||||
// Проверка на победу
|
||||
if (battle.enemy_hp <= 0) {
|
||||
battle.status = "completed";
|
||||
await battle.save();
|
||||
let items = '';
|
||||
Exp(ctx, character, enemy.level * 6)
|
||||
let items = "";
|
||||
Exp(ctx, character, enemy.level * 6);
|
||||
character.enemiesKilled += 1;
|
||||
await character.save();
|
||||
let droppedItems = await dropItem(character, enemy.id);
|
||||
logs(ctx, "Предметы с врага", { droppedItems });
|
||||
const droppedItems = await dropItem(character, enemy.id);
|
||||
|
||||
if (droppedItems.length > 0) {
|
||||
for (const item of droppedItems) {
|
||||
await InventoryModel.create({
|
||||
telegram_id: character.telegram_id,
|
||||
name: item.name,
|
||||
text_id: item.text_id,
|
||||
description: item.description,
|
||||
effectData: item.effectData,
|
||||
price: item.price,
|
||||
rarity: item.rarity,
|
||||
type: item.type,
|
||||
duration: item.duration,
|
||||
canBeEquipped: item.canBeEquipped,
|
||||
equipped: false,
|
||||
img: item.img
|
||||
...item, // Запись всех параметров предмета
|
||||
});
|
||||
}
|
||||
items = droppedItems.map((item) => item.name).join(", ");
|
||||
}
|
||||
|
||||
|
||||
return ctx.editMessageText(
|
||||
`🎉 ${character.name} победил ${enemy.name}!\n\n📜 Логи битвы:\n${battle.logs.slice(-5).map((log) => `• ${log}`).join("\n")}\n🧩 Выпавшие предметы: ${items}`
|
||||
`🎉 ${character.name} победил ${enemy.name}!\n\n📜 Логи битвы:\n${battle.logs
|
||||
.slice(-5)
|
||||
.map((log) => `• ${log}`)
|
||||
.join("\n")}\n🧩 Выпавшие предметы: ${items}`
|
||||
);
|
||||
}
|
||||
|
||||
await battle.save({ fields: ["enemy_hp", "logs"] });
|
||||
|
||||
// Генерация новых кнопок
|
||||
const buttons = generateBattleButtons(character, battle);
|
||||
// Продолжение боя
|
||||
const logMessage = battle.logs.slice(-5).map((log) => `• ${log}`).join("\n");
|
||||
const buttons = generateBattleButtons(character);
|
||||
const keyboard = Markup.inlineKeyboard(buttons);
|
||||
|
||||
const logMessage = battle.logs.slice(-5).map((log) => `• ${log}`).join("\n");
|
||||
logs(ctx, "Критический удар", { enemy, battle, damage });
|
||||
await ctx.editMessageText(
|
||||
`⚔️ Сражение с ${enemy.name}\n\n` +
|
||||
`❤️ Здоровье врага: ${battle.enemy_hp}/${enemy.hp}\n` +
|
||||
`⚔️ Урон врага: ${enemy.damage}\n\n` +
|
||||
`📜 Логи битвы:\n${logMessage|| "Пока ничего не произошло."}\n\n` +
|
||||
`🎯 Выберите цель для атаки:`,
|
||||
`📜 Логи битвы:\n${logMessage}\n\n` +
|
||||
`🎯 Доступные действия:`,
|
||||
keyboard
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// Обработка промаха
|
||||
rpg.action(/miss_\d+/, async (ctx) => {
|
||||
const battleId = ctx.match[0].split("_")[1];
|
||||
const battle = await Battle.findByPk(battleId);
|
||||
|
||||
if (!battle || battle.status !== "active") {
|
||||
return ctx.reply("Сражение завершено или не существует.");
|
||||
rpg.command('checkstats', async (ctx) => {
|
||||
const telegramId = ctx.from.id;
|
||||
|
||||
// Ищем персонажа
|
||||
const character = await CharacterModel.findOne({ where: { telegram_id: telegramId } });
|
||||
|
||||
if (!character) {
|
||||
return ctx.reply('Персонаж не найден. Создайте нового персонажа, чтобы начать игру!');
|
||||
}
|
||||
const hitChance = Math.min(90, 50 + character.endurance / 10);
|
||||
const critChance = Math.min(90, character.intelligence / 20);
|
||||
const critMultiplier = 1.5 + character.force / 100;
|
||||
// Формируем профиль
|
||||
const profile = `
|
||||
🎭 Профиль персонажа
|
||||
|
||||
const character = await CharacterModel.findOne({ where: { telegram_id: ctx.from.id } });
|
||||
if (!character || battle.character != ctx.from.id) {
|
||||
return ctx.reply("Это не ваша битва.");
|
||||
}
|
||||
👤 Имя: ${character.name || 'Не указано'}
|
||||
🏆 Уровень: ${character.level} (${character.exp}/${utils.spaces(expToUp[character.level])})
|
||||
|
||||
const enemy = await Enemy.findByPk(battle.enemy);
|
||||
if (!enemy) {
|
||||
return ctx.reply("Противник не найден.");
|
||||
}
|
||||
❤️ Здоровье: ${character.hp}/${character.max_hp}
|
||||
🔥 Стамина: ${character.stamina}/${character.max_stamina}
|
||||
|
||||
// Логи
|
||||
battle.logs = battle.logs || [];
|
||||
battle.logs.push(`${character.name} промахнулся.`);
|
||||
await battle.save({ fields: ["enemy_hp", "logs"] });
|
||||
await enemyTurn(ctx, character, battle);
|
||||
|
||||
💪 Сила (F): ${character.force}
|
||||
🧠 Интеллект (I): ${character.intelligence}
|
||||
🛡️ Устойчивость (R): ${character.resilience}
|
||||
🔋 Выносливость (E): ${character.endurance}
|
||||
|
||||
// Генерация новых кнопок
|
||||
const buttons = generateBattleButtons(character, battle);
|
||||
const keyboard = Markup.inlineKeyboard(buttons);
|
||||
🎯 Шанс попадания: ${hitChance.toFixed(1)}%
|
||||
🔥 Шанс крита: ${critChance.toFixed(1)}%
|
||||
💥 Критический урон: ${(critMultiplier * 100).toFixed(1)}%
|
||||
|
||||
const logMessage = battle.logs.slice(-5).map((log) => `• ${log}`).join("\n");
|
||||
if (character.hp <= 0) {
|
||||
logs(ctx, "Поражение персонажа", { enemy, battle });
|
||||
return ctx.editMessageText(
|
||||
`💔 ${character.name} потерпел поражение от ${enemy.name}!\n\n📜 Логи битвы:\n${logMessage}`
|
||||
);
|
||||
}
|
||||
logs(ctx, "Промах", { enemy, battle });
|
||||
await ctx.editMessageText(
|
||||
`⚔️ Сражение с ${enemy.name}\n\n` +
|
||||
`❤️ Здоровье врага: ${battle.enemy_hp}/${enemy.hp}\n` +
|
||||
`⚔️ Урон врага: ${enemy.damage}\n\n` +
|
||||
`📜 Логи битвы:\n${logMessage|| "Пока ничего не произошло."}\n\n` +
|
||||
`🎯 Выберите цель для атаки:`,
|
||||
keyboard
|
||||
);
|
||||
`;
|
||||
// Отправляем сообщение
|
||||
ctx.reply(profile.trim());
|
||||
});
|
||||
|
||||
|
||||
module.exports = rpg;
|
||||
|
Loading…
Reference in New Issue
Block a user