mirror of
https://github.com/ChuXunYu/OnlineRpg.git
synced 2026-01-31 16:55:46 +00:00
2
This commit is contained in:
236
src/server/BattleRoom.cpp
Normal file
236
src/server/BattleRoom.cpp
Normal 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();
|
||||
|
||||
// 获取技能(简化版:使用skillIndex,0=普通攻击)
|
||||
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));
|
||||
}
|
||||
Reference in New Issue
Block a user