diff --git a/CMakeLists.txt b/CMakeLists.txt index 42bebfa..65fb598 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,8 @@ set(CLIENT_ONLY_SOURCES "src/gui/font.cpp" "src/gui/menu.hpp" "src/gui/menu.cpp" + "src/gui/use_target_hud.hpp" + "src/gui/use_target_hud.cpp" "src/utils/files.cpp" ) diff --git a/src/client/app.cpp b/src/client/app.cpp index ea7202d..ada3577 100644 --- a/src/client/app.cpp +++ b/src/client/app.cpp @@ -44,7 +44,7 @@ void App::Frame() params.env.clear_color = glm::vec3(0.1f); dlist_.Clear(); - gui_.Begin(); + gui_.Begin(viewport_size_); // draw session if (session_) diff --git a/src/client/app.hpp b/src/client/app.hpp index ca0e020..51cc79d 100644 --- a/src/client/app.hpp +++ b/src/client/app.hpp @@ -40,7 +40,7 @@ public: void Input(game::PlayerInputType in, bool pressed, bool repeated); void MouseMove(const glm::vec2& delta); - float GetTime() const { return time_; } + const float& GetTime() const { return time_; } float GetDeltaTime() const { return delta_time_; } game::view::ClientSession* GetSession() { return session_.get(); } diff --git a/src/game/player.cpp b/src/game/player.cpp index b576175..c07b433 100644 --- a/src/game/player.cpp +++ b/src/game/player.cpp @@ -69,6 +69,14 @@ void game::Player::SendChat(const std::string& text) msg.Write(chatm); } +void game::Player::SetUseTarget(const std::string& text, const std::string& error_text, float delay) +{ + auto msg = BeginMsg(net::MSG_USETARGET); + msg.Write(net::UseTargetName(text)); + msg.Write(net::UseTargetName(error_text)); + msg.Write(delay); +} + game::Player::~Player() { game_.PlayerLeft(*this); diff --git a/src/game/player.hpp b/src/game/player.hpp index 09d42d4..6ecde1a 100644 --- a/src/game/player.hpp +++ b/src/game/player.hpp @@ -32,6 +32,7 @@ public: void SetCamera(net::EntNum entnum); void SendChat(const std::string& text); + void SetUseTarget(const std::string& text, const std::string& error_text, float delay); const std::string& GetName() const { return name_; } diff --git a/src/game/player_character.cpp b/src/game/player_character.cpp index 150dd14..33ada45 100644 --- a/src/game/player_character.cpp +++ b/src/game/player_character.cpp @@ -164,16 +164,13 @@ void game::PlayerCharacter::SendUseTargetInfo() if (!use_target_) { - player_->SendChat("už nejde nic použít"); + player_->SetUseTarget(std::string(), std::string(), 0.0f); return; } - std::string msg = "[E] " + use_target_->desc; + std::string error_text; + if (use_error_) + error_text = use_error_; - if (using_) - { - msg += " (zbývá " + std::to_string(use_delay_ - use_progress_) + ")"; - } - - player_->SendChat(msg); + player_->SetUseTarget(use_target_->desc, error_text, using_ ? use_delay_ - use_progress_ : 0.0f); } diff --git a/src/game/player_character.hpp b/src/game/player_character.hpp index 0180bf6..ec5cda4 100644 --- a/src/game/player_character.hpp +++ b/src/game/player_character.hpp @@ -26,6 +26,7 @@ public: private: void UpdateInputs(); + void UpdateUseTarget(); void UseChanged(bool enabled); void SendUseTargetInfo(); diff --git a/src/gameview/client_session.cpp b/src/gameview/client_session.cpp index 9fdb2db..78d35a4 100644 --- a/src/gameview/client_session.cpp +++ b/src/gameview/client_session.cpp @@ -7,7 +7,7 @@ #include "vehicleview.hpp" #include "utils/version.hpp" -game::view::ClientSession::ClientSession(App& app) : app_(app) +game::view::ClientSession::ClientSession(App& app) : app_(app), use_target_hud_(app.GetTime()) { // send login auto msg = BeginMsg(net::MSG_ID); @@ -46,6 +46,9 @@ bool game::view::ClientSession::ProcessSingleMessage(net::MessageType type, net: case net::MSG_CHAT: return ProcessChatMsg(msg); + case net::MSG_USETARGET: + return ProcessUseTargetMsg(msg); + default: // try pass the msg to world if (world_ && world_->ProcessMsg(type, msg)) @@ -97,6 +100,8 @@ void game::view::ClientSession::Draw(gfx::DrawList& dlist, gfx::DrawListParams& { DrawWorld(dlist, params, gui); } + + use_target_hud_.Draw(gui); } void game::view::ClientSession::GetViewInfo(glm::vec3& eye, glm::mat4& view) const @@ -166,6 +171,18 @@ bool game::view::ClientSession::ProcessChatMsg(net::InMessage& msg) return true; } +bool game::view::ClientSession::ProcessUseTargetMsg(net::InMessage& msg) +{ + net::UseTargetName text, error_text; + float delay; + + if (!msg.Read(text) || !msg.Read(error_text) || !msg.Read(delay)) + return false; + + use_target_hud_.SetData(text, error_text, delay); + return true; +} + void game::view::ClientSession::DrawWorld(gfx::DrawList& dlist, gfx::DrawListParams& params, gui::Context& gui) { // glm::mat4 view = glm::lookAt(glm::vec3(15.0f, 0.0f, 1.0f), glm::vec3(0.0f, 0.0f, -13.0f), glm::vec3(0.0f, diff --git a/src/gameview/client_session.hpp b/src/gameview/client_session.hpp index 3b861d5..7c99908 100644 --- a/src/gameview/client_session.hpp +++ b/src/gameview/client_session.hpp @@ -10,6 +10,7 @@ #include "net/inmessage.hpp" #include "net/msg_producer.hpp" #include "game/player_input.hpp" +#include "gui/use_target_hud.hpp" class App; @@ -39,6 +40,7 @@ private: bool ProcessWorldMsg(net::InMessage& msg); bool ProcessCameraMsg(net::InMessage& msg); bool ProcessChatMsg(net::InMessage& msg); + bool ProcessUseTargetMsg(net::InMessage& msg); void DrawWorld(gfx::DrawList& dlist, gfx::DrawListParams& params, gui::Context& gui); @@ -56,6 +58,8 @@ private: net::ViewYawQ view_yaw_q_; net::ViewPitchQ view_pitch_q_; float last_send_time_ = 0.0f; + + gui::UseTargetHud use_target_hud_; }; } // namespace game::view \ No newline at end of file diff --git a/src/gui/context.cpp b/src/gui/context.cpp index 962d8ee..01e3694 100644 --- a/src/gui/context.cpp +++ b/src/gui/context.cpp @@ -10,11 +10,13 @@ gui::Context::Context(gfx::DrawList& dlist, std::shared_ptr default_ white_tex_ = assets::CacheManager::GetTexture("data/white.png"); } -void gui::Context::Begin() +void gui::Context::Begin(const glm::vec2& viewport_size) { vertices_.clear(); indices_.clear(); ranges_.clear(); + + viewport_size_ = viewport_size; } void gui::Context::DrawRect(const glm::vec2& p0, const glm::vec2& p1, uint32_t color) diff --git a/src/gui/context.hpp b/src/gui/context.hpp index 1be2f87..59a8699 100644 --- a/src/gui/context.hpp +++ b/src/gui/context.hpp @@ -32,7 +32,7 @@ class Context public: Context(gfx::DrawList& dlist, std::shared_ptr default_font); - void Begin(); + void Begin(const glm::vec2& viewport_size); void DrawRect(const glm::vec2& p0, const glm::vec2& p1, uint32_t color); @@ -43,6 +43,8 @@ public: void Render(); const std::shared_ptr& GetFont() const { return font_; } + + const glm::vec2& GetViewportSize() const { return viewport_size_; } private: void BeginTexture(const gfx::Texture* texture); @@ -61,7 +63,7 @@ private: std::vector indices_; std::vector ranges_; - + glm::vec2 viewport_size_ = glm::vec2(1.0f); }; diff --git a/src/gui/use_target_hud.cpp b/src/gui/use_target_hud.cpp new file mode 100644 index 0000000..01cd21f --- /dev/null +++ b/src/gui/use_target_hud.cpp @@ -0,0 +1,87 @@ +#include "use_target_hud.hpp" + +gui::UseTargetHud::UseTargetHud(const float& time) : time_(time) {} + +void gui::UseTargetHud::SetData(std::string text, std::string error_text, float delay) +{ + text_ = std::move(text); + + if (error_text.empty()) + error_text_.clear(); + else + error_text_ = "(" + error_text + ")"; + + start_time_ = time_; + end_time_ = delay > 0.01f ? start_time_ + delay : start_time_; +} + +void gui::UseTargetHud::Draw(Context& ctx) const +{ + if (text_.empty()) + return; + + bool active = start_time_ != end_time_; + + const float spacing = 20.0f; + glm::vec2 key_size(30.0f); + glm::vec2 text_size = ctx.MeasureText(text_); + float total_width = key_size.x + spacing + text_size.x; + + glm::vec2 error_size(0.0f); + if (!error_text_.empty()) + { + error_size = ctx.MeasureText(error_text_); + total_width += spacing + error_size.x; + } + + glm::vec2 progress_size(60.0f, 10.0f); + if (active) + { + total_width += spacing + progress_size.x; + } + + auto& viewport_size = ctx.GetViewportSize(); + float center_x = viewport_size.x * 0.5f; + float center_y = viewport_size.y - 50.0f; + float x = center_x - total_width * 0.5f; + + // draw key bg + glm::vec2 bg_p0(x, center_y - key_size.y * 0.5f); + glm::vec2 bg_p1 = bg_p0 + key_size; + ctx.DrawRect(bg_p0, bg_p1, 0x77000000); + + // draw key text + static constexpr std::string_view key_text = "E"; + ctx.DrawTextAligned(key_text, bg_p0 + key_size * 0.5f, glm::vec2(-0.5f, -0.5f)); + + x += key_size.x + spacing; + + // draw text + glm::vec2 text_p(x, center_y - text_size.y * 0.5f); + ctx.DrawText(text_, text_p); + + x += text_size.x + spacing; + + // draw error text + if (!error_text_.empty()) + { + glm::vec2 error_text_p(x, center_y - error_size.y * 0.5f); + ctx.DrawText(error_text_, error_text_p); + + x += error_size.x + spacing; + } + + // draw progress bar + if (active) + { + float t = (time_ - start_time_) / (end_time_ - start_time_); + t = glm::clamp(t, 0.0f, 1.0f); + + glm::vec2 progress_p0(x, center_y - progress_size.y * 0.5f); + glm::vec2 progress_p1 = progress_p0 + progress_size; + glm::vec2 progress_p1_bar = progress_p0 + glm::vec2(t * progress_size.x, progress_size.y); + + ctx.DrawRect(progress_p0, progress_p1, 0x77000000); + ctx.DrawRect(progress_p0, progress_p1_bar, 0xFF00FFFF); + } +} diff --git a/src/gui/use_target_hud.hpp b/src/gui/use_target_hud.hpp new file mode 100644 index 0000000..cec44fa --- /dev/null +++ b/src/gui/use_target_hud.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "context.hpp" + +namespace gui +{ + +class UseTargetHud +{ +public: + UseTargetHud(const float& time); + + void SetData(std::string text, std::string error_text, float delay); + + void Draw(Context& ctx) const; + +private: + const float& time_; + std::string text_; + std::string error_text_; + float start_time_ = 0.0f; + float end_time_ = 0.0f; +}; + + +} \ No newline at end of file diff --git a/src/net/defs.hpp b/src/net/defs.hpp index 21d8d77..04a1394 100644 --- a/src/net/defs.hpp +++ b/src/net/defs.hpp @@ -34,6 +34,9 @@ enum MessageType : uint8_t // CAM MSG_CAM, + // USETARGET ... + MSG_USETARGET, + /*~~~~~~~~ Entity ~~~~~~~~*/ // ENTSPAWN data... MSG_ENTSPAWN, @@ -132,11 +135,13 @@ using ObjCount = ObjNum; using NumTexels = uint16_t; // version - using Version = uint32_t; // tuning - using TuningPartIdx = uint8_t; +// use target +using UseTargetName = FixedStr<128>; +using UseDelayQ = Quantized; + } // namespace net \ No newline at end of file diff --git a/src/utils/version.hpp b/src/utils/version.hpp index 6e73e7b..c66c621 100644 --- a/src/utils/version.hpp +++ b/src/utils/version.hpp @@ -1,3 +1,3 @@ #pragma once -#define FEKAL_VERSION 2026032101 +#define FEKAL_VERSION 2026032201