• You've discovered RedGuides, an EverQuest multi-boxing and scripting community 🧙‍♀️⚙️. We want you to play several EQ characters at once, come join us and say hello! 👋

  • A TLP without truebox has thawed (Very Vanilla ready)
    Frostreaver

MQ2ChatBlock

vladus2000

Active member
Joined
Dec 1, 2006
RedCents
131¢
Vlad presents MQ2ChatBlock!

This is a simple plugin that allows you to block the normal avenues of chat (say, tell, gsay, etc) as well as emotes. It requires MQ2PacketApi or any other form of OnSendPacket support. It contains methods to bypass the blocks as well, save emote. The channels that are blocked are saved per char, so you can set it and forget it.

WARNING: USE AT YOUR OWN RISK

This is a packet hack, while I have made every attempt to test and ensure this doesn't cause problems, it could, I'm only human. MQ2Pax /saytarget and /hailtarget will likely fail if you block /say. Various other plugins/macros may bomb as well. Its even possible certain in game triggers could fail (I thought some raid forced either emotes or says, cannot remember anymore and no idea how this will affect it).

Usage:

Rich (BB code):
/chatblock [<#> | <channelName> | all | status] | [block | unblock | status]
/chatblock without block unblock or status will toggle

The following commands should be self evident, they will send even if you block the channel:

/ffsay
/rrsay
/ssay
/ftell
/ftt
/freply
/oooc
/aauction
/sshout
/ggsay
/gguildsay
/hhail

code:

Rich (BB code):
#include "../MQ2Plugin.h"

#ifndef PKT_CHANNEL_MESSAGE
#define PKT_CHANNEL_MESSAGE  0x0b5a // 2007-02-16
#endif

#ifndef PKT_EMOTE_MESSAGE
#define PKT_EMOTE_MESSAGE   0x40d0  // 2007-02-16
#endif

#define PLUGIN_NAME "MQ2ChatBlock"
PreSetup(PLUGIN_NAME);
PLUGIN_VERSION(1.11);

// most certainly stolen, unsure of original author, name changed to not cause issues
typedef struct _CHATPACKET
{
/*0000*/ char target[64];
/*0064*/ char sender[64];
/*0128*/ unsigned int language;
/*0132*/ unsigned int channel;
/*0136*/ char padding136[8]; //0x01
/*0144*/ unsigned int languageskill;
/*0148*/ char message[100];

} ChatPacket;

DWORD   blockFlags = 0;
char    INIFileName2[ MAX_STRING ];
char   *channels[] = { "guildsay", "1", "gsay", "shout", "auction", "ooc", "6",
	"tell", "say", "9", "10", "11", "12", "13", "14", "rsay", "16", "17", "18", "19",
	"20", "fsay", "22", "23", "24", "25", "26", "27", "28", "29", "30", "emote" };

void Configure( void )
{
	PCHARINFO MySelf = GetCharInfo();

	if ( MySelf )
	{
		sprintf( INIFileName2, "%s\\%s_%s.ini", gszINIPath, EQADDR_SERVERNAME, MySelf->Name );
	}

	CHAR    buf[ 256 ];
	if ( GetPrivateProfileString( PLUGIN_NAME, "blockFlags", "0", buf, sizeof( buf ), INIFileName2 ) )
	{
		sscanf( buf, "%08x", &blockFlags );
	}

}

PLUGIN_API BOOL OnSendPacket( DWORD Type, PVOID Packet, DWORD Size )
{
	if ( Type == PKT_CHANNEL_MESSAGE )
	{
		ChatPacket *pChatPacket = (ChatPacket*)Packet;

		if ( pChatPacket->channel < 31 && ( blockFlags & ( 1 << pChatPacket->channel ) ) != 0 )
		{
			WriteChatf( "\arBlocked your chat to %s (channel %d)!", channels[ pChatPacket->channel ], pChatPacket->channel );
			return false;
		}
	}
	else if ( Type == PKT_EMOTE_MESSAGE && ( blockFlags & ( 1 << 31 ) ) )
	{
		WriteChatf( "\arBlocked your emote!" );
		return false;
	}

	return true;

}

void BlockIt( DWORD channel, DWORD mode )
{
	DWORD mask = 1 << channel;

	if ( mode == 0 )
	{
		mode = ( blockFlags & mask ) ? 2 : 1;
	}

	switch ( mode )
	{
		case 1:
			blockFlags |= mask;
			WriteChatf( "\arBlocking all of %s", channels[ channel ] );
			break;
		case 2:
			blockFlags &= ~mask;
			WriteChatf( "\agUnblocking all of %s", channels[ channel ] );
			break;
		case 3:
			WriteChatf( "%s%s is currently %sblocked", ( blockFlags & mask ) ? "\ar" : "\ag",
					channels[ channel ], ( blockFlags & mask ) ? "" : "un" );
			break;
	}

}

VOID ChatBlock( PSPAWNINFO pChar, PCHAR szLine )
{
    CHAR szCommand[MAX_STRING] = {0}; 
    GetArg( szCommand, szLine, 1 );
	size_t len = strlen( szCommand );

	int i;
	if ( stricmp( szCommand, "status" ) == 0 )
	{
		WriteChatf( "\arBlocked Channels:" );
		int mask;
		for ( i = 0, mask = 1; i < sizeof( channels ) / sizeof( char* ); i++, mask <<= 1 )
		{
			if ( blockFlags & mask )
			{
				WriteChatf( "\ar    %s (%d)", channels[ i ], i );
			}
		}
		return;
	}

	DWORD mode = 0;

	if ( strstr( szLine, "unblock" ) )
		mode = 2;
	else if ( strstr( szLine, "block" )  )
		mode = 1;
	else if ( strstr( szLine, "status" ) )
		mode = 3;

	bool save = false;
	if ( len )
	{
		DWORD channel = atoi( szCommand );

		if ( ( channel > 0 && channel < 31 ) || ( channel == 0 && szCommand[ 0 ] == '0' ) )
		{
			BlockIt( channel, mode );
			save = true;
		}
		else if ( stricmp( szCommand, "all" ) == 0 )
		{
			for ( i = 0; i < sizeof( channels ) / sizeof( char* ); i++ )
			{
				BlockIt( i, mode );
			}
			save = true;
		}
		else for ( i = sizeof( channels ) / sizeof( char* ) - 1; i >= 0; i-- )
		{
			if ( strnicmp( channels[ i ], szCommand, len ) == 0 )
			{
				BlockIt( i, mode );
				save = true;
				break;
			}
		}
	}

	if ( save )
	{
		char    buf[ 256 ];
		sprintf( buf, "%08x", blockFlags );
		WritePrivateProfileString( PLUGIN_NAME, "blockFlags", buf, INIFileName2 );
	}
	else
	{
		WriteChatf( "/chatblock [<#> | <channelName> | all | status] | [block | unblock | status]" );
		WriteChatf( "/chatblock without block unblock or status will toggle" );
		WriteChatf( "" );
		WriteChatf( "Requires a plugin that adds OnSendPacket support (ex. MQ2PacketApi)" );
	}

}

VOID SendChat( PSPAWNINFO pChar, PCHAR szLine, unsigned int channel, PCHAR szTarget )
{
	if ( pChar )
	{
		ChatPacket  cp = { 0 };

		cp.channel       = ( channel == 0xffffffff ) ? 8 : channel;
		cp.languageskill = 100;

		if ( szTarget )
		{
			strcpy( cp.target, szTarget );
		}
		strcpy( cp.sender, pChar->Name );
		strncpy( cp.message, szLine, sizeof( cp.message ) - 1 );
		cp.message[ sizeof( cp.message ) - 1 ] = 0;

		// handle hails with target
		if ( channel == 0xffffffff && szTarget )
			cp.padding136[ 0 ] = 1;

		memchecks_tramp( EQADDR_GWORLD, PKT_CHANNEL_MESSAGE, (char *)&cp, sizeof( cp ), TRUE );
	}
}

VOID Ggsay( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You tell your party, '%s'", szLine );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_ECHO_GROUP, false ); 

		SendChat( pChar, szLine, 2, NULL );
	}
}

