This commit is contained in:
2025-10-26 20:44:58 +08:00
parent e287aadd3c
commit e73c08abf7
45 changed files with 280774 additions and 0 deletions

236
src/server/BattleRoom.cpp Normal file
View File

@@ -0,0 +1,236 @@
#include "server/BattleRoom.h"
#include "server/ClientHandler.h"
#include "common/Protocol.h"
#include "core/Skills.h"
#include <iostream>
#include <sstream>
BattleRoom::BattleRoom(int roomId,
std::shared_ptr<ClientHandler> player1,
std::shared_ptr<ClientHandler> player2,
std::shared_ptr<ICharacter> char1,
std::shared_ptr<ICharacter> char2)
: m_roomId(roomId),
m_player1(player1),
m_player2(player2),
m_char1(char1),
m_char2(char2),
m_isRunning(false),
m_currentTurn(0),
m_turnCount(0) {
}
BattleRoom::~BattleRoom() {
if (m_isRunning) {
endBattle();
}
}
void BattleRoom::start() {
std::lock_guard<std::mutex> lock(m_mutex);
if (m_isRunning) {
return;
}
m_isRunning = true;
m_turnCount = 0;
// 根据速度决定谁先手
m_currentTurn = (m_char1->getSpeed() >= m_char2->getSpeed()) ? 0 : 1;
// 发送战斗开始消息
std::string startLog = "战斗开始:" + m_char1->getName() + " vs " + m_char2->getName();
addLog(startLog);
// 通知双方战斗开始
std::string msg1 = Protocol::buildMessage(Protocol::S2C_BATTLE_START,
{m_char2->getName(), "Mage"}); // 简化:对手信息
std::string msg2 = Protocol::buildMessage(Protocol::S2C_BATTLE_START,
{m_char1->getName(), "Warrior"});
sendToPlayer1(msg1);
sendToPlayer2(msg2);
// 发送初始回合通知
notifyTurn();
sendBattleStatus();
std::cout << "战斗 " << m_roomId << " 已开始:" << startLog << std::endl;
}
bool BattleRoom::handleAction(const std::string& username,
int skillIndex,
const std::string& targetName) {
std::lock_guard<std::mutex> lock(m_mutex);
if (!m_isRunning) {
return false;
}
// 检查是否轮到该玩家
if (!isPlayerTurn(username)) {
return false;
}
// 确定攻击者和防守者
ICharacter* attacker = (m_currentTurn == 0) ? m_char1.get() : m_char2.get();
ICharacter* defender = (m_currentTurn == 0) ? m_char2.get() : m_char1.get();
// 获取技能简化版使用skillIndex0=普通攻击)
ISkill* skill = nullptr;
if (skillIndex == 0) {
skill = attacker->getSkill("NormalAttack");
} else if (skillIndex == 1) {
// 获取第二个技能
skill = (m_currentTurn == 0) ?
(m_char1->getSkill("HeavyStrike") ? m_char1->getSkill("HeavyStrike") : m_char1->getSkill("Fireball")) :
(m_char2->getSkill("HeavyStrike") ? m_char2->getSkill("HeavyStrike") : m_char2->getSkill("Fireball"));
}
if (!skill) {
skill = attacker->getSkill("NormalAttack"); // fallback
}
// 执行技能
int defenderHpBefore = defender->getHp();
skill->execute(*attacker, *defender);
int defenderHpAfter = defender->getHp();
int damage = defenderHpBefore - defenderHpAfter;
// 记录战斗日志
std::ostringstream logStream;
logStream << attacker->getName() << " 使用 " << skill->getName()
<< " 攻击 " << defender->getName() << ",造成 " << damage << " 点伤害!";
std::string actionLog = logStream.str();
addLog(actionLog);
// 广播战斗日志
broadcastToBoth(Protocol::buildBattleLog(actionLog));
// 发送状态更新
sendBattleStatus();
// 检查战斗是否结束
if (isFinished()) {
endBattle();
return true;
}
// 切换回合
m_currentTurn = (m_currentTurn == 0) ? 1 : 0;
m_turnCount++;
// 通知下一回合
notifyTurn();
return true;
}
bool BattleRoom::isFinished() const {
return !m_char1->isAlive() || !m_char2->isAlive() || m_turnCount >= 50;
}
std::string BattleRoom::getWinner() const {
if (m_char1->isAlive() && !m_char2->isAlive()) {
return m_char1->getName();
} else if (m_char2->isAlive() && !m_char1->isAlive()) {
return m_char2->getName();
}
return ""; // 平局或未结束
}
std::vector<std::string> BattleRoom::getBattleLog() const {
return m_historyLog.getAllEntries();
}
bool BattleRoom::isPlayerTurn(const std::string& username) const {
if (m_currentTurn == 0) {
return username == m_player1->getUsername();
} else {
return username == m_player2->getUsername();
}
}
void BattleRoom::executeTurn() {
// 这个方法在简化版本中不使用由handleAction处理
}
void BattleRoom::broadcastToBoth(const std::string& message) {
sendToPlayer1(message);
sendToPlayer2(message);
}
void BattleRoom::sendToPlayer1(const std::string& message) {
if (m_player1) {
m_player1->sendMessage(message);
}
}
void BattleRoom::sendToPlayer2(const std::string& message) {
if (m_player2) {
m_player2->sendMessage(message);
}
}
void BattleRoom::addLog(const std::string& log) {
m_historyLog.add(log);
}
void BattleRoom::endBattle() {
if (!m_isRunning) {
return;
}
m_isRunning = false;
std::string winner = getWinner();
std::string endLog;
if (!winner.empty()) {
endLog = winner + " 获胜!";
// 通知胜负
if (winner == m_player1->getUsername()) {
sendToPlayer1(Protocol::buildMessage(Protocol::S2C_BATTLE_END, {"WIN"}));
sendToPlayer2(Protocol::buildMessage(Protocol::S2C_BATTLE_END, {"LOSE"}));
} else {
sendToPlayer1(Protocol::buildMessage(Protocol::S2C_BATTLE_END, {"LOSE"}));
sendToPlayer2(Protocol::buildMessage(Protocol::S2C_BATTLE_END, {"WIN"}));
}
} else {
endLog = "战斗以平局结束!";
broadcastToBoth(Protocol::buildMessage(Protocol::S2C_BATTLE_END, {"DRAW"}));
}
addLog(endLog);
broadcastToBoth(Protocol::buildBattleLog(endLog));
// 重置玩家状态
m_player1->setState(ClientState::Lobby);
m_player1->setBattleRoomId(-1);
m_player2->setState(ClientState::Lobby);
m_player2->setBattleRoomId(-1);
std::cout << "战斗 " << m_roomId << " 已结束:" << endLog << std::endl;
}
void BattleRoom::notifyTurn() {
if (m_currentTurn == 0) {
sendToPlayer1(Protocol::buildMessage(Protocol::S2C_BATTLE_TURN, {"YOUR_TURN"}));
sendToPlayer2(Protocol::buildMessage(Protocol::S2C_BATTLE_TURN, {"OPP_TURN"}));
} else {
sendToPlayer1(Protocol::buildMessage(Protocol::S2C_BATTLE_TURN, {"OPP_TURN"}));
sendToPlayer2(Protocol::buildMessage(Protocol::S2C_BATTLE_TURN, {"YOUR_TURN"}));
}
}
void BattleRoom::sendBattleStatus() {
std::ostringstream status;
status << m_char1->getName() << " HP:" << m_char1->getHp()
<< " | " << m_char2->getName() << " HP:" << m_char2->getHp();
std::string statusMsg = status.str();
addLog(statusMsg);
broadcastToBoth(Protocol::buildBattleLog(statusMsg));
}