mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
fix: derive rest state from PLAYER_BYTES_2 and add action bar 2 settings
XP bar rest state: - isResting_ now set from PLAYER_BYTES_2 byte 3 bit 0 (rest state flag) on both CREATE and VALUES update object handlers - playerRestedXp_ was missing from VALUES handler — now tracked there too - Eliminates dependency on SMSG_SET_REST_START (wrong in WotLK opcodes.json) Interface settings: - New "Interface" tab in Settings window - "Show Second Action Bar" toggle (default: on) - Horizontal/vertical position offset sliders for bar 2 - Settings persisted to/from save file
This commit is contained in:
parent
1a370fef76
commit
ec5e7c66c3
3 changed files with 64 additions and 3 deletions
|
|
@ -112,6 +112,9 @@ private:
|
|||
bool pendingSeparateBags = true;
|
||||
bool pendingAutoLoot = false;
|
||||
bool pendingUseOriginalSoundtrack = true;
|
||||
bool pendingShowActionBar2 = true; // Show second action bar above main bar
|
||||
float pendingActionBar2OffsetX = 0.0f; // Horizontal offset from default center position
|
||||
float pendingActionBar2OffsetY = 0.0f; // Vertical offset from default (above bar 1)
|
||||
int pendingGroundClutterDensity = 100;
|
||||
int pendingAntiAliasing = 0; // 0=Off, 1=2x, 2=4x, 3=8x
|
||||
bool pendingNormalMapping = true; // on by default
|
||||
|
|
|
|||
|
|
@ -8086,6 +8086,9 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
LOG_WARNING("PLAYER_BYTES_2 (CREATE): raw=0x", std::hex, val, std::dec,
|
||||
" bankBagSlots=", static_cast<int>(bankBagSlots));
|
||||
inventory.setPurchasedBankBagSlots(bankBagSlots);
|
||||
// Byte 3 (bits 24-31): REST_STATE — bit 0 set means in inn/city
|
||||
uint8_t restStateByte = static_cast<uint8_t>((val >> 24) & 0xFF);
|
||||
isResting_ = (restStateByte & 0x01) != 0;
|
||||
}
|
||||
// Do not synthesize quest-log entries from raw update-field slots.
|
||||
// Slot layouts differ on some classic-family realms and can produce
|
||||
|
|
@ -8354,6 +8357,7 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
bool slotsChanged = false;
|
||||
const uint16_t ufPlayerXp = fieldIndex(UF::PLAYER_XP);
|
||||
const uint16_t ufPlayerNextXp = fieldIndex(UF::PLAYER_NEXT_LEVEL_XP);
|
||||
const uint16_t ufPlayerRestedXpV = fieldIndex(UF::PLAYER_REST_STATE_EXPERIENCE);
|
||||
const uint16_t ufPlayerLevel = fieldIndex(UF::UNIT_FIELD_LEVEL);
|
||||
const uint16_t ufCoinage = fieldIndex(UF::PLAYER_FIELD_COINAGE);
|
||||
const uint16_t ufPlayerFlags = fieldIndex(UF::PLAYER_FLAGS);
|
||||
|
|
@ -8368,6 +8372,9 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
playerNextLevelXp_ = val;
|
||||
LOG_DEBUG("Next level XP updated: ", val);
|
||||
}
|
||||
else if (ufPlayerRestedXpV != 0xFFFF && key == ufPlayerRestedXpV) {
|
||||
playerRestedXp_ = val;
|
||||
}
|
||||
else if (key == ufPlayerLevel) {
|
||||
serverPlayerLevel_ = val;
|
||||
LOG_DEBUG("Level updated: ", val);
|
||||
|
|
@ -8390,6 +8397,9 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
LOG_WARNING("PLAYER_BYTES_2 (VALUES): raw=0x", std::hex, val, std::dec,
|
||||
" bankBagSlots=", static_cast<int>(bankBagSlots));
|
||||
inventory.setPurchasedBankBagSlots(bankBagSlots);
|
||||
// Byte 3 (bits 24-31): REST_STATE — bit 0 set means in inn/city
|
||||
uint8_t restStateByte = static_cast<uint8_t>((val >> 24) & 0xFF);
|
||||
isResting_ = (restStateByte & 0x01) != 0;
|
||||
}
|
||||
else if (key == ufPlayerFlags) {
|
||||
constexpr uint32_t PLAYER_FLAGS_GHOST = 0x00000010;
|
||||
|
|
|
|||
|
|
@ -4137,13 +4137,14 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
|
|||
};
|
||||
|
||||
// Bar 2 (slots 12-23) — only show if at least one slot is populated
|
||||
{
|
||||
if (pendingShowActionBar2) {
|
||||
bool bar2HasContent = false;
|
||||
for (int i = 0; i < game::GameHandler::SLOTS_PER_BAR; ++i)
|
||||
if (!bar[game::GameHandler::SLOTS_PER_BAR + i].isEmpty()) { bar2HasContent = true; break; }
|
||||
|
||||
float bar2Y = barY - barH - 2.0f;
|
||||
ImGui::SetNextWindowPos(ImVec2(barX, bar2Y), ImGuiCond_Always);
|
||||
float bar2X = barX + pendingActionBar2OffsetX;
|
||||
float bar2Y = barY - barH - 2.0f + pendingActionBar2OffsetY;
|
||||
ImGui::SetNextWindowPos(ImVec2(bar2X, bar2Y), ImGuiCond_Always);
|
||||
ImGui::SetNextWindowSize(ImVec2(barW, barH), ImGuiCond_Always);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 4.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(padding, padding));
|
||||
|
|
@ -7995,6 +7996,44 @@ void GameScreen::renderSettingsWindow() {
|
|||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// INTERFACE TAB
|
||||
// ============================================================
|
||||
if (ImGui::BeginTabItem("Interface")) {
|
||||
ImGui::Spacing();
|
||||
ImGui::BeginChild("InterfaceSettings", ImVec2(0, 360), true);
|
||||
|
||||
ImGui::SeparatorText("Action Bars");
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::Checkbox("Show Second Action Bar", &pendingShowActionBar2)) {
|
||||
saveSettings();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::TextDisabled("(Shift+1 through Shift+=)");
|
||||
|
||||
if (pendingShowActionBar2) {
|
||||
ImGui::Spacing();
|
||||
ImGui::TextUnformatted("Second Bar Position Offset");
|
||||
ImGui::SetNextItemWidth(160.0f);
|
||||
if (ImGui::SliderFloat("Horizontal##bar2x", &pendingActionBar2OffsetX, -600.0f, 600.0f, "%.0f px")) {
|
||||
saveSettings();
|
||||
}
|
||||
ImGui::SetNextItemWidth(160.0f);
|
||||
if (ImGui::SliderFloat("Vertical##bar2y", &pendingActionBar2OffsetY, -400.0f, 400.0f, "%.0f px")) {
|
||||
saveSettings();
|
||||
}
|
||||
if (ImGui::Button("Reset Position##bar2")) {
|
||||
pendingActionBar2OffsetX = 0.0f;
|
||||
pendingActionBar2OffsetY = 0.0f;
|
||||
saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// AUDIO TAB
|
||||
// ============================================================
|
||||
|
|
@ -9054,6 +9093,9 @@ void GameScreen::saveSettings() {
|
|||
out << "minimap_square=" << (pendingMinimapSquare ? 1 : 0) << "\n";
|
||||
out << "minimap_npc_dots=" << (pendingMinimapNpcDots ? 1 : 0) << "\n";
|
||||
out << "separate_bags=" << (pendingSeparateBags ? 1 : 0) << "\n";
|
||||
out << "show_action_bar2=" << (pendingShowActionBar2 ? 1 : 0) << "\n";
|
||||
out << "action_bar2_offset_x=" << pendingActionBar2OffsetX << "\n";
|
||||
out << "action_bar2_offset_y=" << pendingActionBar2OffsetY << "\n";
|
||||
|
||||
// Audio
|
||||
out << "sound_muted=" << (soundMuted_ ? 1 : 0) << "\n";
|
||||
|
|
@ -9143,6 +9185,12 @@ void GameScreen::loadSettings() {
|
|||
} else if (key == "separate_bags") {
|
||||
pendingSeparateBags = (std::stoi(val) != 0);
|
||||
inventoryScreen.setSeparateBags(pendingSeparateBags);
|
||||
} else if (key == "show_action_bar2") {
|
||||
pendingShowActionBar2 = (std::stoi(val) != 0);
|
||||
} else if (key == "action_bar2_offset_x") {
|
||||
pendingActionBar2OffsetX = std::clamp(std::stof(val), -600.0f, 600.0f);
|
||||
} else if (key == "action_bar2_offset_y") {
|
||||
pendingActionBar2OffsetY = std::clamp(std::stof(val), -400.0f, 400.0f);
|
||||
}
|
||||
// Audio
|
||||
else if (key == "sound_muted") {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue