Update rpg.js

This commit is contained in:
Degradin 2025-01-22 20:05:52 +03:00
parent e0a4eb184d
commit 7b53c7ea08

335
rpg.js
View File

@ -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}
🎯 Шанс попадания: ${hitChance.toFixed(1)}%
🔥 Шанс крита: ${critChance.toFixed(1)}%
💥 Критический урон: ${(critMultiplier * 100).toFixed(1)}%
// Генерация новых кнопок
const buttons = generateBattleButtons(character, battle);
const keyboard = Markup.inlineKeyboard(buttons);
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;