VOID Ssay( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You say, '%s'", szLine );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_ECHO_SAY, false ); 

		SendChat( pChar, szLine, 8, ( pTarget ) ? ( ( PSPAWNINFO )pTarget )->Name : NULL );
	}
}

VOID Gguildsay( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You say to your guild, '%s'", szLine );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_ECHO_GUILD, false ); 

		SendChat( pChar, szLine, 0, NULL );
	}
}

VOID Sshout( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You shout, '%s'", szLine );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_ECHO_SHOUT, false ); 

		SendChat( pChar, szLine, 3, NULL );
	}
}

VOID Aauction( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You auction, '%s'", szLine );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_ECHO_AUCTION, false ); 

		SendChat( pChar, szLine, 4, NULL );
	}
}

VOID Oooc( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You say out of character, '%s'", szLine );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_ECHO_OOC, false ); 

		SendChat( pChar, szLine, 5, NULL );
	}
}

VOID Rrsay( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You tell your raid, '%s'", szLine );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_RAID, false ); 

		SendChat( pChar, szLine, 15, NULL );
	}
}

VOID Ffsay( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];

		_snprintf( command, sizeof( command ), "You say to your fellowship, '%s'", szLine );
		// no clue on the color for this one
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_EMOTE, false ); 

		SendChat( pChar, szLine, 21, NULL );
	}
}

