mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
feat: add PvP honor credit toast on honorable kill
SMSG_PVP_CREDIT previously only wrote a system chat message. Now it also fires a new PvpHonorCallback, which game_screen.cpp uses to push a compact dark-red toast at the top-right of the screen showing "⚔ +N Honor" with a 3.5 s lifetime and smooth fade in/out.
This commit is contained in:
parent
59fc7cebaf
commit
129fa84fe3
4 changed files with 97 additions and 0 deletions
|
|
@ -1490,6 +1490,10 @@ public:
|
||||||
using RepChangeCallback = std::function<void(const std::string& factionName, int32_t delta, int32_t standing)>;
|
using RepChangeCallback = std::function<void(const std::string& factionName, int32_t delta, int32_t standing)>;
|
||||||
void setRepChangeCallback(RepChangeCallback cb) { repChangeCallback_ = std::move(cb); }
|
void setRepChangeCallback(RepChangeCallback cb) { repChangeCallback_ = std::move(cb); }
|
||||||
|
|
||||||
|
// PvP honor credit callback (honorable kill or BG reward)
|
||||||
|
using PvpHonorCallback = std::function<void(uint32_t honorAmount, uint64_t victimGuid, uint32_t victimRank)>;
|
||||||
|
void setPvpHonorCallback(PvpHonorCallback cb) { pvpHonorCallback_ = std::move(cb); }
|
||||||
|
|
||||||
// Quest turn-in completion callback
|
// Quest turn-in completion callback
|
||||||
using QuestCompleteCallback = std::function<void(uint32_t questId, const std::string& questTitle)>;
|
using QuestCompleteCallback = std::function<void(uint32_t questId, const std::string& questTitle)>;
|
||||||
void setQuestCompleteCallback(QuestCompleteCallback cb) { questCompleteCallback_ = std::move(cb); }
|
void setQuestCompleteCallback(QuestCompleteCallback cb) { questCompleteCallback_ = std::move(cb); }
|
||||||
|
|
@ -2831,6 +2835,9 @@ private:
|
||||||
RepChangeCallback repChangeCallback_;
|
RepChangeCallback repChangeCallback_;
|
||||||
uint32_t watchedFactionId_ = 0; // auto-set to most recently changed faction
|
uint32_t watchedFactionId_ = 0; // auto-set to most recently changed faction
|
||||||
|
|
||||||
|
// ---- PvP honor credit callback ----
|
||||||
|
PvpHonorCallback pvpHonorCallback_;
|
||||||
|
|
||||||
// ---- Quest completion callback ----
|
// ---- Quest completion callback ----
|
||||||
QuestCompleteCallback questCompleteCallback_;
|
QuestCompleteCallback questCompleteCallback_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -563,6 +563,17 @@ private:
|
||||||
bool otherPlayerLevelUpCallbackSet_ = false;
|
bool otherPlayerLevelUpCallbackSet_ = false;
|
||||||
void renderPlayerLevelUpToasts(game::GameHandler& gameHandler);
|
void renderPlayerLevelUpToasts(game::GameHandler& gameHandler);
|
||||||
|
|
||||||
|
// PvP honor credit toast ("+N Honor" shown when an honorable kill is credited)
|
||||||
|
struct PvpHonorToastEntry {
|
||||||
|
uint32_t honor = 0;
|
||||||
|
uint32_t victimRank = 0; // 0 = unranked / not available
|
||||||
|
float age = 0.0f;
|
||||||
|
};
|
||||||
|
static constexpr float PVP_HONOR_TOAST_DURATION = 3.5f;
|
||||||
|
std::vector<PvpHonorToastEntry> pvpHonorToasts_;
|
||||||
|
bool pvpHonorCallbackSet_ = false;
|
||||||
|
void renderPvpHonorToasts();
|
||||||
|
|
||||||
// Zone discovery text ("Entering: <ZoneName>")
|
// Zone discovery text ("Entering: <ZoneName>")
|
||||||
static constexpr float ZONE_TEXT_DURATION = 5.0f;
|
static constexpr float ZONE_TEXT_DURATION = 5.0f;
|
||||||
float zoneTextTimer_ = 0.0f;
|
float zoneTextTimer_ = 0.0f;
|
||||||
|
|
|
||||||
|
|
@ -1882,6 +1882,9 @@ void GameHandler::handlePacket(network::Packet& packet) {
|
||||||
std::dec, " rank=", rank);
|
std::dec, " rank=", rank);
|
||||||
std::string msg = "You gain " + std::to_string(honor) + " honor points.";
|
std::string msg = "You gain " + std::to_string(honor) + " honor points.";
|
||||||
addSystemChatMessage(msg);
|
addSystemChatMessage(msg);
|
||||||
|
if (pvpHonorCallback_) {
|
||||||
|
pvpHonorCallback_(honor, victimGuid, rank);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -348,6 +348,17 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
||||||
otherPlayerLevelUpCallbackSet_ = true;
|
otherPlayerLevelUpCallbackSet_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up PvP honor credit toast callback (once)
|
||||||
|
if (!pvpHonorCallbackSet_) {
|
||||||
|
gameHandler.setPvpHonorCallback([this](uint32_t honor, uint64_t /*victimGuid*/, uint32_t rank) {
|
||||||
|
if (honor == 0) return;
|
||||||
|
pvpHonorToasts_.push_back({honor, rank, 0.0f});
|
||||||
|
if (pvpHonorToasts_.size() > 4)
|
||||||
|
pvpHonorToasts_.erase(pvpHonorToasts_.begin());
|
||||||
|
});
|
||||||
|
pvpHonorCallbackSet_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up UI error frame callback (once)
|
// Set up UI error frame callback (once)
|
||||||
if (!uiErrorCallbackSet_) {
|
if (!uiErrorCallbackSet_) {
|
||||||
gameHandler.setUIErrorCallback([this](const std::string& msg) {
|
gameHandler.setUIErrorCallback([this](const std::string& msg) {
|
||||||
|
|
@ -680,6 +691,7 @@ void GameScreen::render(game::GameHandler& gameHandler) {
|
||||||
renderWhisperToasts();
|
renderWhisperToasts();
|
||||||
renderQuestProgressToasts();
|
renderQuestProgressToasts();
|
||||||
renderPlayerLevelUpToasts(gameHandler);
|
renderPlayerLevelUpToasts(gameHandler);
|
||||||
|
renderPvpHonorToasts();
|
||||||
renderZoneText();
|
renderZoneText();
|
||||||
|
|
||||||
// World map (M key toggle handled inside)
|
// World map (M key toggle handled inside)
|
||||||
|
|
@ -18214,6 +18226,70 @@ void GameScreen::renderQuestProgressToasts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// PvP honor credit toasts — shown at screen top-right on honorable kill
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void GameScreen::renderPvpHonorToasts() {
|
||||||
|
if (pvpHonorToasts_.empty()) return;
|
||||||
|
|
||||||
|
float dt = ImGui::GetIO().DeltaTime;
|
||||||
|
for (auto& t : pvpHonorToasts_) t.age += dt;
|
||||||
|
pvpHonorToasts_.erase(
|
||||||
|
std::remove_if(pvpHonorToasts_.begin(), pvpHonorToasts_.end(),
|
||||||
|
[](const PvpHonorToastEntry& t) { return t.age >= PVP_HONOR_TOAST_DURATION; }),
|
||||||
|
pvpHonorToasts_.end());
|
||||||
|
if (pvpHonorToasts_.empty()) return;
|
||||||
|
|
||||||
|
ImVec2 displaySize = ImGui::GetIO().DisplaySize;
|
||||||
|
float screenW = displaySize.x > 0.0f ? displaySize.x : 1280.0f;
|
||||||
|
|
||||||
|
// Stack toasts at top-right, below any minimap area
|
||||||
|
constexpr float TOAST_W = 180.0f;
|
||||||
|
constexpr float TOAST_H = 30.0f;
|
||||||
|
constexpr float TOAST_GAP = 3.0f;
|
||||||
|
constexpr float TOAST_TOP = 10.0f;
|
||||||
|
float toastX = screenW - TOAST_W - 10.0f;
|
||||||
|
|
||||||
|
ImDrawList* bgDL = ImGui::GetBackgroundDrawList();
|
||||||
|
const int count = static_cast<int>(pvpHonorToasts_.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
const auto& toast = pvpHonorToasts_[i];
|
||||||
|
|
||||||
|
float remaining = PVP_HONOR_TOAST_DURATION - toast.age;
|
||||||
|
float alpha;
|
||||||
|
if (toast.age < 0.15f)
|
||||||
|
alpha = toast.age / 0.15f;
|
||||||
|
else if (remaining < 0.8f)
|
||||||
|
alpha = remaining / 0.8f;
|
||||||
|
else
|
||||||
|
alpha = 1.0f;
|
||||||
|
alpha = std::clamp(alpha, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
float ty = TOAST_TOP + i * (TOAST_H + TOAST_GAP);
|
||||||
|
|
||||||
|
uint8_t bgA = static_cast<uint8_t>(190 * alpha);
|
||||||
|
uint8_t fgA = static_cast<uint8_t>(255 * alpha);
|
||||||
|
|
||||||
|
// Background: dark red (PvP theme)
|
||||||
|
bgDL->AddRectFilled(ImVec2(toastX, ty), ImVec2(toastX + TOAST_W, ty + TOAST_H),
|
||||||
|
IM_COL32(28, 5, 5, bgA), 4.0f);
|
||||||
|
bgDL->AddRect(ImVec2(toastX, ty), ImVec2(toastX + TOAST_W, ty + TOAST_H),
|
||||||
|
IM_COL32(200, 50, 50, static_cast<uint8_t>(160 * alpha)), 4.0f, 0, 1.2f);
|
||||||
|
|
||||||
|
// Sword ⚔ icon (U+2694, UTF-8: e2 9a 94)
|
||||||
|
bgDL->AddText(ImVec2(toastX + 7.0f, ty + 7.0f),
|
||||||
|
IM_COL32(220, 80, 80, fgA), "\xe2\x9a\x94");
|
||||||
|
|
||||||
|
// "+N Honor" text in gold
|
||||||
|
char buf[40];
|
||||||
|
snprintf(buf, sizeof(buf), "+%u Honor", toast.honor);
|
||||||
|
bgDL->AddText(ImVec2(toastX + 24.0f, ty + 8.0f),
|
||||||
|
IM_COL32(255, 210, 50, fgA), buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Nearby player level-up toasts — shown at screen bottom-centre
|
// Nearby player level-up toasts — shown at screen bottom-centre
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue