Example #1
0
static void CG_RestoreClientGhoul_f( void ) {
	//rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably)
	int			indexNum = 0;
	int			argNum = trap->Cmd_Argc();
	centity_t	*clent;
	qboolean	IRCG = qfalse;

	if ( !strcmp( CG_Argv( 0 ), "ircg" ) )
		IRCG = qtrue;

	if ( argNum < 1 ) {
		assert( 0 );
		return;
	}

	indexNum = atoi( CG_Argv( 1 ) );
	if ( indexNum < 0 || indexNum >= MAX_CLIENTS ) {
		assert( 0 );
		return;
	}

	clent = &cg_entities[indexNum];

	//assert( clent->ghoul2 );
	//this can happen while connecting as a client
	if ( !clent->ghoul2 )
		return;

#ifdef _DEBUG
	if ( !trap->G2_HaveWeGhoul2Models( clent->ghoul2 ) )
		assert( !"Tried to reset state on a bad instance. Crash is inevitable." );
#endif

	if ( IRCG ) {
		int bodyIndex = 0;
		int weaponIndex = 0;
		int side = 0;
		centity_t *body;

		assert( argNum >= 3 );
		bodyIndex = atoi( CG_Argv( 2 ) );
		weaponIndex = atoi( CG_Argv( 3 ) );
		side = atoi( CG_Argv( 4 ) );

		body = &cg_entities[bodyIndex];

		if ( side )
			body->teamPowerType = qtrue; //light side
		else
			body->teamPowerType = qfalse; //dark side

		CG_BodyQueueCopy( body, clent->currentState.number, weaponIndex );
	}

	//reattach any missing limbs
	if ( clent->torsoBolt )
		CG_ReattachLimb(clent);

	//make sure ragdoll state is reset
	if ( clent->isRagging ) {
		clent->isRagging = qfalse;
		trap->G2API_SetRagDoll( clent->ghoul2, NULL ); //calling with null parms resets to no ragdoll.
	}

	//clear all the decals as well
	trap->G2API_ClearSkinGore( clent->ghoul2 );

	clent->weapon = 0;
	clent->ghoul2weapon = NULL; //force a weapon reinit
}
Example #2
0
static void CG_BodyQueueCopy(centity_t *cent, int clientNum, int knownWeapon)
{
	centity_t		*source;
	animation_t		*anim;
	float			animSpeed;
	int				flags=BONE_ANIM_OVERRIDE_FREEZE;

	if (cent->ghoul2)
	{
		trap->G2API_CleanGhoul2Models(&cent->ghoul2);
	}

	if (clientNum < 0 || clientNum >= MAX_CLIENTS)
	{
		return;
	}

	source = &cg_entities[ clientNum ];

	if (!source)
	{
		return;
	}

	if (!source->ghoul2)
	{
		return;
	}

	cent->isRagging = qfalse; //reset in case it's still set from another body that was in this cent slot.
	cent->ownerRagging = source->isRagging; //if the owner was in ragdoll state, then we want to go into it too right away.

#if 0
	VectorCopy(source->lerpOriginOffset, cent->lerpOriginOffset);
#endif

	cent->bodyFadeTime = 0;
	cent->bodyHeight = 0;

	cent->dustTrailTime = source->dustTrailTime;

	trap->G2API_DuplicateGhoul2Instance(source->ghoul2, &cent->ghoul2);

	if (source->isRagging)
	{ //just reset it now.
		source->isRagging = qfalse;
		trap->G2API_SetRagDoll(source->ghoul2, NULL); //calling with null parms resets to no ragdoll.
	}

	//either force the weapon from when we died or remove it if it was a dropped weapon
	if (knownWeapon > WP_BRYAR_PISTOL && trap->G2API_HasGhoul2ModelOnIndex(&(cent->ghoul2), 1))
	{
		trap->G2API_RemoveGhoul2Model(&(cent->ghoul2), 1);
	}
	else if (trap->G2API_HasGhoul2ModelOnIndex(&(cent->ghoul2), 1))
	{
		trap->G2API_CopySpecificGhoul2Model(CG_G2WeaponInstance(cent, knownWeapon), 0, cent->ghoul2, 1);
	}

	if (!cent->ownerRagging)
	{
		int aNum;
		int eFrame;
		qboolean fallBack = qfalse;

		//anim = &bgAllAnims[cent->localAnimIndex].anims[ cent->currentState.torsoAnim ];
		if (!BG_InDeathAnim(source->currentState.torsoAnim))
		{ //then just snap the corpse into a default
			anim = &bgAllAnims[source->localAnimIndex].anims[ BOTH_DEAD1 ];
			fallBack = qtrue;
		}
		else
		{
			anim = &bgAllAnims[source->localAnimIndex].anims[ source->currentState.torsoAnim ];
		}
		animSpeed = 50.0f / anim->frameLerp;

		if (!fallBack)
		{
			//this will just set us to the last frame of the animation, in theory
			aNum = cgs.clientinfo[source->currentState.number].frame+1;

			while (aNum >= anim->firstFrame+anim->numFrames)
			{
				aNum--;
			}

			if (aNum < anim->firstFrame-1)
			{ //wrong animation...?
				aNum = (anim->firstFrame+anim->numFrames)-1;
			}
		}
		else
		{
			aNum = anim->firstFrame;
		}

		eFrame = anim->firstFrame + anim->numFrames;

		//if (!cgs.clientinfo[source->currentState.number].frame || (cent->currentState.torsoAnim) != (source->currentState.torsoAnim) )
		//{
		//	aNum = (anim->firstFrame+anim->numFrames)-1;
		//}

		trap->G2API_SetBoneAnim(cent->ghoul2, 0, "upper_lumbar", aNum, eFrame, flags, animSpeed, cg.time, -1, 150);
		trap->G2API_SetBoneAnim(cent->ghoul2, 0, "model_root", aNum, eFrame, flags, animSpeed, cg.time, -1, 150);
		trap->G2API_SetBoneAnim(cent->ghoul2, 0, "Motion", aNum, eFrame, flags, animSpeed, cg.time, -1, 150);
	}

	//After we create the bodyqueue, regenerate any limbs on the real instance
	if (source->torsoBolt)
	{
		CG_ReattachLimb(source);
	}
}
static void CG_ServerCommand( void ) {
	const char	*cmd;
	char		text[MAX_NOTIFICATION_CHARS]; // extra bytes for name
	qboolean	IRCG = qfalse;

	cmd = CG_Argv(0);

	if ( !cmd[0] ) {
		// server claimed the command
		return;
	}

	// Jedi Knight Galaxies
	// Check the crossover
	if ( uiImports->HandleServerCommand( cmd ) )
		return;

	if (!strcmp(cmd, "svr")) { // Server redirect
		CG_ServerRedirect();
		return;
	}

	if (!strcmp(cmd, "cin")) {
		Cin_ProcessCinematic_f();
		return;
	}

	if (!strcmp(cmd, "cinb")) {
		Cin_ProcessCinematicBinary_f();
		return;
	}

	if (!strcmp(cmd, "cb")) {
		CinBuild_Cmd_f();
		return;
	}

	if (!strcmp(cmd, "cbb")) {
		Cmd_CBB_f();
		return;
	}
	if (!strcmp(cmd, "dc")) {
		cg.deathcamFadeStart = cg.time;
		cg.deathcamTime = atoi(_Cmd_Argv(1));
		cg.deathcamRadius = atoi(_Cmd_Argv(2));
		VectorSet(cg.deathcamCenter, atof(_Cmd_Argv(3)),atof(_Cmd_Argv(4)),atof(_Cmd_Argv(5)));
		ChatBox_CloseChat();
		return;
	}

	if (!strcmp(cmd, "dcr")) {
		cg.deathcamFadeStart = 0;
		cg.deathcamTime = 0;
		cg.deathcamRadius = 0;
		VectorSet(cg.deathcamCenter, 0, 0, 0);
		return;
	}

	// Forced weapon change
	if (!strcmp(cmd, "chw")) {
		cg.weaponSelect = atoi(CG_Argv(1));
		return;
	}

	if (!strcmp(cmd, "clearinv"))
	{
		cg.playerInventory->clear();
		return;
	}

	if ( !strcmp( cmd, "spc" ) )
	{
		trap->Cvar_Set("ui_myteam", "3");
		trap->OpenUIMenu(UIMENU_PLAYERCONFIG); //UIMENU_CLASSSEL
		return;
	}

	if ( !strcmp( cmd, "nfr" ) )
	{ //"nfr" == "new force rank" (want a short string)
		int doMenu = 0;
		int setTeam = 0;
		int newRank = 0;

		if (trap->Cmd_Argc() < 3)
		{
#ifdef _DEBUG
			Com_Printf("WARNING: Invalid newForceRank string\n");
#endif
			return;
		}

		newRank = atoi(CG_Argv(1));
		doMenu = atoi(CG_Argv(2));
		setTeam = atoi(CG_Argv(3));

		trap->Cvar_Set("ui_rankChange", va("%i", newRank));

		trap->Cvar_Set("ui_myteam", va("%i", setTeam));

		if (!( trap->Key_GetCatcher() & KEYCATCH_UI ) && doMenu)
		{
			trap->OpenUIMenu(UIMENU_PLAYERCONFIG);
		}

		return;
	}

	if ( !strcmp( cmd, "kg2" ) )
	{ //Kill a ghoul2 instance in this slot.
	  //If it has been occupied since this message was sent somehow, the worst that can (should) happen
	  //is the instance will have to reinit with its current info.
		int indexNum = 0;
		int argNum = trap->Cmd_Argc();
		int i = 1;
		
		if (argNum < 1)
		{
			return;
		}

		while (i < argNum)
		{
			indexNum = atoi(CG_Argv(i));

			if (cg_entities[indexNum].ghoul2 && trap->G2_HaveWeGhoul2Models(cg_entities[indexNum].ghoul2))
			{
				if (indexNum < MAX_CLIENTS)
				{ //You try to do very bad thing!
#ifdef _DEBUG
					Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n");
#endif
					return;
				}

				CG_KillCEntityG2(indexNum);
			}

			i++;
		}
		
		return;
	}

	if (!strcmp(cmd, "kls"))
	{ //kill looping sounds
		int indexNum = 0;
		int argNum = trap->Cmd_Argc();
		centity_t *clent = NULL;
		centity_t *trackerent = NULL;
		
		if (argNum < 1)
		{
			assert(0);
			return;
		}

		indexNum = atoi(CG_Argv(1));

		if (indexNum != -1)
		{
			clent = &cg_entities[indexNum];
		}

		if (argNum >= 2)
		{
			indexNum = atoi(CG_Argv(2));

			if (indexNum != -1)
			{
				trackerent = &cg_entities[indexNum];
			}
		}

		if (clent)
		{
			CG_S_StopLoopingSound(clent->currentState.number, -1);
		}
		if (trackerent)
		{
			CG_S_StopLoopingSound(trackerent->currentState.number, -1);
		}

		return;
	}

	//eezstreet add
	if ( !strcmp (cmd, "aciset") )
	{
		int number = atoi(CG_Argv(1));
		cg.weaponSelect = number;
		return;
	}

	if ( !strcmp (cmd, "ieq") )
	{
	    if ( trap->Cmd_Argc() == 3 )
	    {
	        int newItem = atoi (CG_Argv (1));
	        int oldItem = atoi (CG_Argv (2));
	        
			(*cg.playerInventory)[newItem].equipped = true;
			if (oldItem != -1) {
				(*cg.playerInventory)[oldItem].equipped = false;
			}
	        uiImports->InventoryNotify( INVENTORYNOTIFY_UPDATE );
	    }
	    return;
	}
	
	if ( !strcmp (cmd, "iueq") )
	{
	    if ( trap->Cmd_Argc() == 2 )
	    {
	        int slot = atoi (CG_Argv (1));
			(*cg.playerInventory)[slot].equipped = false;
	        uiImports->InventoryNotify( INVENTORYNOTIFY_UPDATE );
	    }
	    
	    return;
	}
	if ( !strcmp (cmd, "inventory_update") )
	{
		cg.predictedPlayerState.credits = atoi(CG_Argv(1));
		uiImports->InventoryNotify (INVENTORYNOTIFY_UPDATE);
		return;
	}

	if(!strcmp(cmd, "frcaci"))
	{
		// Force ACI
		JKG_CG_FillACISlot(atoi(CG_Argv(0)), atoi(CG_Argv(1)));
		return;
	}

	if (!strcmp(cmd, "ircg"))
	{ //this means param 2 is the body index and we want to copy to bodyqueue on it
		IRCG = qtrue;
	}

	if (!strcmp(cmd, "rcg") || IRCG)
	{ //rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably)
		int indexNum = 0;
		int argNum = trap->Cmd_Argc();
		centity_t *clent;
		
		if (argNum < 1)
		{
			assert(0);
			return;
		}

		indexNum = atoi(CG_Argv(1));
		if (indexNum < 0 || indexNum >= MAX_CLIENTS)
		{
			assert(0);
			return;
		}

		clent = &cg_entities[indexNum];

		//assert(clent->ghoul2);
		if (!clent->ghoul2)
		{ //this can happen while connecting as a client
			return;
		}

#ifdef _DEBUG
		if (!trap->G2_HaveWeGhoul2Models(clent->ghoul2))
		{
			assert(!"Tried to reset state on a bad instance. Crash is inevitable.");
		}
#endif

		if (IRCG)
		{
			int bodyIndex = 0;
			int weaponIndex = 0;
			int weaponVariation = 0;
			int side = 0;
			centity_t *body;

			assert(argNum >= 4);
			bodyIndex = atoi(CG_Argv(2));
			weaponIndex = atoi(CG_Argv(3));
			weaponVariation = atoi (CG_Argv (4));
			side = atoi(CG_Argv(5));

			body = &cg_entities[bodyIndex];

			if (side)
			{
				body->teamPowerType = qtrue; //light side
			}
			else
			{
				body->teamPowerType = qfalse; //dark side
			}

			CG_BodyQueueCopy(body, clent->currentState.number, weaponIndex, weaponVariation);
		}

		//reattach any missing limbs
		if (clent->torsoBolt)
		{
			CG_ReattachLimb(clent);
		}

		//make sure ragdoll state is reset
		if (clent->isRagging)
		{
			clent->isRagging = qfalse;
			trap->G2API_SetRagDoll(clent->ghoul2, NULL); //calling with null parms resets to no ragdoll.
		}
		
		//clear all the decals as well
		trap->G2API_ClearSkinGore(clent->ghoul2);

		clent->weapon = 0;
		clent->ghoul2weapon = NULL; //force a weapon reinit

		return;
	}

	if ( !strcmp( cmd, "cp" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		CG_CheckSVStringEdRef(strEd, CG_Argv(1));
		CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
		return;
	}

	if ( !strcmp( cmd, "cps" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		char *x = (char *)CG_Argv(1);
		if (x[0] == '@')
		{
			x++;
		}
		trap->SE_GetStringTextString(x, strEd, MAX_STRINGED_SV_STRING);
		CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
		return;
	}

	if ( !strcmp( cmd, "cs" ) ) {
		CG_ConfigStringModified();
		return;
	}

	// Warzone Tickets...
	if ( !strcmp( cmd, "tkt" ) ) {
		//CG_Printf("CG_Argv(0) = %s. CG_Argv(1) = %s. CG_Argv(2) = %s. CG_Argv(3) = %s.\n", CG_Argv(0), CG_Argv(1), CG_Argv(2), CG_Argv(3));
		cgs.redtickets = atoi(CG_Argv(1));
		cgs.bluetickets = atoi(CG_Argv(2));
		return;
	}

	if ( !strcmp( cmd, "print" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		CG_CheckSVStringEdRef(strEd, CG_Argv(1));
		trap->Print( "%s", strEd );
		return;
	}

	if ( !strcmp( cmd, "chat" ) ) {
		if ( !cg_teamChatsOnly.integer ) {
			trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
			Q_strncpyz( text, CG_Argv(2), sizeof (text) );
			CG_RemoveChatEscapeChar( text );
			CG_ChatBox_AddString(text, atoi(CG_Argv(1)));
			trap->Print( "*%s\n", text );
		}
		return;
	}

	if ( !strcmp( cmd, "tchat" ) ) {
		trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
		Q_strncpyz( text, CG_Argv(2), MAX_SAY_TEXT );
		CG_RemoveChatEscapeChar( text );
		CG_ChatBox_AddString(text, atoi(CG_Argv(1)));
		trap->Print( "*%s\n", text );

		return;
	}

	//chat with location, possibly localized.
	if ( !strcmp( cmd, "lchat" ) ) {
		if ( !cg_teamChatsOnly.integer ) {
			char name[MAX_STRING_CHARS];
			char loc[MAX_STRING_CHARS];
			char color[8];
			char message[MAX_STRING_CHARS];
			int fadeLevel;

			if (trap->Cmd_Argc() < 4)
			{
				return;
			}
			fadeLevel = atoi(CG_Argv(1));
			strcpy(name, CG_Argv(2));
			strcpy(loc, CG_Argv(3));
			strcpy(color, CG_Argv(4));
			strcpy(message, CG_Argv(5));

			if (loc[0] == '@')
			{ //get localized text
				trap->SE_GetStringTextString(loc+1, loc, MAX_STRING_CHARS);
			}

			trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
			//Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT );
			Com_sprintf(text, MAX_SAY_TEXT, "%s<%s>^%s%s", name, loc, color, message);
			CG_RemoveChatEscapeChar( text );
			CG_ChatBox_AddString(text, fadeLevel);
			trap->Print( "*%s\n", text );
		}
		return;
	}
	if ( !strcmp( cmd, "ltchat" ) ) {
		char name[MAX_STRING_CHARS];
		char loc[MAX_STRING_CHARS];
		char color[8];
		char message[MAX_STRING_CHARS];
		int fadeLevel;

		if (trap->Cmd_Argc() < 4)
		{
			return;
		}
		fadeLevel = atoi(CG_Argv(1));
		strcpy(name, CG_Argv(2));
		strcpy(loc, CG_Argv(3));
		strcpy(color, CG_Argv(4));
		strcpy(message, CG_Argv(5));

		if (loc[0] == '@')
		{ //get localized text
			trap->SE_GetStringTextString(loc+1, loc, MAX_STRING_CHARS);
		}

		trap->S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
		//Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT );
		Com_sprintf(text, MAX_SAY_TEXT, "%s<%s> ^%s%s", name, loc, color, message);
		CG_RemoveChatEscapeChar( text );
		CG_ChatBox_AddString(text, fadeLevel);
		trap->Print( "*%s\n", text );

		return;
	}

	if ( !strcmp( cmd, "scores" ) ) {
		CG_ParseScores();
		return;
	}

	if ( !strcmp( cmd, "tinfo" ) ) {
		CG_ParseTeamInfo();
		return;
	}

	if ( !strcmp( cmd, "map_restart" ) ) {
		CG_MapRestart();
		return;
	}

	if ( !strcmp( cmd, "fmrefresh" ) ) {
		JKG_FireModeUpdate();
		return;
	}

	//[OverflowProtection]
	//this command was vulnerable to buffer overflow and could cause problems due to not properly returning 
	//after processing the command.
	if ( !strcmp( cmd, "remapShader" ) ) 
	{
		if ( trap->Cmd_Argc() == 4 )
		{
			char shader1[MAX_QPATH];
			char shader2[MAX_QPATH];
			Q_strncpyz( shader1, CG_Argv( 1 ), sizeof( shader1 ) );
			Q_strncpyz( shader2, CG_Argv( 2 ), sizeof( shader2 ) );
			trap->R_RemapShader( shader1, shader2, CG_Argv( 3 ) );
			return;
		}
		return;
	}
	//[/OverflowProtection]

	// loaddeferred can be both a servercmd and a consolecmd
	if ( !strcmp( cmd, "loaddefered" ) ) {	// FIXME: spelled wrong, but not changing for demo
		CG_LoadDeferredPlayers();
		return;
	}

	// clientLevelShot is sent before taking a special screenshot for
	// the menu system during development
	if ( !strcmp( cmd, "clientLevelShot" ) ) {
		cg.levelShot = qtrue;
		return;
	}

	// Team Party List
	if ( !strcmp( cmd, "tpl" ))
	{
		int i, iID, iLen;

		for ( i = 0, iLen = (( trap->Cmd_Argc() - 1 ) / 5 ); i < iLen; i++ )
		{
			iID	= atoi( CG_Argv( i * 5 + 1 ));
			cgs.partyList[iID].id = atoi( CG_Argv( i * 5 + 2 ));
			cgs.partyList[iID].classId = atoi( CG_Argv( i * 5 + 3 ));
			cgs.partyList[iID].time	= atoi( CG_Argv( i * 5 + 4 ));
			Q_strncpyz( cgs.partyList[iID].message, ( char * ) CG_Argv( i * 5 + 5 ), sizeof( cgs.partyList[iID].message ));

			if ( cgs.partyList[iID].time > cgs.partyListTime )
			{
				cgs.partyListTime = cgs.partyList[iID].time;
			}
		}
		/* Notify UI */
		uiImports->PartyMngtNotify( PARTYNOTIFY_UPDATESEEKERS );
		return;
	}

	// Team Party Invites
	if ( !strcmp( cmd, "tpi" ))
	{
		/* Can't do this with an active party o.o */
		cgs.party.active = 0;

		/* Scan the incoming string into the party struct */
		sscanf( CG_Argv( 1 ), "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
			&cgs.party.invites[0].id, &cgs.party.invites[0].leaderId, &cgs.party.invites[0].memberCount,
			&cgs.party.invites[1].id, &cgs.party.invites[1].leaderId, &cgs.party.invites[1].memberCount,
			&cgs.party.invites[2].id, &cgs.party.invites[2].leaderId, &cgs.party.invites[2].memberCount,
			&cgs.party.invites[3].id, &cgs.party.invites[3].leaderId, &cgs.party.invites[3].memberCount,
			&cgs.party.invites[4].id, &cgs.party.invites[4].leaderId, &cgs.party.invites[4].memberCount );

		/* Win cake */

		/* Notify UI */
		uiImports->PartyMngtNotify( PARTYNOTIFY_UPDATESTATE );
		return;
	}

	// Team Party Update
	if ( !strcmp( cmd, "tpu" ))
	{
		int i;

		/* Set the party status to active */
		cgs.party.active = 1;

		/* Scan the incoming string into the party struct */
		sscanf( CG_Argv( 1 ), "%i %i %i %i %i %i %i %i %i %i %i",
			&cgs.party.number,
			&cgs.party.members[0].id, &cgs.party.members[0].classId,
			&cgs.party.members[1].id, &cgs.party.members[1].classId,
			&cgs.party.members[2].id, &cgs.party.members[2].classId,
			&cgs.party.members[3].id, &cgs.party.members[3].classId,
			&cgs.party.members[4].id, &cgs.party.members[4].classId );

		/* Parse the members and fix the status and ID's! */
		for ( i = 0; i < 5; i++ )
		{
			if ( cgs.party.members[i].id < 0 )
			{
				cgs.party.members[i].id = abs( cgs.party.members[i].id + 1 );
				cgs.party.members[i].status = -1;
			}
			else
			{
				cgs.party.members[i].status = 0;
			}
		}

		/* Set the party leader status accordingly */
		cgs.party.members[0].status = 1;

		/* Notify UI */
		uiImports->PartyMngtNotify( PARTYNOTIFY_UPDATESTATE );
		return;
	}

	if( !strcmp( cmd, "pInv" ))
	{
		BG_ReceivedItemPacket(BG_ItemPacketFromName(CG_Argv(1)));
		uiImports->ItemsUpdated();
		return;
	}

	if (!strcmp(cmd, "pTrade"))
	{
		BG_ReceivedTradePacket(BG_TradePacketFromName(CG_Argv(1)));
		uiImports->ItemsUpdated();
		return;
	}

	// UQ1: Use an event!!!!
	// eez: Again, this is only getting sent to one client, so no go
	if( !strcmp( cmd, "hitmarker") )
	{
		// All this does is make a hitmarker display. Nothing too fancy.
		trap->S_StartSound(NULL, cg.clientNum, CHAN_AUTO, cgs.media.hitmarkerSound);
		cg.hitmarkerLastTime = cg.time + 1000;
		return;
	}

	if( !strcmp( cmd, "notify") )
	{
		// add a notification to the display
		CG_Notifications_Add((char *)CG_Argv(2), qfalse);	// first arg is ignored. it's supposed to specify the type of message but it's unused.
		return;
	}

	if (!strcmp(cmd, "apc"))
	{
		// Ammo price check response
		uiImports->InventoryPriceCheckResult(atoi(CG_Argv(1)), atoi(CG_Argv(2)));
		return;
	}

	if (!strcmp(cmd, "cbi"))
	{
		// Client bought item
		char* playerName = va("%s", CG_Argv(2));
		for (int i = 3; i < trap->Cmd_Argc(); i++)
		{
			playerName = va("%s %s", playerName, CG_Argv(i));
		}
		JKG_ClientBoughtItem(playerName, atoi(CG_Argv(1)));
		return;
	}
	//eezstreet end

	trap->Print( "Unknown client game command: %s\n", cmd );
}
Example #4
0
// The string has been tokenized and can be retrieved with Cmd_Argc() / Cmd_Argv()
static void CG_ServerCommand( void ) {
	const char	*cmd;
	char		text[MAX_SAY_TEXT];
	qboolean	IRCG = qfalse;

	if ( JPLua_Event_ServerCommand() )
		return;

	cmd = CG_Argv( 0 );

	// server claimed the command
	if ( !cmd[0] )
		return;

	if ( !strcmp( cmd, "sxd" ) ) {
		// siege extended data, contains extra info certain classes may want to know about other clients
		CG_ParseSiegeExtendedData();
		return;
	}

	if ( !strcmp( cmd, "sb" ) ) {
		// siege briefing display
		CG_SiegeBriefingDisplay( atoi( CG_Argv( 1 ) ), qfalse );
		return;
	}

	if ( !strcmp( cmd, "scl" ) ) {
		trap->OpenUIMenu( UIMENU_CLASSSEL );
		return;
	}

	if ( !strcmp( cmd, "spc" ) ) {
		if ( !cg.demoPlayback ) {
			trap->Cvar_Set( "ui_myteam", "3" );
			trap->OpenUIMenu( UIMENU_PLAYERCONFIG );
		}
		return;
	}

	if ( !strcmp( cmd, "nfr" ) ) {
		// new force rank
		int doMenu = 0, setTeam = 0, newRank = 0;

		if ( trap->Cmd_Argc() < 3 ) {
#ifdef _DEBUG
			Com_Printf( "WARNING: Invalid newForceRank string\n" );
#endif
			return;
		}

		newRank = atoi( CG_Argv( 1 ) );
		doMenu = atoi( CG_Argv( 2 ) );
		setTeam = atoi( CG_Argv( 3 ) );

		trap->Cvar_Set( "ui_rankChange", va( "%i", newRank ) );

		trap->Cvar_Set( "ui_myteam", va( "%i", setTeam ) );

		if ( !(trap->Key_GetCatcher() & KEYCATCH_UI) && doMenu && !cg.demoPlayback )
			trap->OpenUIMenu( UIMENU_PLAYERCONFIG );

		return;
	}

	if ( !strcmp( cmd, "kg2" ) ) {
		// Kill a ghoul2 instance in this slot.
		// If it has been occupied since this message was sent somehow, the worst that can (should) happen is the instance
		//	will have to reinit with its current info.
		int i, indexNum = 0, argNum = trap->Cmd_Argc();

		if ( argNum < 1 )
			return;

		for ( i = 1; i < argNum; i++ ) {
			indexNum = atoi( CG_Argv( i ) );

			if ( cg_entities[indexNum].ghoul2 && trap->G2_HaveWeGhoul2Models( cg_entities[indexNum].ghoul2 ) ) {
				if ( indexNum < MAX_CLIENTS ) { //You try to do very bad thing!
#ifdef _DEBUG
					Com_Printf( "WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n" );
#endif
					return;
				}

				CG_KillCEntityG2( indexNum );
			}
		}

		return;
	}

	if ( !strcmp( cmd, "kls" ) ) {
		// kill looping sounds
		int indexNum = 0, argNum = trap->Cmd_Argc();
		centity_t *clent = NULL, *trackerent = NULL;

		if ( argNum < 1 ) {
			assert( 0 );
			return;
		}

		indexNum = atoi( CG_Argv( 1 ) );

		if ( indexNum != -1 )
			clent = &cg_entities[indexNum];

		if ( argNum >= 2 ) {
			indexNum = atoi( CG_Argv( 2 ) );

			if ( indexNum != -1 )
				trackerent = &cg_entities[indexNum];
		}

		if ( clent )
			CG_S_StopLoopingSound( clent->currentState.number, -1 );
		if ( trackerent )
			CG_S_StopLoopingSound( trackerent->currentState.number, -1 );

		return;
	}

	// this means param 2 is the body index and we want to copy to bodyqueue on it
	if ( !strcmp( cmd, "ircg" ) )
		IRCG = qtrue;

	if ( !strcmp( cmd, "rcg" ) || IRCG ) {
		//rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably)
		int indexNum = 0, argNum = trap->Cmd_Argc();
		centity_t *clent;

		if ( argNum < 1 ) {
			assert( 0 );
			return;
		}

		indexNum = atoi( CG_Argv( 1 ) );
		if ( indexNum < 0 || indexNum >= MAX_CLIENTS ) {
			assert( 0 );
			return;
		}

		clent = &cg_entities[indexNum];

		// this can happen while connecting as a client
		if ( !clent->ghoul2 )
			return;

#ifdef _DEBUG
		if ( !trap->G2_HaveWeGhoul2Models( clent->ghoul2 ) )
			assert( !"Tried to reset state on a bad instance. Crash is inevitable." );
#endif

		if ( IRCG ) {
			int bodyIndex = 0, weaponIndex = 0, side = 0;
			centity_t *body;

			assert( argNum >= 3 );
			bodyIndex = atoi( CG_Argv( 2 ) );
			weaponIndex = atoi( CG_Argv( 3 ) );
			side = atoi( CG_Argv( 4 ) );

			body = &cg_entities[bodyIndex];
			body->teamPowerType = side ? 1 : 0;

			CG_BodyQueueCopy( body, clent->currentState.number, weaponIndex );
		}

		// reattach any missing limbs
		if ( clent->torsoBolt )
			CG_ReattachLimb( clent );

		// make sure ragdoll state is reset
		if ( clent->isRagging ) {
			clent->isRagging = qfalse;
			trap->G2API_SetRagDoll( clent->ghoul2, NULL ); //calling with null parms resets to no ragdoll.
		}

		// clear all the decals as well
		trap->G2API_ClearSkinGore( clent->ghoul2 );

		clent->weapon = 0;
		clent->ghoul2weapon = NULL; //force a weapon reinit

		return;
	}

	if ( !strcmp( cmd, "cp" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		CG_CheckSVStringEdRef( strEd, CG_Argv( 1 ) );
		CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30f, BIGCHAR_WIDTH );
		return;
	}

	if ( !strcmp( cmd, "cps" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		char *x = (char *)CG_Argv( 1 );
		if ( x[0] == '@' )
			x++;
		trap->SE_GetStringTextString( x, strEd, MAX_STRINGED_SV_STRING );
		//Raz: From OJP
		//	CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30f, BIGCHAR_WIDTH );
		CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.20f, BIGCHAR_WIDTH );
		return;
	}

	if ( !strcmp( cmd, "cs" ) ) {
		CG_ConfigStringModified();
		return;
	}

	if ( !strcmp( cmd, "print" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		CG_CheckSVStringEdRef( strEd, CG_Argv( 1 ) );
		CG_LogPrintf( cg.log.console, strEd );
		trap->Print( "%s", strEd );
		return;
	}

	if ( !strcmp( cmd, "chat" ) ) {
		char *msg = JPLua_Event_ChatMessageRecieved( CG_Argv( 1 ) );

		//If a JPLua plugin cancelled it, bail
		if ( !msg )
			return;

		if ( !cg_teamChatsOnly.integer ) {
			char cbName[MAX_CHATBOX_IDENTIFIER_SIZE] = "normal";
			trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND );
			Q_strncpyz( text, msg, MAX_SAY_TEXT );

			if ( CG_ContainsChannelEscapeChar( text ) )
				Q_strncpyz( cbName, CG_RemoveChannelEscapeChar( text ), sizeof(cbName) );

			CG_RemoveChatEscapeChar( text );
			CG_LogPrintf( cg.log.console, va( "%s\n", text ) );
			if ( cg_newChatbox.integer )
				CG_ChatboxAddMessage( text, qfalse, cbName );
			else
				CG_ChatBox_AddString( text );
			trap->Print( "*%s\n", text );
			Q_CleanString( text, STRIP_COLOUR );
			CG_LogPrintf( cg.log.chat, va( "%s\n", text ) );
		}

		return;
	}

	if ( !strcmp( cmd, "tchat" ) ) {
		trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND );
		Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT );
		CG_RemoveChatEscapeChar( text );
		CG_LogPrintf( cg.log.console, va( "%s\n", text ) );
		if ( cg_newChatbox.integer )
			CG_ChatboxAddMessage( text, qfalse, "team" );
		else
			CG_ChatBox_AddString( text );
		trap->Print( "*%s\n", text );
		Q_CleanString( text, STRIP_COLOUR );
		CG_LogPrintf( cg.log.chat, va( "%s\n", text ) );

		return;
	}

	//chat with location, possibly localized.
	if ( !strcmp( cmd, "lchat" ) ) {
		if ( !cg_teamChatsOnly.integer ) {
			char name[MAX_STRING_CHARS], loc[MAX_STRING_CHARS], color[8], message[MAX_STRING_CHARS];

			if ( trap->Cmd_Argc() < 4 )
				return;

			Q_strncpyz( name, CG_Argv( 1 ), sizeof(name) );
			Q_strncpyz( loc, CG_Argv( 2 ), sizeof(loc) );
			Q_strncpyz( color, CG_Argv( 3 ), sizeof(color) );
			Q_strncpyz( message, CG_Argv( 4 ), sizeof(message) );

			if ( loc[0] == '@' )
				trap->SE_GetStringTextString( loc + 1, loc, sizeof(loc) );

			trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND );
			//	Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT );
			Com_sprintf( text, sizeof(text), "%s" S_COLOR_WHITE "<%s> ^%s%s", name, loc, color, message );
			CG_RemoveChatEscapeChar( text );
			//Raz: Siege chat now uses the fancy new chatbox
			if ( cg_newChatbox.integer )
				CG_ChatboxAddMessage( text, qfalse, "normal" );
			else
				CG_ChatBox_AddString( text );
			trap->Print( "*%s\n", text );
			Q_CleanString( text, STRIP_COLOUR );
			CG_LogPrintf( cg.log.chat, va( "%s\n", text ) );
		}
		return;
	}
	if ( !strcmp( cmd, "ltchat" ) ) {
		char name[MAX_STRING_CHARS], loc[MAX_STRING_CHARS], color[8], message[MAX_STRING_CHARS];

		if ( trap->Cmd_Argc() < 4 )
			return;

		Q_strncpyz( name, CG_Argv( 1 ), sizeof(name) );
		Q_strncpyz( loc, CG_Argv( 2 ), sizeof(loc) );
		Q_strncpyz( color, CG_Argv( 3 ), sizeof(color) );
		Q_strncpyz( message, CG_Argv( 4 ), sizeof(message) );

		if ( loc[0] == '@' )
			trap->SE_GetStringTextString( loc + 1, loc, sizeof(loc) );

		trap->S_StartLocalSound( media.sounds.interface.talk, CHAN_LOCAL_SOUND );
		//	Q_strncpyz( text, CG_Argv( 1 ), MAX_SAY_TEXT );
		Com_sprintf( text, sizeof(text), "%s" S_COLOR_WHITE "<%s> ^%s%s", name, loc, color, message );
		CG_RemoveChatEscapeChar( text );
		if ( cg_newChatbox.integer )
			CG_ChatboxAddMessage( text, qfalse, "team" );
		else
			CG_ChatBox_AddString( text );
		trap->Print( "*%s\n", text );
		Q_CleanString( text, STRIP_COLOUR );
		CG_LogPrintf( cg.log.chat, va( "%s\n", text ) );

		return;
	}

	if ( !strcmp( cmd, "scores" ) ) {
		CG_ParseScores();
		return;
	}

	if ( !strcmp( cmd, "tinfo" ) ) {
		CG_ParseTeamInfo();
		return;
	}

	if ( !strcmp( cmd, "map_restart" ) ) {
		CG_MapRestart();
		return;
	}

	if ( !Q_stricmp( cmd, "remapShader" ) ) {
		if ( trap->Cmd_Argc() == 4 ) {
			char shader1[MAX_QPATH], shader2[MAX_QPATH];
			Q_strncpyz( shader1, CG_Argv( 1 ), sizeof(shader1) );
			Q_strncpyz( shader2, CG_Argv( 2 ), sizeof(shader2) );
			trap->R_RemapShader( shader1, shader2, CG_Argv( 3 ) );
			return;
		}
		return;
	}

	// loaddeferred can be both a servercmd and a consolecmd
	if ( !strcmp( cmd, "loaddefered" ) ) {	// FIXME: spelled wrong, but not changing for demo
		CG_LoadDeferredPlayers();
		return;
	}

	// clientLevelShot is sent before taking a special screenshot for the menu system during development
	if ( !strcmp( cmd, "clientLevelShot" ) ) {
		cg.levelShot = qtrue;
		return;
	}

	trap->Print( "Unknown client game command: %s\n", cmd );
}
Example #5
0
static void CG_ServerCommand( void ) {
	const char	*cmd;
	char		text[MAX_SAY_TEXT];
	qboolean	IRCG = qfalse;

	cmd = CG_Argv(0);

	if ( !cmd[0] ) {
		// server claimed the command
		return;
	}

#if 0
	// never seems to get used -Ste
	if ( !strcmp( cmd, "spd" ) ) 
	{
		const char *ID;
		int holdInt,count,i;
		char string[1204];

		count = trap_Argc();

		ID =  CG_Argv(1);
		holdInt = atoi(ID);

		memset( &string, 0, sizeof( string ) );

		Com_sprintf( string,sizeof(string)," \"%s\"", (const char *) CG_Argv(2));

		for (i=3;i<count;i++)
		{
			Com_sprintf( string,sizeof(string)," %s \"%s\"", string, (const char *) CG_Argv(i));
		}

		trap_SP_Print(holdInt, (byte *)string);
		return;
	}
#endif

	if (!strcmp(cmd, "sxd"))
	{ //siege extended data, contains extra info certain classes may want to know about other clients
        CG_ParseSiegeExtendedData();
		return;
	}

	if (!strcmp(cmd, "sb"))
	{ //siege briefing display
		CG_SiegeBriefingDisplay(atoi(CG_Argv(1)), 0);
		return;
	}

	if ( !strcmp( cmd, "scl" ) )
	{
		//if (!( trap_Key_GetCatcher() & KEYCATCH_UI ))
		//Well, I want it to come up even if the briefing display is up.
		{
			trap_OpenUIMenu(UIMENU_CLASSSEL); //UIMENU_CLASSSEL
		}
		return;
	}

	if ( !strcmp( cmd, "spc" ) )
	{
		trap_Cvar_Set("ui_myteam", "3");
		trap_OpenUIMenu(UIMENU_PLAYERCONFIG); //UIMENU_CLASSSEL
		return;
	}

	if ( !strcmp( cmd, "nfr" ) )
	{ //"nfr" == "new force rank" (want a short string)
		int doMenu = 0;
		int setTeam = 0;
		int newRank = 0;

		if (trap_Argc() < 3)
		{
#ifdef _DEBUG
			Com_Printf("WARNING: Invalid newForceRank string\n");
#endif
			return;
		}

		newRank = atoi(CG_Argv(1));
		doMenu = atoi(CG_Argv(2));
		setTeam = atoi(CG_Argv(3));

		trap_Cvar_Set("ui_rankChange", va("%i", newRank));

		trap_Cvar_Set("ui_myteam", va("%i", setTeam));

		if (!( trap_Key_GetCatcher() & KEYCATCH_UI ) && doMenu)
		{
			trap_OpenUIMenu(UIMENU_PLAYERCONFIG);
		}

		return;
	}

	if ( !strcmp( cmd, "kg2" ) )
	{ //Kill a ghoul2 instance in this slot.
	  //If it has been occupied since this message was sent somehow, the worst that can (should) happen
	  //is the instance will have to reinit with its current info.
		int indexNum = 0;
		int argNum = trap_Argc();
		int i = 1;
		
		if (argNum < 1)
		{
			return;
		}

		while (i < argNum)
		{
			indexNum = atoi(CG_Argv(i));

			if (cg_entities[indexNum].ghoul2 && trap_G2_HaveWeGhoul2Models(cg_entities[indexNum].ghoul2))
			{
				if (indexNum < MAX_CLIENTS)
				{ //You try to do very bad thing!
#ifdef _DEBUG
					Com_Printf("WARNING: Tried to kill a client ghoul2 instance with a kg2 command!\n");
#endif
					return;
				}

				CG_KillCEntityG2(indexNum);
			}

			i++;
		}
		
		return;
	}

	if (!strcmp(cmd, "kls"))
	{ //kill looping sounds
		int indexNum = 0;
		int argNum = trap_Argc();
		centity_t *clent = NULL;
		centity_t *trackerent = NULL;
		
		if (argNum < 1)
		{
			assert(0);
			return;
		}

		indexNum = atoi(CG_Argv(1));

		if (indexNum != -1)
		{
			clent = &cg_entities[indexNum];
		}

		if (argNum >= 2)
		{
			indexNum = atoi(CG_Argv(2));

			if (indexNum != -1)
			{
				trackerent = &cg_entities[indexNum];
			}
		}

		if (clent)
		{
			CG_S_StopLoopingSound(clent->currentState.number, -1);
		}
		if (trackerent)
		{
			CG_S_StopLoopingSound(trackerent->currentState.number, -1);
		}

		return;
	}

	if (!strcmp(cmd, "ircg"))
	{ //this means param 2 is the body index and we want to copy to bodyqueue on it
		IRCG = qtrue;
	}

	if (!strcmp(cmd, "rcg") || IRCG)
	{ //rcg - Restore Client Ghoul (make sure limbs are reattached and ragdoll state is reset - this must be done reliably)
		int indexNum = 0;
		int argNum = trap_Argc();
		centity_t *clent;
		
		if (argNum < 1)
		{
			assert(0);
			return;
		}

		indexNum = atoi(CG_Argv(1));
		if (indexNum < 0 || indexNum >= MAX_CLIENTS)
		{
			assert(0);
			return;
		}

		clent = &cg_entities[indexNum];

		//assert(clent->ghoul2);
		if (!clent->ghoul2)
		{ //this can happen while connecting as a client
			return;
		}

#ifdef _DEBUG
		if (!trap_G2_HaveWeGhoul2Models(clent->ghoul2))
		{
			assert(!"Tried to reset state on a bad instance. Crash is inevitable.");
		}
#endif

		if (IRCG)
		{
			int bodyIndex = 0;
			int weaponIndex = 0;
			int side = 0;
			centity_t *body;

			assert(argNum >= 3);
			bodyIndex = atoi(CG_Argv(2));
			weaponIndex = atoi(CG_Argv(3));
			side = atoi(CG_Argv(4));

			body = &cg_entities[bodyIndex];

			if (side)
			{
				body->teamPowerType = qtrue; //light side
			}
			else
			{
				body->teamPowerType = qfalse; //dark side
			}

			CG_BodyQueueCopy(body, clent->currentState.number, weaponIndex);
		}

		//reattach any missing limbs
		if (clent->torsoBolt)
		{
			CG_ReattachLimb(clent);
		}

		//make sure ragdoll state is reset
		if (clent->isRagging)
		{
			clent->isRagging = qfalse;
			trap_G2API_SetRagDoll(clent->ghoul2, NULL); //calling with null parms resets to no ragdoll.
		}
		
		//clear all the decals as well
		trap_G2API_ClearSkinGore(clent->ghoul2);

		clent->weapon = 0;
		clent->ghoul2weapon = NULL; //force a weapon reinit

		return;
	}

	if ( !strcmp( cmd, "cp" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		CG_CheckSVStringEdRef(strEd, CG_Argv(1));
		CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.30, BIGCHAR_WIDTH );
		return;
	}

	if ( !strcmp( cmd, "cps" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		char *x = (char *)CG_Argv(1);
		if (x[0] == '@')
		{
			x++;
		}
		trap_SP_GetStringTextString(x, strEd, MAX_STRINGED_SV_STRING);
		CG_CenterPrint( strEd, SCREEN_HEIGHT * 0.20, BIGCHAR_WIDTH );
		return;
	}

	if ( !strcmp( cmd, "cs" ) ) {
		CG_ConfigStringModified();
		return;
	}

	if ( !strcmp( cmd, "print" ) ) {
		char strEd[MAX_STRINGED_SV_STRING];
		CG_CheckSVStringEdRef(strEd, CG_Argv(1));
		CG_Printf( "%s", strEd );
		return;
	}

	if ( !strcmp( cmd, "chat" ) ) {
		if ( !cg_teamChatsOnly.integer ) {
			trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
			Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT );
			CG_RemoveChatEscapeChar( text );
			CG_ChatBox_AddString(text);
			CG_Printf( "*%s\n", text );
		}
		return;
	}

	if ( !strcmp( cmd, "tchat" ) ) {
		trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
		Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT );
		CG_RemoveChatEscapeChar( text );
		CG_ChatBox_AddString(text);
		CG_Printf( "*%s\n", text );

		return;
	}

	//chat with location, possibly localized.
	if ( !strcmp( cmd, "lchat" ) ) {
		if ( !cg_teamChatsOnly.integer ) {
			char name[MAX_STRING_CHARS];
			char loc[MAX_STRING_CHARS];
			char color[8];
			char message[MAX_STRING_CHARS];

			if (trap_Argc() < 4)
			{
				return;
			}

			strcpy(name, CG_Argv(1));
			strcpy(loc, CG_Argv(2));
			strcpy(color, CG_Argv(3));
			strcpy(message, CG_Argv(4));

			if (loc[0] == '@')
			{ //get localized text
				trap_SP_GetStringTextString(loc+1, loc, MAX_STRING_CHARS);
			}

			trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
			//Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT );
			Com_sprintf(text, MAX_SAY_TEXT, "%s<%s>^%s%s", name, loc, color, message);
			CG_RemoveChatEscapeChar( text );
			CG_ChatBox_AddString(text);
			CG_Printf( "*%s\n", text );
		}
		return;
	}
	if ( !strcmp( cmd, "ltchat" ) ) {
		char name[MAX_STRING_CHARS];
		char loc[MAX_STRING_CHARS];
		char color[8];
		char message[MAX_STRING_CHARS];

		if (trap_Argc() < 4)
		{
			return;
		}

		strcpy(name, CG_Argv(1));
		strcpy(loc, CG_Argv(2));
		strcpy(color, CG_Argv(3));
		strcpy(message, CG_Argv(4));

		if (loc[0] == '@')
		{ //get localized text
			trap_SP_GetStringTextString(loc+1, loc, MAX_STRING_CHARS);
		}

		trap_S_StartLocalSound( cgs.media.talkSound, CHAN_LOCAL_SOUND );
		//Q_strncpyz( text, CG_Argv(1), MAX_SAY_TEXT );
		Com_sprintf(text, MAX_SAY_TEXT, "%s<%s> ^%s%s", name, loc, color, message);
		CG_RemoveChatEscapeChar( text );
		CG_ChatBox_AddString(text);
		CG_Printf( "*%s\n", text );

		return;
	}

	if ( !strcmp( cmd, "scores" ) ) {
		CG_ParseScores();
		return;
	}

	if ( !strcmp( cmd, "tinfo" ) ) {
		CG_ParseTeamInfo();
		return;
	}

	if ( !strcmp( cmd, "map_restart" ) ) {
		CG_MapRestart();
		return;
	}

  if ( Q_stricmp (cmd, "remapShader") == 0 ) {
		if (trap_Argc() == 4) {
			trap_R_RemapShader(CG_Argv(1), CG_Argv(2), CG_Argv(3));
		}
	}

	// loaddeferred can be both a servercmd and a consolecmd
	if ( !strcmp( cmd, "loaddefered" ) ) {	// FIXME: spelled wrong, but not changing for demo
		CG_LoadDeferredPlayers();
		return;
	}

	// clientLevelShot is sent before taking a special screenshot for
	// the menu system during development
	if ( !strcmp( cmd, "clientLevelShot" ) ) {
		cg.levelShot = qtrue;
		return;
	}

	CG_Printf( "Unknown client game command: %s\n", cmd );
}