From 5468e9745cc3cfe3aac655e16f533e39904c5f70 Mon Sep 17 00:00:00 2001
From: Arkshine <hv.contact@gmail.com>
Date: Fri, 11 Apr 2014 21:54:24 +0200
Subject: [PATCH] Add set/show_dhudmessage (bug 5979, r=ds)

---
 amxmodx/amxmodx.cpp         | 93 +++++++++++++++++++++++++++++++++++++
 amxmodx/amxmodx.h           |  1 +
 amxmodx/util.cpp            | 23 +++++++++
 plugins/include/amxmodx.inc | 37 +++++++++++++++
 4 files changed, 154 insertions(+)

diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp
index 78617190..217b3721 100755
--- a/amxmodx/amxmodx.cpp
+++ b/amxmodx/amxmodx.cpp
@@ -568,6 +568,97 @@ static cell AMX_NATIVE_CALL show_hudmessage(AMX *amx, cell *params) /* 2 param *
 	return len;
 }
 
+static cell AMX_NATIVE_CALL set_dhudmessage(AMX *amx, cell *params) /* 10 param */
+{
+	g_hudset.a1 = 0;
+	g_hudset.a2 = 0;
+	g_hudset.r2 = 255;
+	g_hudset.g2 = 255;
+	g_hudset.b2 = 250;
+	g_hudset.r1 = static_cast<byte>(params[1]);
+	g_hudset.g1 = static_cast<byte>(params[2]);
+	g_hudset.b1 = static_cast<byte>(params[3]);
+	g_hudset.x = amx_ctof(params[4]);
+	g_hudset.y = amx_ctof(params[5]);
+	g_hudset.effect = params[6];;
+	g_hudset.fxTime = amx_ctof(params[7]);
+	g_hudset.holdTime = amx_ctof(params[8]);
+	g_hudset.fadeinTime = amx_ctof(params[9]);
+	g_hudset.fadeoutTime = amx_ctof(params[10]);
+	g_hudset.channel = -1;
+
+	return 1;
+}
+
+static cell AMX_NATIVE_CALL show_dhudmessage(AMX *amx, cell *params) /* 2 param */
+{
+	int len = 0;
+	int index = params[1];
+	char *message;
+
+	if (!index)
+	{
+		for (int i = 1; i <= gpGlobals->maxClients; ++i)
+		{
+			CPlayer *pPlayer = GET_PLAYER_POINTER_I(i);
+
+			if (pPlayer->ingame && !pPlayer->IsBot())
+			{
+				g_langMngr.SetDefLang(i);
+				message = format_amxstring(amx, params, 2, len);
+
+				if (len > 127)	// Client truncates after byte 127.
+				{
+					len = 127;
+
+					// Don't truncate a double-byte character
+					if (((message[len - 1] & 0xFF) >= 0xC2) && ((message[len - 1] & 0xFF) <= 0xEF))
+					{
+						len--;
+					}
+
+					message[len] = 0;
+				}
+
+				UTIL_DHudMessage(pPlayer->pEdict, g_hudset, message, len);
+			}
+		}
+	}
+	else
+	{
+		if (index < 1 || index > gpGlobals->maxClients)
+		{
+			LogError(amx, AMX_ERR_NATIVE, "Invalid player id %d", index);
+			return 0;
+		}
+
+		CPlayer* pPlayer = GET_PLAYER_POINTER_I(index);
+
+		if (pPlayer->ingame && !pPlayer->IsBot())
+		{
+			g_langMngr.SetDefLang(index);
+			message = format_amxstring(amx, params, 2, len);
+
+			if (len > 127)	// Client truncates after byte 127.
+			{
+				len = 127;
+
+				// Don't truncate a double-byte character
+				if (((message[len - 1] & 0xFF) >= 0xC2) && ((message[len - 1] & 0xFF) <= 0xEF))      
+				{
+					--len;
+				}
+
+				message[len] = 0;
+			}
+
+			UTIL_DHudMessage(pPlayer->pEdict, g_hudset, message, len);
+		}
+	}
+
+	return len;
+}
+
 static cell AMX_NATIVE_CALL get_user_name(AMX *amx, cell *params) /* 3 param */
 {
 	int index = params[1];
@@ -4925,6 +5016,7 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
 	{"set_cvar_num",			set_cvar_num},
 	{"set_cvar_string",			set_cvar_string},
 	{"set_fail_state",			set_fail_state},
+	{"set_dhudmessage",			set_dhudmessage},
 	{"set_hudmessage",			set_hudmessage},
 	{"set_localinfo",			set_localinfo},
 	{"set_pcvar_flags",			set_pcvar_flags},
@@ -4936,6 +5028,7 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
 	{"set_user_info",			set_user_info},
 	{"set_xvar_float",			set_xvar_num},
 	{"set_xvar_num",			set_xvar_num},
+	{"show_dhudmessage",		show_dhudmessage}, 
 	{"show_hudmessage",			show_hudmessage},
 	{"show_menu",				show_menu},
 	{"show_motd",				show_motd},
diff --git a/amxmodx/amxmodx.h b/amxmodx/amxmodx.h
index 26d092ad..04316b9b 100755
--- a/amxmodx/amxmodx.h
+++ b/amxmodx/amxmodx.h
@@ -140,6 +140,7 @@ void UTIL_ClientPrint(edict_t *pEntity, int msg_dest, char *msg);
 void UTIL_FakeClientCommand(edict_t *pEdict, const char *cmd, const char *arg1 = NULL, const char *arg2 = NULL);
 void UTIL_GetFlags(char* flags, int flag);
 void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage);
