diff --git a/regamedll/dlls/API/CAPI_Impl.cpp b/regamedll/dlls/API/CAPI_Impl.cpp index 398c8a136..7708d1f83 100644 --- a/regamedll/dlls/API/CAPI_Impl.cpp +++ b/regamedll/dlls/API/CAPI_Impl.cpp @@ -402,4 +402,19 @@ bool CReGameApi::BGetIGameRules(const char *pchVersion) const return false; } +void CReGameApi::QueueHudMessage(int client, const struct hudtextparms_s &textparms, const char *pMessage) +{ + if (client == 0) + { + for (int i = 1; i <= gpGlobals->maxClients; i++) + { + g_HudQueue.QueueMessage(i, textparms, pMessage); + } + } + else + { + g_HudQueue.QueueMessage(client, textparms, pMessage); + } +} + EXPOSE_SINGLE_INTERFACE(CReGameApi, IReGameApi, VRE_GAMEDLL_API_VERSION); diff --git a/regamedll/dlls/API/CAPI_Impl.h b/regamedll/dlls/API/CAPI_Impl.h index 4bb154a9a..855097c6b 100644 --- a/regamedll/dlls/API/CAPI_Impl.h +++ b/regamedll/dlls/API/CAPI_Impl.h @@ -1116,4 +1116,5 @@ class CReGameApi: public IReGameApi { EXT_FUNC virtual AmmoInfoStruct *GetAmmoInfoEx(const char *ammoName); EXT_FUNC virtual bool BGetICSEntity(const char *pchVersion) const; EXT_FUNC virtual bool BGetIGameRules(const char *pchVersion) const; + EXT_FUNC virtual void QueueHudMessage(int client, const struct hudtextparms_s &textparms, const char *pMessage); }; diff --git a/regamedll/dlls/client.cpp b/regamedll/dlls/client.cpp index daee11d12..ec1a0829e 100644 --- a/regamedll/dlls/client.cpp +++ b/regamedll/dlls/client.cpp @@ -3910,7 +3910,7 @@ void EXT_FUNC PlayerPostThink(edict_t *pEntity) void EXT_FUNC ParmsNewLevel() { - ; + g_HudQueue.Reset(); } void EXT_FUNC ParmsChangeLevel() @@ -3933,6 +3933,7 @@ void EXT_FUNC StartFrame() return; } + g_HudQueue.Think(); CLocalNav::Think(); gpGlobals->teamplay = 1.0f; diff --git a/regamedll/dlls/hud_queue.cpp b/regamedll/dlls/hud_queue.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/regamedll/dlls/util.cpp b/regamedll/dlls/util.cpp index e0ffed532..36c8d442f 100644 --- a/regamedll/dlls/util.cpp +++ b/regamedll/dlls/util.cpp @@ -592,47 +592,128 @@ void UTIL_ScreenFade(CBaseEntity *pEntity, const Vector &color, float fadeTime, UTIL_ScreenFadeWrite(fade, pEntity); } +CHudMessageQueue g_HudQueue; + +CHudMessageQueue::CHudMessageQueue() { + Reset(); +} + +void CHudMessageQueue::Reset() { + for (int i = 0; i < 33; i++) { + for (int j = 0; j < NUM_HUD_CHANNELS; j++) { + m_players[i].channelFreeTime[j] = 0.0f; + } + for (int j = 0; j < MAX_HUD_QUEUE; j++) { + m_players[i].messages[j].inUse = false; + } + } +} + +void CHudMessageQueue::QueueMessage(int client, const hudtextparms_t &textparms, const char *pMessage) { + if (client < 1 || client >= 33) return; + + int freeSlot = -1; + for (int i = 0; i < MAX_HUD_QUEUE; i++) { + if (!m_players[client].messages[i].inUse) { + freeSlot = i; + break; + } + } + + if (freeSlot == -1) { + return; + } + + m_players[client].messages[freeSlot].textparms = textparms; + Q_strlcpy(m_players[client].messages[freeSlot].message, pMessage, sizeof(m_players[client].messages[freeSlot].message)); + m_players[client].messages[freeSlot].inUse = true; +} + +void CHudMessageQueue::Think() { + float currentTime = gpGlobals->time; + + for (int i = 1; i <= gpGlobals->maxClients; i++) { + CBaseEntity *pPlayer = UTIL_PlayerByIndex(i); + if (!pPlayer || !pPlayer->IsNetClient()) + continue; + + for (int j = 0; j < MAX_HUD_QUEUE; j++) { + if (!m_players[i].messages[j].inUse) + continue; + + hudtextparms_t parms = m_players[i].messages[j].textparms; + + int targetChannel = parms.channel - 1; + if (parms.channel <= 0 || parms.channel > NUM_HUD_CHANNELS) { + int bestChannel = 0; + float oldestTime = m_players[i].channelFreeTime[0]; + for (int c = 1; c < NUM_HUD_CHANNELS; c++) { + if (m_players[i].channelFreeTime[c] < oldestTime) { + oldestTime = m_players[i].channelFreeTime[c]; + bestChannel = c; + } + } + targetChannel = bestChannel; + parms.channel = bestChannel + 1; + } + + if (currentTime >= m_players[i].channelFreeTime[targetChannel]) { + UTIL_HudMessage(pPlayer, parms, m_players[i].messages[j].message); + m_players[i].channelFreeTime[targetChannel] = currentTime + parms.fadeinTime + parms.holdTime + parms.fadeoutTime + 0.2f; + + m_players[i].messages[j].inUse = false; + } + } + } +} + void UTIL_HudMessage(CBaseEntity *pEntity, const hudtextparms_t &textparms, const char *pMessage) { if (!pEntity || !pEntity->IsNetClient()) return; MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, nullptr, pEntity->edict()); - WRITE_BYTE(TE_TEXTMESSAGE); - WRITE_BYTE(textparms.channel & 0xFF); - WRITE_SHORT(FixedSigned16(textparms.x, (1<<13))); - WRITE_SHORT(FixedSigned16(textparms.y, (1<<13))); - WRITE_BYTE(textparms.effect); - WRITE_BYTE(textparms.r1); - WRITE_BYTE(textparms.g1); - WRITE_BYTE(textparms.b1); - WRITE_BYTE(textparms.a1); - WRITE_BYTE(textparms.r2); - WRITE_BYTE(textparms.g2); - WRITE_BYTE(textparms.b2); - WRITE_BYTE(textparms.a2); - WRITE_SHORT(FixedUnsigned16(textparms.fadeinTime, (1<<8))); - WRITE_SHORT(FixedUnsigned16(textparms.fadeoutTime, (1<<8))); - WRITE_SHORT(FixedUnsigned16(textparms.holdTime, (1<<8))); - - if (textparms.effect == 2) - WRITE_SHORT(FixedUnsigned16(textparms.fxTime, (1<<8))); - - if (!pMessage) - WRITE_STRING(" "); + WRITE_BYTE(TE_TEXTMESSAGE); + WRITE_BYTE(textparms.channel & 0xFF); + + WRITE_SHORT(FixedSigned16(textparms.x, 1 << 13)); + WRITE_SHORT(FixedSigned16(textparms.y, 1 << 13)); + WRITE_BYTE(textparms.effect); + + WRITE_BYTE(textparms.r1); + WRITE_BYTE(textparms.g1); + WRITE_BYTE(textparms.b1); + WRITE_BYTE(textparms.a1); + + WRITE_BYTE(textparms.r2); + WRITE_BYTE(textparms.g2); + WRITE_BYTE(textparms.b2); + WRITE_BYTE(textparms.a2); + + WRITE_SHORT(FixedUnsigned16(textparms.fadeinTime, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(textparms.fadeoutTime, 1 << 8)); + WRITE_SHORT(FixedUnsigned16(textparms.holdTime, 1 << 8)); + + if (textparms.effect == 2) + WRITE_SHORT(FixedUnsigned16(textparms.fxTime, 1 << 8)); + + if (!pMessage) + { + WRITE_STRING(" "); + } + else + { + if (Q_strlen(pMessage) >= 512) + { + char tmp[512]; + Q_strlcpy(tmp, pMessage); + WRITE_STRING(tmp); + } else { - if (Q_strlen(pMessage) >= 512) - { - char tmp[512]; - Q_strlcpy(tmp, pMessage); - WRITE_STRING(tmp); - } - else - { - WRITE_STRING(pMessage); - } + WRITE_STRING(pMessage); } + } MESSAGE_END(); } diff --git a/regamedll/dlls/util.h b/regamedll/dlls/util.h index f96be669b..6b55681c7 100644 --- a/regamedll/dlls/util.h +++ b/regamedll/dlls/util.h @@ -227,6 +227,36 @@ void UTIL_ScreenFadeBuild(ScreenFade &fade, const Vector &color, float fadeTime, void UTIL_ScreenFadeWrite(const ScreenFade &fade, CBaseEntity *pEntity); void UTIL_ScreenFadeAll(const Vector &color, float fadeTime, float fadeHold, int alpha, int flags); void UTIL_ScreenFade(CBaseEntity *pEntity, const Vector &color, float fadeTime, float fadeHold = 0.0f, int alpha = 0, int flags = 0); +// ---------------------------------------------------- +// Native HUD Messages Queue +// ---------------------------------------------------- +#define MAX_HUD_QUEUE 10 +#define NUM_HUD_CHANNELS 4 + +struct QueuedHudMessage_t { + hudtextparms_t textparms; + char message[512]; + bool inUse; +}; + +class CHudMessageQueue { +public: + CHudMessageQueue(); + + void QueueMessage(int client, const hudtextparms_t &textparms, const char *pMessage); + void Think(); + void Reset(); + +private: + struct PlayerHudQueue { + QueuedHudMessage_t messages[MAX_HUD_QUEUE]; + float channelFreeTime[NUM_HUD_CHANNELS]; + }; + PlayerHudQueue m_players[33]; +}; + +extern CHudMessageQueue g_HudQueue; + void UTIL_HudMessage(CBaseEntity *pEntity, const hudtextparms_t &textparms, const char *pMessage); void UTIL_HudMessageAll(const hudtextparms_t &textparms, const char *pMessage); void UTIL_ClientPrintAll(int msg_dest, const char *msg_name, const char *param1 = nullptr, const char *param2 = nullptr, const char *param3 = nullptr, const char *param4 = nullptr); diff --git a/regamedll/public/regamedll/regamedll_api.h b/regamedll/public/regamedll/regamedll_api.h index 466ec4b42..2cbb06a3d 100644 --- a/regamedll/public/regamedll/regamedll_api.h +++ b/regamedll/public/regamedll/regamedll_api.h @@ -856,6 +856,7 @@ class IReGameApi { virtual struct AmmoInfoStruct *GetAmmoInfoEx(const char *ammoName) = 0; virtual bool BGetICSEntity(const char *pchVersion) const = 0; virtual bool BGetIGameRules(const char *pchVersion) const = 0; + virtual void QueueHudMessage(int client, const struct hudtextparms_s &textparms, const char *pMessage) = 0; }; #define VRE_GAMEDLL_API_VERSION "VRE_GAMEDLL_API_VERSION001"