physics: send MSG_MOVE_START/STOP_ASCEND and START_DESCEND during flight

When flyingActive_, detect Space/X key transitions and emit proper flight
vertical movement opcodes so the server (and other players) see the
correct ascending/descending animation state:

- MSG_MOVE_START_ASCEND  (Space pressed while flying)  → sets ASCENDING flag
- MSG_MOVE_STOP_ASCEND   (Space released while flying) → clears ASCENDING flag
- MSG_MOVE_START_DESCEND (X pressed while flying)      → clears ASCENDING flag
- MSG_MOVE_STOP_ASCEND   (X released while flying)     → clears vertical state

Track wasAscending_/wasDescending_ member state to detect transitions.
Also clear lingering vertical state when leaving flight mode.
This commit is contained in:
Kelsi 2026-03-10 14:32:30 -07:00
parent a9ddfe70c2
commit 132598fc88
3 changed files with 43 additions and 0 deletions

View file

@ -256,6 +256,8 @@ private:
bool wasTurningRight = false;
bool wasJumping = false;
bool wasFalling = false;
bool wasAscending_ = false; // Space held while flyingActive_
bool wasDescending_ = false; // X held while flyingActive_
bool moveForwardActive = false;
bool moveBackwardActive = false;
bool strafeLeftActive = false;

View file

@ -7329,6 +7329,17 @@ void GameHandler::sendMovement(Opcode opcode) {
case Opcode::MSG_MOVE_HEARTBEAT:
// No flag changes — just sends current position
break;
case Opcode::MSG_MOVE_START_ASCEND:
movementInfo.flags |= static_cast<uint32_t>(MovementFlags::ASCENDING);
break;
case Opcode::MSG_MOVE_STOP_ASCEND:
// Clears ascending (and descending) — one stop opcode for both directions
movementInfo.flags &= ~static_cast<uint32_t>(MovementFlags::ASCENDING);
break;
case Opcode::MSG_MOVE_START_DESCEND:
// Descending: no separate flag; clear ASCENDING so they don't conflict
movementInfo.flags &= ~static_cast<uint32_t>(MovementFlags::ASCENDING);
break;
default:
break;
}

View file

@ -217,6 +217,7 @@ void CameraController::update(float deltaTime) {
bool shiftDown = !uiWantsKeyboard && (input.isKeyPressed(SDL_SCANCODE_LSHIFT) || input.isKeyPressed(SDL_SCANCODE_RSHIFT));
bool ctrlDown = !uiWantsKeyboard && (input.isKeyPressed(SDL_SCANCODE_LCTRL) || input.isKeyPressed(SDL_SCANCODE_RCTRL));
bool nowJump = !uiWantsKeyboard && !sitting && !movementSuppressed && input.isKeyJustPressed(SDL_SCANCODE_SPACE);
bool spaceDown = !uiWantsKeyboard && !sitting && !movementSuppressed && input.isKeyPressed(SDL_SCANCODE_SPACE);
// Idle camera: any input resets the timer; timeout triggers a slow orbit pan
bool anyInput = leftMouseDown || rightMouseDown || keyW || keyS || keyA || keyD || keyQ || keyE || nowJump;
@ -1795,6 +1796,35 @@ void CameraController::update(float deltaTime) {
}
}
// Flight ascend/descend transitions (Space = ascend, X = descend while mounted+flying)
if (movementCallback && !externalFollow_) {
const bool nowAscending = flyingActive_ && spaceDown;
const bool nowDescending = flyingActive_ && xDown && mounted_;
if (flyingActive_) {
if (nowAscending && !wasAscending_) {
movementCallback(static_cast<uint32_t>(game::Opcode::MSG_MOVE_START_ASCEND));
} else if (!nowAscending && wasAscending_) {
movementCallback(static_cast<uint32_t>(game::Opcode::MSG_MOVE_STOP_ASCEND));
}
if (nowDescending && !wasDescending_) {
movementCallback(static_cast<uint32_t>(game::Opcode::MSG_MOVE_START_DESCEND));
} else if (!nowDescending && wasDescending_) {
// No separate STOP_DESCEND opcode; STOP_ASCEND ends all vertical movement
movementCallback(static_cast<uint32_t>(game::Opcode::MSG_MOVE_STOP_ASCEND));
}
} else {
// Left flight mode: clear any lingering vertical movement states
if (wasAscending_) {
movementCallback(static_cast<uint32_t>(game::Opcode::MSG_MOVE_STOP_ASCEND));
} else if (wasDescending_) {
movementCallback(static_cast<uint32_t>(game::Opcode::MSG_MOVE_STOP_ASCEND));
}
}
wasAscending_ = nowAscending;
wasDescending_ = nowDescending;
}
// Update previous-frame state
wasSwimming = swimming;
wasMovingForward = nowForward;