+void UTIL_DHudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage, unsigned int length);
 void UTIL_IntToString(int value, char *output);
 void UTIL_ShowMOTD(edict_t *client, char *motd, int mlen, const char *name);
 void UTIL_ShowMenu(edict_t* pEntity, int slots, int time, char *menu, int mlen);
diff --git a/amxmodx/util.cpp b/amxmodx/util.cpp
index 9236981d..ed5b7bf5 100755
--- a/amxmodx/util.cpp
+++ b/amxmodx/util.cpp
@@ -273,6 +273,29 @@ void UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const ch
 	MESSAGE_END();
 }
 
+void UTIL_DHudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage, unsigned int length)
+{
+	#define DRC_CMD_MESSAGE 6
+
+	if (pEntity)
+		MESSAGE_BEGIN(MSG_ONE_UNRELIABLE, SVC_DIRECTOR, NULL, pEntity);
+	else
+		MESSAGE_BEGIN(MSG_BROADCAST, SVC_DIRECTOR);
+
+	WRITE_BYTE(length + 31); // message length (counting WRITE size)
+	WRITE_BYTE(DRC_CMD_MESSAGE);
+	WRITE_BYTE(textparms.effect);
+	WRITE_LONG(textparms.b1 + (textparms.g1 << 8) + (textparms.r1 << 16)); // pack color.
+	WRITE_LONG(amx_ftoc(textparms.x));
+	WRITE_LONG(amx_ftoc(textparms.y));
+	WRITE_LONG(amx_ftoc(textparms.fadeinTime));
+	WRITE_LONG(amx_ftoc(textparms.fadeoutTime));
+	WRITE_LONG(amx_ftoc(textparms.holdTime));
+	WRITE_LONG(amx_ftoc(textparms.fxTime));
+	WRITE_STRING(pMessage); // max length: 128. Truncated on the client.
+	MESSAGE_END();
+}
+
 /* warning - buffer of msg must be longer than 190 chars!
 (here in AMX it is always longer) */
 void UTIL_ClientPrint(edict_t *pEntity, int msg_dest, char *msg)
diff --git a/plugins/include/amxmodx.inc b/plugins/include/amxmodx.inc
index 99e666ae..6478ef94 100755
--- a/plugins/include/amxmodx.inc
+++ b/plugins/include/amxmodx.inc
@@ -179,6 +179,43 @@ native set_hudmessage(red=200, green=100, blue=0, Float:x=-1.0, Float:y=0.35, ef
 /* Displays HUD message to given player. */
 native show_hudmessage(index,const message[],any:...);
 
+/**
+ * Sets the Director HUD parameters for drawing text. 
+ *
+ * These parameters are stored globally, although nothing other than this function and set_hudmessage modify them. 
+ * You must call this function before drawing text. If you are drawing text to multiple clients, you can set the 
+ * parameters once, since they won't be modified. However, as soon as you pass control back to other plugins, 
+ * you must reset the parameters next time you draw.
+ * 
+ * @param red			The red color value.
+ * @param green			The green color value.
+ * @param blue			The blue color value.
+ * @param x				The x coordinate (abscissa). From 0,0 to 1.0.  -1.0 is the center.
+ * @param y				The y coordinate (ordinate). From 0,0 to 1.0. - 1.0 is the center.
+ * @param effects		The effect value. 0 = fade in/fade out, 1 is flickery credits, 2 is write out (training room).
+ * @param fxtime		The duration of chosen effect (may not apply to all effects).
+ * @param holdtime		The Number of seconds to hold the text.
+ * @param fadeintime	The number of seconds to spend fading in.	
+ * @param fadeoutime	The number of seconds to spend fading out.	
+ */
+native set_dhudmessage(red=200, green=100, blue=0, Float:x=-1.0, Float:y=0.35, effects=0, Float:fxtime=6.0, Float:holdtime=12.0, Float:fadeintime=0.1, Float:fadeouttime=0.2);
+
+/**
+ * Shows a Director HUD message to a client. Usually such message has a bigger letter size.
+ * Ideally used to show static/persistent message. 
+ *
+ * Unlike classic HUD message which is channel-based, Director HUD message is stack-based. Don't expect same behavior.
+ * You can have up to 8 messages displatying at once. If you try more, the first will be overwritten, then second, etc.
+ * Each message is limited to 128 characters. This will be automatically truncated by the native.
+ * Due to its way for working, there is no native to clear a specific message.
+ *
+ * @param index			THe client index to send the message to. Use 0 to send to all connected clients.
+ * @param message		The message text or formatting rules.
+ * @param ...			The message formatting parameters.
+ * @return				On success, the formatted message length. Otherwise 0.
+ */
+native show_dhudmessage(index, const message[], any:...);
+
 /* Displays menu. Keys have bit values (key 1 is (1<<0), key 5 is (1<<4) etc.). */
 native show_menu(index,keys,const menu[], time = -1, const title[] = "");