From 37d37804582636db5a2e5b03dddc4b2dfbf95f09 Mon Sep 17 00:00:00 2001
From: RedEnchilada <redenchilada@derpymail.com>
Date: Wed, 18 Jun 2014 15:28:09 -0500
Subject: [PATCH] Add hook for chat messages, including csays

---
 src/hu_stuff.c    |  6 +++++
 src/lua_hook.h    |  2 ++
 src/lua_hooklib.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)

diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 96902c732c..ccb97f2f87 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -48,6 +48,7 @@
 
 #ifdef HAVE_BLUA
 #include "lua_hud.h"
+#include "lua_hook.h"
 #endif
 
 // coords are scaled
@@ -513,6 +514,11 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 			}
 		}
 	}
+	
+#ifdef HAVE_BLUA
+	if (LUAh_PlayerMsg(playernum, target, flags, msg))
+		return;
+#endif
 
 	// If it's a CSAY, just CECHO and be done with it.
 	if (flags & HU_CSAY)
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 0c22092a2e..a19516cdd3 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -36,6 +36,7 @@ enum hook {
 	hook_BotTiccmd,
 	hook_BotAI,
 	hook_LinedefExecute,
+	hook_PlayerMsg,
 
 	hook_MAX // last hook
 };
@@ -61,5 +62,6 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Ho
 boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd
 boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name
 boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo); // Hook for linedef executors
+boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
 
 #endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index ed9f53d2ce..2a6bd1af15 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -14,6 +14,7 @@
 #ifdef HAVE_BLUA
 #include "doomstat.h"
 #include "p_mobj.h"
+#include "g_game.h"
 #include "r_things.h"
 #include "b_bot.h"
 #include "z_zone.h"
@@ -46,6 +47,7 @@ const char *const hookNames[hook_MAX+1] = {
 	"BotTiccmd",
 	"BotAI",
 	"LinedefExecute",
+	"PlayerMsg",
 	NULL
 };
 
@@ -862,4 +864,58 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo)
 	return true;
 }
 
+// Hook for PlayerMsg -Red
+boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
+{
+	boolean handled = false;
+	
+	if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8))))
+		return false;
+	
+	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
+	I_Assert(lua_istable(gL, -1));
+	lua_rawgeti(gL, -1, hook_PlayerMsg);
+	lua_remove(gL, -2);
+	I_Assert(lua_istable(gL, -1));
+	
+	LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player
+	
+	if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c
+		lua_pushinteger(gL, 3); // type
+		lua_pushnil(gL); // target
+	} else if (target == -1) { // sayteam
+		lua_pushinteger(gL, 1); // type
+		lua_pushnil(gL); // target
+	} else if (target == 0) { // say
+		lua_pushinteger(gL, 0); // type
+		lua_pushnil(gL); // target
+	} else { // sayto
+		lua_pushinteger(gL, 2); // type
+		LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
+	}
+	
+	lua_pushstring(gL, msg); // msg
+	
+	lua_pushnil(gL);
+	
+	while (lua_next(gL, -6)) {
+		lua_pushvalue(gL, -6); // source
+		lua_pushvalue(gL, -6); // type
+		lua_pushvalue(gL, -6); // target
+		lua_pushvalue(gL, -6); // msg
+		if (lua_pcall(gL, 4, 1, 0)) {
+			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+			lua_pop(gL, 1);
+			continue;
+		}
+		if (lua_toboolean(gL, -1))
+			handled = true;
+		lua_pop(gL, 1); // pop return value
+	}
+	lua_pop(gL, 4); // pop arguments and mobjtype table
+
+	lua_gc(gL, LUA_GCSTEP, 1);
+	return handled;
+}
+
 #endif
-- 
GitLab