VOID Ftell( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char szName[ MAX_STRING ];

		GetArg( szName, szLine, 0 );
		szLine = GetNextArg( szLine );

		SendChat( pChar, szLine, 7, szName );
	}
}

VOID Ftt( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME && pTarget )
	{
		SendChat( pChar, szLine, 7, ( ( PSPAWNINFO )pTarget )->Name );
	}
}

VOID Freply( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		SendChat( pChar, szLine, 7, &EQADDR_LASTTELL[0] );
	}
}

VOID Hhail( PSPAWNINFO pChar, PCHAR szLine )
{
	if ( pChar && gGameState == GAMESTATE_INGAME )
	{
		char command[ MAX_STRING ];
		char szText[ MAX_STRING ];
		char *pName = ( pTarget ) ? ( ( PSPAWNINFO )pTarget )->DisplayedName : NULL;

		if ( pName )
			sprintf( szText, "Hail, %s", pName );
		else
			strcpy( szText, "Hail" );

		_snprintf( command, sizeof( command ), "You say, '%s'", szText );
		(*ppEverQuest)->dsp_chat( command, USERCOLOR_ECHO_SAY, false ); 

		SendChat( pChar, szText, 0xffffffff, pName );
	}
}

// Called once directly after initialization, and then every time the gamestate changes
PLUGIN_API VOID SetGameState(DWORD GameState)
{
	if ( GameState == GAMESTATE_INGAME )
		Configure();
}

// Called once, when the plugin is to initialize
PLUGIN_API VOID InitializePlugin(VOID)
{
	DebugSpewAlways("Initializing MQ2ChatBlock");
	AddCommand( "/chatblock", ChatBlock );
	AddCommand( "/ffsay", Ffsay );
	AddCommand( "/rrsay", Rrsay );
	AddCommand( "/ssay", Ssay );
	AddCommand( "/ftell", Ftell );
	AddCommand( "/ftt", Ftt );
	AddCommand( "/freply", Freply );
	AddCommand( "/oooc", Oooc );
	AddCommand( "/aauction", Aauction );
	AddCommand( "/sshout", Sshout );
	AddCommand( "/ggsay", Ggsay );
	AddCommand( "/gguildsay", Gguildsay );
	AddCommand( "/hhail", Hhail );
}

// Called once, when the plugin is to shutdown
PLUGIN_API VOID ShutdownPlugin(VOID)
{
	DebugSpewAlways("Shutting down MQ2ChatBlock");
	RemoveCommand( "/chatblock" );
	RemoveCommand( "/ffsay" );
	RemoveCommand( "/rrsay" );
	RemoveCommand( "/ssay" );
	RemoveCommand( "/ftell" );
	RemoveCommand( "/ftt" );
	RemoveCommand( "/ftreply" );
	RemoveCommand( "/oooc" );
	RemoveCommand( "/aauction" );
	RemoveCommand( "/sshout" );
	RemoveCommand( "/ggsay" );
	RemoveCommand( "/gguildsay" );
	RemoveCommand( "/hhail" );
}
 
Last edited:
I forgot to add why I wrote this. I have accidentally done :setma tankname and 'setma tankname and announced to the world that yes I use MQ2. This is not a good thing on a raid. I also have another plugin that I may post someday that takes groupsay and routes it to /bc. I have twice unloaded this, forgotten about it and accidentally said something....less than ideal to say in a public channel. I have seen other people fall victim to : or ' as well.
 
One thing about rerouting group say to /bc, you can just type /alias /g /bc and it should do the same thing heh.
 
I do more than just alias it...and that doesn't work if group is your default channel, which is how I have that set up. That would be one way to do it. I have a message so that you know its going to /bc and it shows up as group chat to everyone in bc. So if you have a trigger to ask for haste in group, you just type haste, and it appears to the macro at the other end that it came from group. This is of course not necessary, as you could change the macro to accept /bc commands, but it makes it easier to read when it in your chat window with tells, etc instead of the mq2 window.
 
MQ2ChatBlock

Users who are viewing this thread

Back
Top
Cart