diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index fb5d4ef5..f66e29d5 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -1279,6 +1279,7 @@ private: bool autoAttacking = false; uint64_t autoAttackTarget = 0; bool autoAttackOutOfRange_ = false; + float autoAttackResendTimer_ = 0.0f; // Re-send CMSG_ATTACKSWING every ~1s while attacking std::unordered_set hostileAttackers_; std::vector combatText; diff --git a/include/game/transport_manager.hpp b/include/game/transport_manager.hpp index d3b80729..571d3b3f 100644 --- a/include/game/transport_manager.hpp +++ b/include/game/transport_manager.hpp @@ -43,7 +43,7 @@ struct ActiveTransport { glm::mat4 transform; // Cached world transform glm::mat4 invTransform; // Cached inverse for collision - // Player attachment (single-player for now) + // Player attachment state bool playerOnBoard; glm::vec3 playerLocalOffset; diff --git a/src/audio/ambient_sound_manager.cpp b/src/audio/ambient_sound_manager.cpp index 241c0cbb..f976cbdf 100644 --- a/src/audio/ambient_sound_manager.cpp +++ b/src/audio/ambient_sound_manager.cpp @@ -771,7 +771,7 @@ void AmbientSoundManager::updateBellTolls(float deltaTime) { return; } - // Get current system time (server time for single-player) + // Get current system time auto now = std::chrono::system_clock::now(); std::time_t currentTime = std::chrono::system_clock::to_time_t(now); std::tm* localTime = std::localtime(¤tTime); diff --git a/src/core/application.cpp b/src/core/application.cpp index 33cd621c..9aa4328c 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -418,7 +418,6 @@ void Application::setState(AppState newState) { gameHandler->sendMovement(static_cast(opcode)); } }); - // Keep player locomotion WoW-like in both single-player and online modes. cc->setUseWoWSpeed(true); } if (gameHandler) { @@ -884,7 +883,7 @@ void Application::render() { renderer->beginFrame(); - // Only render 3D world when in-game (after server connect or single-player) + // Only render 3D world when in-game if (state == AppState::IN_GAME) { if (world) { renderer->renderWorld(world.get(), gameHandler.get()); diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index ae598424..037e643e 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -522,6 +522,7 @@ void GameHandler::update(float deltaTime) { auto distanceStart = std::chrono::high_resolution_clock::now(); // Leave combat if auto-attack target is too far away (leash range) + // Also re-send CMSG_ATTACKSWING every second to resume after server SMSG_ATTACKSTOP if (autoAttacking && autoAttackTarget != 0) { auto targetEntity = entityManager.getEntity(autoAttackTarget); if (targetEntity) { @@ -531,6 +532,13 @@ void GameHandler::update(float deltaTime) { if (dist > 40.0f) { stopAutoAttack(); LOG_INFO("Left combat: target too far (", dist, " yards)"); + } else if (state == WorldState::IN_WORLD && socket) { + autoAttackResendTimer_ += deltaTime; + if (autoAttackResendTimer_ >= 1.0f) { + autoAttackResendTimer_ = 0.0f; + auto pkt = AttackSwingPacket::build(autoAttackTarget); + socket->send(pkt); + } } } } @@ -6382,6 +6390,7 @@ void GameHandler::startAutoAttack(uint64_t targetGuid) { autoAttacking = true; autoAttackTarget = targetGuid; autoAttackOutOfRange_ = false; + autoAttackResendTimer_ = 0.0f; if (state == WorldState::IN_WORLD && socket) { auto packet = AttackSwingPacket::build(targetGuid); socket->send(packet); @@ -6394,6 +6403,7 @@ void GameHandler::stopAutoAttack() { autoAttacking = false; autoAttackTarget = 0; autoAttackOutOfRange_ = false; + autoAttackResendTimer_ = 0.0f; if (state == WorldState::IN_WORLD && socket) { auto packet = AttackStopPacket::build(); socket->send(packet);