mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Fix movement desync: strafe animation and missing SET_FACING
Two bugs caused the client to look like a bot to server GMs: 1. Strafe animation played during forward+strafe (W+A) instead of the walk/run animation. Added pureStrafe guard so strafe animations only play when exclusively strafing (no forward key or auto-run active). 2. CMSG_MOVE_SET_FACING was never sent on mouse-look turns. The server predicts movement from the last known facing; without SET_FACING the heartbeat position appeared to teleport each time the player changed direction. Now sent at up to 10 Hz whenever facing changes >3°, skipped while keyboard-turning (handled server-side by TURN flags).
This commit is contained in:
parent
4e5d424b34
commit
2bbd0fdc5f
5 changed files with 31 additions and 2 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
||||||
# Build directories
|
# Build directories
|
||||||
build/
|
build/
|
||||||
|
build-sanitize/
|
||||||
bin/
|
bin/
|
||||||
lib/
|
lib/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,8 @@ private:
|
||||||
uint32_t loadedMapId_ = 0xFFFFFFFF; // Map ID of currently loaded terrain (0xFFFFFFFF = none)
|
uint32_t loadedMapId_ = 0xFFFFFFFF; // Map ID of currently loaded terrain (0xFFFFFFFF = none)
|
||||||
float taxiLandingClampTimer_ = 0.0f;
|
float taxiLandingClampTimer_ = 0.0f;
|
||||||
float worldEntryMovementGraceTimer_ = 0.0f;
|
float worldEntryMovementGraceTimer_ = 0.0f;
|
||||||
|
float facingSendCooldown_ = 0.0f; // Rate-limits CMSG_MOVE_SET_FACING
|
||||||
|
float lastSentCanonicalYaw_ = 1000.0f; // Sentinel — triggers first send
|
||||||
float taxiStreamCooldown_ = 0.0f;
|
float taxiStreamCooldown_ = 0.0f;
|
||||||
bool idleYawned_ = false;
|
bool idleYawned_ = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ public:
|
||||||
bool isMovingBackward() const { return moveBackwardActive; }
|
bool isMovingBackward() const { return moveBackwardActive; }
|
||||||
bool isStrafingLeft() const { return strafeLeftActive; }
|
bool isStrafingLeft() const { return strafeLeftActive; }
|
||||||
bool isStrafingRight() const { return strafeRightActive; }
|
bool isStrafingRight() const { return strafeRightActive; }
|
||||||
|
bool isAutoRunning() const { return autoRunning; }
|
||||||
bool isRightMouseHeld() const { return rightMouseDown; }
|
bool isRightMouseHeld() const { return rightMouseDown; }
|
||||||
bool isSitting() const { return sitting; }
|
bool isSitting() const { return sitting; }
|
||||||
bool isSwimming() const { return swimming; }
|
bool isSwimming() const { return swimming; }
|
||||||
|
|
|
||||||
|
|
@ -820,6 +820,26 @@ void Application::update(float deltaTime) {
|
||||||
// equivalent canonical yaw is radians(180 - yawDeg).
|
// equivalent canonical yaw is radians(180 - yawDeg).
|
||||||
float canonicalYaw = core::coords::normalizeAngleRad(glm::radians(180.0f - yawDeg));
|
float canonicalYaw = core::coords::normalizeAngleRad(glm::radians(180.0f - yawDeg));
|
||||||
gameHandler->setOrientation(canonicalYaw);
|
gameHandler->setOrientation(canonicalYaw);
|
||||||
|
|
||||||
|
// Send CMSG_MOVE_SET_FACING when the player changes facing direction
|
||||||
|
// (e.g. via mouse-look). Without this, the server predicts movement in
|
||||||
|
// the old facing and position-corrects on the next heartbeat — the
|
||||||
|
// micro-teleporting the GM observed.
|
||||||
|
// Skip while keyboard-turning: the server tracks that via TURN_LEFT/RIGHT flags.
|
||||||
|
facingSendCooldown_ -= deltaTime;
|
||||||
|
const auto& mi = gameHandler->getMovementInfo();
|
||||||
|
constexpr uint32_t kTurnFlags =
|
||||||
|
static_cast<uint32_t>(game::MovementFlags::TURN_LEFT) |
|
||||||
|
static_cast<uint32_t>(game::MovementFlags::TURN_RIGHT);
|
||||||
|
bool keyboardTurning = (mi.flags & kTurnFlags) != 0;
|
||||||
|
if (!keyboardTurning && facingSendCooldown_ <= 0.0f) {
|
||||||
|
float yawDiff = core::coords::normalizeAngleRad(canonicalYaw - lastSentCanonicalYaw_);
|
||||||
|
if (std::abs(yawDiff) > glm::radians(3.0f)) {
|
||||||
|
gameHandler->sendMovement(game::Opcode::CMSG_MOVE_SET_FACING);
|
||||||
|
lastSentCanonicalYaw_ = canonicalYaw;
|
||||||
|
facingSendCooldown_ = 0.1f; // max 10 Hz
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -954,11 +954,16 @@ void Renderer::updateCharacterAnimation() {
|
||||||
CharAnimState newState = charAnimState;
|
CharAnimState newState = charAnimState;
|
||||||
|
|
||||||
bool moving = cameraController->isMoving();
|
bool moving = cameraController->isMoving();
|
||||||
|
bool movingForward = cameraController->isMovingForward();
|
||||||
bool movingBackward = cameraController->isMovingBackward();
|
bool movingBackward = cameraController->isMovingBackward();
|
||||||
|
bool autoRunning = cameraController->isAutoRunning();
|
||||||
bool strafeLeft = cameraController->isStrafingLeft();
|
bool strafeLeft = cameraController->isStrafingLeft();
|
||||||
bool strafeRight = cameraController->isStrafingRight();
|
bool strafeRight = cameraController->isStrafingRight();
|
||||||
bool anyStrafeLeft = strafeLeft && !strafeRight;
|
// Strafe animation only plays during *pure* strafing (no forward/backward/autorun).
|
||||||
bool anyStrafeRight = strafeRight && !strafeLeft;
|
// When forward+strafe are both held, the walk/run animation plays — same as the real client.
|
||||||
|
bool pureStrafe = !movingForward && !movingBackward && !autoRunning;
|
||||||
|
bool anyStrafeLeft = strafeLeft && !strafeRight && pureStrafe;
|
||||||
|
bool anyStrafeRight = strafeRight && !strafeLeft && pureStrafe;
|
||||||
bool grounded = cameraController->isGrounded();
|
bool grounded = cameraController->isGrounded();
|
||||||
bool jumping = cameraController->isJumping();
|
bool jumping = cameraController->isJumping();
|
||||||
bool sprinting = cameraController->isSprinting();
|
bool sprinting = cameraController->isSprinting();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue