diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 27e0715c..e5e5f460 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -507,6 +507,13 @@ public: float getGameTime() const { return gameTime_; } float getTimeSpeed() const { return timeSpeed_; } + // Weather state (updated by SMSG_WEATHER) + // weatherType: 0=clear, 1=rain, 2=snow, 3=storm/fog + uint32_t getWeatherType() const { return weatherType_; } + float getWeatherIntensity() const { return weatherIntensity_; } + bool isRaining() const { return weatherType_ == 1 && weatherIntensity_ > 0.05f; } + bool isSnowing() const { return weatherType_ == 2 && weatherIntensity_ > 0.05f; } + // Player skills const std::map& getPlayerSkills() const { return playerSkills_; } const std::string& getSkillName(uint32_t skillId) const; @@ -1538,6 +1545,10 @@ private: float timeSpeed_ = 0.0166f; // Time scale (default: 1 game day = 1 real hour) void handleLoginSetTimeSpeed(network::Packet& packet); + // ---- Weather state (SMSG_WEATHER) ---- + uint32_t weatherType_ = 0; // 0=clear, 1=rain, 2=snow, 3=storm + float weatherIntensity_ = 0.0f; // 0.0 to 1.0 + // ---- Player skills ---- std::map playerSkills_; std::unordered_map skillLineNames_; diff --git a/include/game/opcode_table.hpp b/include/game/opcode_table.hpp index 66419810..8875ede0 100644 --- a/include/game/opcode_table.hpp +++ b/include/game/opcode_table.hpp @@ -358,6 +358,9 @@ enum class LogicalOpcode : uint16_t { SMSG_ARENA_ERROR, MSG_INSPECT_ARENA_TEAMS, + // ---- Weather ---- + SMSG_WEATHER, + // ---- Emotes ---- CMSG_EMOTE, SMSG_EMOTE, diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index a4354cba..df49a127 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -1239,6 +1239,19 @@ void GameHandler::handlePacket(network::Packet& packet) { } case Opcode::MSG_RAID_TARGET_UPDATE: break; + case Opcode::SMSG_WEATHER: { + // Format: uint32 weatherType, float intensity, uint8 isAbrupt + if (packet.getSize() - packet.getReadPos() >= 9) { + uint32_t wType = packet.readUInt32(); + float wIntensity = packet.readFloat(); + /*uint8_t isAbrupt =*/ packet.readUInt8(); + weatherType_ = wType; + weatherIntensity_ = wIntensity; + const char* typeName = (wType == 1) ? "Rain" : (wType == 2) ? "Snow" : (wType == 3) ? "Storm" : "Clear"; + LOG_INFO("Weather changed: type=", wType, " (", typeName, "), intensity=", wIntensity); + } + break; + } case Opcode::SMSG_GAMEOBJECT_QUERY_RESPONSE: handleGameObjectQueryResponse(packet); break; diff --git a/src/game/opcode_table.cpp b/src/game/opcode_table.cpp index 32eb0577..22acd50b 100644 --- a/src/game/opcode_table.cpp +++ b/src/game/opcode_table.cpp @@ -287,6 +287,7 @@ static const OpcodeNameEntry kOpcodeNames[] = { {"SMSG_ARENA_TEAM_STATS", LogicalOpcode::SMSG_ARENA_TEAM_STATS}, {"SMSG_ARENA_ERROR", LogicalOpcode::SMSG_ARENA_ERROR}, {"MSG_INSPECT_ARENA_TEAMS", LogicalOpcode::MSG_INSPECT_ARENA_TEAMS}, + {"SMSG_WEATHER", LogicalOpcode::SMSG_WEATHER}, {"CMSG_EMOTE", LogicalOpcode::CMSG_EMOTE}, {"SMSG_EMOTE", LogicalOpcode::SMSG_EMOTE}, {"CMSG_TEXT_EMOTE", LogicalOpcode::CMSG_TEXT_EMOTE}, @@ -627,6 +628,7 @@ void OpcodeTable::loadWotlkDefaults() { {LogicalOpcode::SMSG_ARENA_TEAM_STATS, 0x035B}, {LogicalOpcode::SMSG_ARENA_ERROR, 0x0376}, {LogicalOpcode::MSG_INSPECT_ARENA_TEAMS, 0x0377}, + {LogicalOpcode::SMSG_WEATHER, 0x2F4}, {LogicalOpcode::CMSG_EMOTE, 0x102}, {LogicalOpcode::SMSG_EMOTE, 0x103}, {LogicalOpcode::CMSG_TEXT_EMOTE, 0x104}, diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 73c655af..9d54e8cc 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -1838,15 +1838,23 @@ void Renderer::update(float deltaTime) { // Update lighting system auto light1 = std::chrono::high_resolution_clock::now(); if (lightingManager) { - // TODO: Get actual map ID from game state (0 = Eastern Kingdoms for now) - // TODO: Get actual game time from server (use -1 for local time fallback) - // TODO: Get weather/underwater state from game state - uint32_t mapId = 0; // Eastern Kingdoms - float gameTime = -1.0f; // Use local time for now - bool isRaining = false; // TODO: Get from weather system - bool isUnderwater = false; // TODO: Get from player state + const auto* gh = core::Application::getInstance().getGameHandler(); + uint32_t mapId = gh ? gh->getCurrentMapId() : 0; + float gameTime = gh ? gh->getGameTime() : -1.0f; + bool isRaining = gh ? gh->isRaining() : false; + bool isUnderwater = cameraController ? cameraController->isSwimming() : false; lightingManager->update(characterPosition, mapId, gameTime, isRaining, isUnderwater); + + // Sync weather visual renderer with game state + if (weather && gh) { + uint32_t wType = gh->getWeatherType(); + float wInt = gh->getWeatherIntensity(); + if (wType == 1) weather->setWeatherType(Weather::Type::RAIN); + else if (wType == 2) weather->setWeatherType(Weather::Type::SNOW); + else weather->setWeatherType(Weather::Type::NONE); + weather->setIntensity(wInt); + } } auto light2 = std::chrono::high_resolution_clock::now(); lightTime += std::chrono::duration(light2 - light1).count();