mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-25 00:20:16 +00:00
feat: add WotLK vehicle exit UI with Leave Vehicle button
Parse SMSG_PLAYER_VEHICLE_DATA (PackedGuid + uint32 vehicleId) and track in-vehicle state. Add sendRequestVehicleExit() which sends CMSG_REQUEST_VEHICLE_EXIT. Render a floating red "Leave Vehicle" button above the action bar whenever vehicleId_ is non-zero. State cleared on world leave and zone transfer.
This commit is contained in:
parent
fbcec9e7bf
commit
b7c1aa39a9
3 changed files with 62 additions and 3 deletions
|
|
@ -1594,6 +1594,11 @@ public:
|
|||
return it != taxiNpcHasRoutes_.end() && it->second;
|
||||
}
|
||||
|
||||
// Vehicle (WotLK)
|
||||
bool isInVehicle() const { return vehicleId_ != 0; }
|
||||
uint32_t getVehicleId() const { return vehicleId_; }
|
||||
void sendRequestVehicleExit();
|
||||
|
||||
// Vendor
|
||||
void openVendor(uint64_t npcGuid);
|
||||
void closeVendor();
|
||||
|
|
@ -2536,6 +2541,9 @@ private:
|
|||
return it != factionHostileMap_.end() ? it->second : true; // default hostile if unknown
|
||||
}
|
||||
|
||||
// Vehicle (WotLK): non-zero when player is seated in a vehicle
|
||||
uint32_t vehicleId_ = 0;
|
||||
|
||||
// Taxi / Flight Paths
|
||||
std::unordered_map<uint64_t, bool> taxiNpcHasRoutes_; // guid -> has new/available routes
|
||||
std::unordered_map<uint32_t, TaxiNode> taxiNodes_;
|
||||
|
|
|
|||
|
|
@ -5211,10 +5211,19 @@ void GameHandler::handlePacket(network::Packet& packet) {
|
|||
// GM ticket status (new/updated); no ticket UI yet
|
||||
packet.setReadPos(packet.getSize());
|
||||
break;
|
||||
case Opcode::SMSG_PLAYER_VEHICLE_DATA:
|
||||
// Vehicle data update for player in vehicle; no vehicle UI yet
|
||||
packet.setReadPos(packet.getSize());
|
||||
case Opcode::SMSG_PLAYER_VEHICLE_DATA: {
|
||||
// PackedGuid (player guid) + uint32 vehicleId
|
||||
// vehicleId == 0 means the player left the vehicle
|
||||
if (packet.getSize() - packet.getReadPos() >= 1) {
|
||||
(void)UpdateObjectParser::readPackedGuid(packet); // player guid (unused)
|
||||
}
|
||||
if (packet.getSize() - packet.getReadPos() >= 4) {
|
||||
vehicleId_ = packet.readUInt32();
|
||||
} else {
|
||||
vehicleId_ = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Opcode::SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE:
|
||||
packet.setReadPos(packet.getSize());
|
||||
break;
|
||||
|
|
@ -6868,6 +6877,7 @@ void GameHandler::handleLoginVerifyWorld(network::Packet& packet) {
|
|||
taxiStartGrace_ = 0.0f;
|
||||
currentMountDisplayId_ = 0;
|
||||
taxiMountDisplayId_ = 0;
|
||||
vehicleId_ = 0;
|
||||
if (mountCallback_) {
|
||||
mountCallback_(0);
|
||||
}
|
||||
|
|
@ -7891,6 +7901,14 @@ void GameHandler::sendPing() {
|
|||
socket->send(packet);
|
||||
}
|
||||
|
||||
void GameHandler::sendRequestVehicleExit() {
|
||||
if (state != WorldState::IN_WORLD || vehicleId_ == 0) return;
|
||||
// CMSG_REQUEST_VEHICLE_EXIT has no payload — opcode only
|
||||
network::Packet pkt(wireOpcode(Opcode::CMSG_REQUEST_VEHICLE_EXIT));
|
||||
socket->send(pkt);
|
||||
vehicleId_ = 0; // Optimistically clear; server will confirm via SMSG_PLAYER_VEHICLE_DATA(0)
|
||||
}
|
||||
|
||||
void GameHandler::sendMinimapPing(float wowX, float wowY) {
|
||||
if (state != WorldState::IN_WORLD) return;
|
||||
|
||||
|
|
@ -8202,6 +8220,7 @@ void GameHandler::forceClearTaxiAndMovementState() {
|
|||
taxiMountActive_ = false;
|
||||
taxiMountDisplayId_ = 0;
|
||||
currentMountDisplayId_ = 0;
|
||||
vehicleId_ = 0;
|
||||
resurrectPending_ = false;
|
||||
resurrectRequestPending_ = false;
|
||||
playerDead_ = false;
|
||||
|
|
|
|||
|
|
@ -6968,6 +6968,38 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
|
|||
ImGui::PopStyleVar(4);
|
||||
}
|
||||
|
||||
// Vehicle exit button (WotLK): floating button above action bar when player is in a vehicle
|
||||
if (gameHandler.isInVehicle()) {
|
||||
const float btnW = 120.0f;
|
||||
const float btnH = 32.0f;
|
||||
const float btnX = (screenW - btnW) / 2.0f;
|
||||
const float btnY = barY - btnH - 6.0f;
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(btnX, btnY), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(btnW, btnH), ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(4.0f, 4.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
ImGuiWindowFlags vFlags = ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar |
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoBackground;
|
||||
if (ImGui::Begin("##VehicleExit", nullptr, vFlags)) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.6f, 0.1f, 0.1f, 0.9f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.8f, 0.2f, 0.2f, 1.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0.4f, 0.0f, 0.0f, 1.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
|
||||
if (ImGui::Button("Leave Vehicle", ImVec2(btnW - 8.0f, btnH - 8.0f))) {
|
||||
gameHandler.sendRequestVehicleExit();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
// Handle action bar drag: render icon at cursor and detect drop outside
|
||||
if (actionBarDragSlot_ >= 0) {
|
||||
ImVec2 mousePos = ImGui::GetMousePos();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue