mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-04 16:23:52 +00:00
Implement activity SFX and decouple camera orbit from movement facing
This commit is contained in:
parent
dfc29cad10
commit
8bc50818a9
9 changed files with 592 additions and 12 deletions
|
|
@ -36,6 +36,7 @@ std::optional<float> selectReachableFloor(const std::optional<float>& terrainH,
|
|||
|
||||
CameraController::CameraController(Camera* cam) : camera(cam) {
|
||||
yaw = defaultYaw;
|
||||
facingYaw = defaultYaw;
|
||||
pitch = defaultPitch;
|
||||
reset();
|
||||
}
|
||||
|
|
@ -90,6 +91,7 @@ void CameraController::update(float deltaTime) {
|
|||
}
|
||||
if (nowTurnLeft || nowTurnRight) {
|
||||
camera->setRotation(yaw, pitch);
|
||||
facingYaw = yaw;
|
||||
}
|
||||
|
||||
// Select physics constants based on mode
|
||||
|
|
@ -129,12 +131,14 @@ void CameraController::update(float deltaTime) {
|
|||
|
||||
// Get camera axes — project forward onto XY plane for walking
|
||||
glm::vec3 forward3D = camera->getForward();
|
||||
glm::vec3 forward = glm::normalize(glm::vec3(forward3D.x, forward3D.y, 0.0f));
|
||||
glm::vec3 right = camera->getRight();
|
||||
right.z = 0.0f;
|
||||
if (glm::length(right) > 0.001f) {
|
||||
right = glm::normalize(right);
|
||||
bool cameraDrivesFacing = rightMouseDown || mouseAutorun;
|
||||
if (cameraDrivesFacing) {
|
||||
facingYaw = yaw;
|
||||
}
|
||||
float moveYaw = cameraDrivesFacing ? yaw : facingYaw;
|
||||
float moveYawRad = glm::radians(moveYaw);
|
||||
glm::vec3 forward(std::cos(moveYawRad), std::sin(moveYawRad), 0.0f);
|
||||
glm::vec3 right(-std::sin(moveYawRad), std::cos(moveYawRad), 0.0f);
|
||||
|
||||
// Toggle sit/crouch with X or C key (edge-triggered) — only when UI doesn't want keyboard
|
||||
bool xDown = !uiWantsKeyboard && (input.isKeyPressed(SDL_SCANCODE_X) || input.isKeyPressed(SDL_SCANCODE_C));
|
||||
|
|
@ -209,6 +213,27 @@ void CameraController::update(float deltaTime) {
|
|||
if (verticalVelocity > 0.0f) verticalVelocity = 0.0f;
|
||||
}
|
||||
|
||||
// Prevent sinking/clipping through world floor while swimming.
|
||||
std::optional<float> floorH;
|
||||
if (terrainManager) {
|
||||
floorH = terrainManager->getHeightAt(targetPos.x, targetPos.y);
|
||||
}
|
||||
if (wmoRenderer) {
|
||||
auto wh = wmoRenderer->getFloorHeight(targetPos.x, targetPos.y, targetPos.z + 5.0f);
|
||||
if (wh && (!floorH || *wh > *floorH)) floorH = wh;
|
||||
}
|
||||
if (m2Renderer) {
|
||||
auto mh = m2Renderer->getFloorHeight(targetPos.x, targetPos.y, targetPos.z);
|
||||
if (mh && (!floorH || *mh > *floorH)) floorH = mh;
|
||||
}
|
||||
if (floorH) {
|
||||
float swimFloor = *floorH + 0.30f;
|
||||
if (targetPos.z < swimFloor) {
|
||||
targetPos.z = swimFloor;
|
||||
if (verticalVelocity < 0.0f) verticalVelocity = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
grounded = false;
|
||||
} else {
|
||||
swimming = false;
|
||||
|
|
@ -815,6 +840,7 @@ void CameraController::reset() {
|
|||
}
|
||||
|
||||
yaw = defaultYaw;
|
||||
facingYaw = defaultYaw;
|
||||
pitch = defaultPitch;
|
||||
verticalVelocity = 0.0f;
|
||||
grounded = true;
|
||||
|
|
|
|||
|
|
@ -1185,6 +1185,19 @@ bool CharacterRenderer::hasAnimation(uint32_t instanceId, uint32_t animationId)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CharacterRenderer::getInstanceModelName(uint32_t instanceId, std::string& modelName) const {
|
||||
auto it = instances.find(instanceId);
|
||||
if (it == instances.end()) {
|
||||
return false;
|
||||
}
|
||||
auto modelIt = models.find(it->second.modelId);
|
||||
if (modelIt == models.end()) {
|
||||
return false;
|
||||
}
|
||||
modelName = modelIt->second.data.name;
|
||||
return !modelName.empty();
|
||||
}
|
||||
|
||||
bool CharacterRenderer::attachWeapon(uint32_t charInstanceId, uint32_t attachmentId,
|
||||
const pipeline::M2Model& weaponModel, uint32_t weaponModelId,
|
||||
const std::string& texturePath) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "game/zone_manager.hpp"
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "audio/footstep_manager.hpp"
|
||||
#include "audio/activity_sound_manager.hpp"
|
||||
#include <GL/glew.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtx/euler_angles.hpp>
|
||||
|
|
@ -190,6 +191,7 @@ bool Renderer::initialize(core::Window* win) {
|
|||
// Create music manager (initialized later with asset manager)
|
||||
musicManager = std::make_unique<audio::MusicManager>();
|
||||
footstepManager = std::make_unique<audio::FootstepManager>();
|
||||
activitySoundManager = std::make_unique<audio::ActivitySoundManager>();
|
||||
|
||||
LOG_INFO("Renderer initialized");
|
||||
return true;
|
||||
|
|
@ -266,6 +268,10 @@ void Renderer::shutdown() {
|
|||
footstepManager->shutdown();
|
||||
footstepManager.reset();
|
||||
}
|
||||
if (activitySoundManager) {
|
||||
activitySoundManager->shutdown();
|
||||
activitySoundManager.reset();
|
||||
}
|
||||
|
||||
zoneManager.reset();
|
||||
|
||||
|
|
@ -647,13 +653,16 @@ void Renderer::update(float deltaTime) {
|
|||
// Sync character model position/rotation and animation with follow target
|
||||
if (characterInstanceId > 0 && characterRenderer && cameraController && cameraController->isThirdPerson()) {
|
||||
characterRenderer->setInstancePosition(characterInstanceId, characterPosition);
|
||||
if (activitySoundManager) {
|
||||
std::string modelName;
|
||||
if (characterRenderer->getInstanceModelName(characterInstanceId, modelName)) {
|
||||
activitySoundManager->setCharacterVoiceProfile(modelName);
|
||||
}
|
||||
}
|
||||
|
||||
// Keep facing decoupled from lateral movement:
|
||||
// face camera when RMB is held, or with forward/back intent.
|
||||
if (cameraController->isRightMouseHeld() ||
|
||||
cameraController->isMovingForward() ||
|
||||
cameraController->isMovingBackward()) {
|
||||
characterYaw = cameraController->getYaw();
|
||||
// Movement-facing comes from camera controller and is decoupled from LMB orbit.
|
||||
if (cameraController->isMoving() || cameraController->isRightMouseHeld()) {
|
||||
characterYaw = cameraController->getFacingYaw();
|
||||
} else if (targetPosition && !emoteActive && !cameraController->isMoving()) {
|
||||
// Face target when idle
|
||||
glm::vec3 toTarget = *targetPosition - characterPosition;
|
||||
|
|
@ -737,6 +746,51 @@ void Renderer::update(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
// Activity SFX: animation/state-driven jump, landing, and swim loops/splashes.
|
||||
if (activitySoundManager) {
|
||||
activitySoundManager->update(deltaTime);
|
||||
if (cameraController && cameraController->isThirdPerson()) {
|
||||
bool grounded = cameraController->isGrounded();
|
||||
bool jumping = cameraController->isJumping();
|
||||
bool falling = cameraController->isFalling();
|
||||
bool swimming = cameraController->isSwimming();
|
||||
bool moving = cameraController->isMoving();
|
||||
|
||||
if (!sfxStateInitialized) {
|
||||
sfxPrevGrounded = grounded;
|
||||
sfxPrevJumping = jumping;
|
||||
sfxPrevFalling = falling;
|
||||
sfxPrevSwimming = swimming;
|
||||
sfxStateInitialized = true;
|
||||
}
|
||||
|
||||
if (jumping && !sfxPrevJumping && !swimming) {
|
||||
activitySoundManager->playJump();
|
||||
}
|
||||
|
||||
if (grounded && !sfxPrevGrounded) {
|
||||
bool hardLanding = sfxPrevFalling;
|
||||
activitySoundManager->playLanding(resolveFootstepSurface(), hardLanding);
|
||||
}
|
||||
|
||||
if (swimming && !sfxPrevSwimming) {
|
||||
activitySoundManager->playWaterEnter();
|
||||
} else if (!swimming && sfxPrevSwimming) {
|
||||
activitySoundManager->playWaterExit();
|
||||
}
|
||||
|
||||
activitySoundManager->setSwimmingState(swimming, moving);
|
||||
|
||||
sfxPrevGrounded = grounded;
|
||||
sfxPrevJumping = jumping;
|
||||
sfxPrevFalling = falling;
|
||||
sfxPrevSwimming = swimming;
|
||||
} else {
|
||||
activitySoundManager->setSwimmingState(false, false);
|
||||
sfxStateInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Update M2 doodad animations
|
||||
if (m2Renderer) {
|
||||
m2Renderer->update(deltaTime);
|
||||
|
|
@ -1011,6 +1065,9 @@ bool Renderer::loadTestTerrain(pipeline::AssetManager* assetManager, const std::
|
|||
if (footstepManager) {
|
||||
footstepManager->initialize(assetManager);
|
||||
}
|
||||
if (activitySoundManager) {
|
||||
activitySoundManager->initialize(assetManager);
|
||||
}
|
||||
cachedAssetManager = assetManager;
|
||||
}
|
||||
|
||||
|
|
@ -1079,6 +1136,11 @@ bool Renderer::loadTerrainArea(const std::string& mapName, int centerX, int cent
|
|||
footstepManager->initialize(cachedAssetManager);
|
||||
}
|
||||
}
|
||||
if (activitySoundManager && cachedAssetManager) {
|
||||
if (!activitySoundManager->isInitialized()) {
|
||||
activitySoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
}
|
||||
|
||||
// Wire WMO, M2, and water renderer to camera controller
|
||||
if (cameraController && wmoRenderer) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue