Fix auto-attack stalling after SMSG_ATTACKSTOP and remove stale comments

Re-send CMSG_ATTACKSWING every second while auto-attacking so combat
resumes automatically when the server pauses the attack loop (out of
range, etc). Previously the client kept autoAttacking=true but never
re-engaged, requiring the player to manually right-click again.

Also remove leftover single-player/offline references from comments.
This commit is contained in:
Kelsi 2026-02-17 15:37:02 -08:00
parent 22648870f3
commit bd70ca17ca
5 changed files with 14 additions and 4 deletions

View file

@ -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<uint64_t> hostileAttackers_;
std::vector<CombatTextEntry> combatText;

View file

@ -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;

View file

@ -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(&currentTime);

View file

@ -418,7 +418,6 @@ void Application::setState(AppState newState) {
gameHandler->sendMovement(static_cast<game::Opcode>(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());

View file

@ -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);