Example #1
0
/* <25d5a> ../cstrike/dlls/buttons.cpp:236 */
void CMultiSource::Register()
{
	edict_t *pentTarget = NULL;

	m_iTotal = 0;
	Q_memset(m_rgEntities, 0, MS_MAX_TARGETS * sizeof(EHANDLE));

	SetThink(&CMultiSource::SUB_DoNothing);

	// search for all entities which target this multisource (pev->targetname)
	pentTarget = FIND_ENTITY_BY_STRING(NULL, "target", STRING(pev->targetname));

	while (!FNullEnt(pentTarget) && m_iTotal < MS_MAX_TARGETS)
	{
		CBaseEntity *pTarget = CBaseEntity::Instance(pentTarget);

		if (pTarget != NULL)
		{
			m_rgEntities[m_iTotal++] = pTarget;
		}

		pentTarget = FIND_ENTITY_BY_STRING(pentTarget, "target", STRING(pev->targetname));
	}

	pentTarget = FIND_ENTITY_BY_STRING(NULL, "classname", "multi_manager");

	while (!FNullEnt(pentTarget) && m_iTotal < MS_MAX_TARGETS)
	{
		CBaseEntity *pTarget = CBaseEntity::Instance(pentTarget);
		if (pTarget != NULL && pTarget->HasTarget(pev->targetname))
		{
			m_rgEntities[m_iTotal++] = pTarget;
		}

		pentTarget = FIND_ENTITY_BY_STRING(pentTarget, "classname", "multi_manager");
	}

	pev->spawnflags &= ~SF_MULTI_INIT;
}
Example #2
0
void EXT_FUNC RemoveExtDll_api(void *hModule)
{
	if (!hModule) {
		return;
	}

	for (auto i = 0; i < g_iextdllMac; i++)
	{
		if (g_rgextdll[i].lDLLHandle == hModule)
		{
			g_iextdllMac--;
			if (g_iextdllMac != i)
			{
				Q_memmove(&g_rgextdll[i], &g_rgextdll[i + 1], (g_iextdllMac - i) * sizeof(g_rgextdll[0]));
				i = g_iextdllMac;
			}

			Q_memset(&g_rgextdll[i], 0, sizeof(g_rgextdll[0]));
			break;
		}
	}
}
CBugReporter::CBugReporter()
{
	Q_memset( &m_cserIP, 0, sizeof( m_cserIP ) );
	m_pBug = NULL;

	m_Severity.AddToTail( m_BugStrings.AddString( "Zero" ) );
	m_Severity.AddToTail( m_BugStrings.AddString( "Low" ) );
	m_Severity.AddToTail( m_BugStrings.AddString( "Medium" ) );
	m_Severity.AddToTail( m_BugStrings.AddString( "High" ) );
	m_Severity.AddToTail( m_BugStrings.AddString( "Showstopper" ) );

	
	m_ReportType.AddToTail( m_BugStrings.AddString( "<<Choose Item>>" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "Video / Display Problems" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "Network / Connectivity Problems" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "Download / Installation Problems" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "In-game Crash" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "Game play / Strategy Problems" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "Steam Problems" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "Unlisted Bug" ) );
	m_ReportType.AddToTail( m_BugStrings.AddString( "Feature Request / Suggestion" ) );
}
//-----------------------------------------------------------------------------
// Run this Bot's AI for one frame.
//-----------------------------------------------------------------------------
void Bot_Think( CPluginBot *pBot )
{
	CBotCmd cmd;
	Q_memset( &cmd, 0, sizeof( cmd ) );
	
	// Finally, override all this stuff if the bot is being forced to mimic a player.
	if ( !Bot_RunMimicCommand( cmd ) )
	{
		cmd.sidemove = pBot->m_flSideMove;

		if ( !pBot->m_PlayerInfo->IsDead() )
		{
			Bot_SetForwardMovement( pBot, cmd );

			// Only turn if I haven't been hurt
			if ( !pBot->m_BotInterface->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_PlayerInfo->GetHealth() == 100 )
			{
				Bot_UpdateDirection( pBot );
				Bot_UpdateStrafing( pBot, cmd );
			}

			// Handle console settings.
			Bot_ForceFireWeapon( pBot, cmd );
			Bot_HandleSendCmd( pBot );
		}
		else
		{
			Bot_HandleRespawn( pBot, cmd );
		}

		Bot_FlipOut( pBot, cmd );

		cmd.viewangles = pBot->m_BotInterface->GetLocalAngles();
		cmd.upmove = 0;
		cmd.impulse = 0;
	}

	pBot->m_BotInterface->RunPlayerMove( &cmd );
}
Example #5
0
/*
================
CL_BaseMove

Send the intended movement message to the server
================
*/
void CL_BaseMove (usercmd_t *cmd)
{
	if (cls.signon != SIGNONS)
		return;

	CL_AdjustAngles ();

	Q_memset (cmd, 0, sizeof(*cmd));

	if (in_strafe.state & 1)
	{
		cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
		cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
	}

	cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
	cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);

	cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
	cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);

	if (! (in_klook.state & 1) )
	{
		cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
		cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
	}

//
// adjust for speed key
//
	if (cl_forwardspeed.value > 200 && cl_movespeedkey.value)
		cmd->forwardmove /= cl_movespeedkey.value;
	if ((cl_forwardspeed.value > 200) ^ (in_speed.state & 1))
	{
		cmd->forwardmove *= cl_movespeedkey.value;
		cmd->sidemove *= cl_movespeedkey.value;
		cmd->upmove *= cl_movespeedkey.value;
	}
}
void CTilegenAction_PlaceComponent::OnBeginGeneration( CLayoutSystem *pLayoutSystem )
{
	int nNumOptionalRooms = pLayoutSystem->GetRandomInt( m_nMinOptionalRooms, m_nMaxOptionalRooms );
	nNumOptionalRooms = MIN( nNumOptionalRooms, m_OptionalRooms.Count() );
	nNumOptionalRooms = MAX( nNumOptionalRooms, 0 );

	m_RoomsToPlace.RemoveAll();
	for ( int i = 0; i < m_MandatoryRooms.Count(); ++ i )
	{
		AddRoomPlacementInstance( pLayoutSystem, &m_MandatoryRooms[i] );
	}

	bool isRoomChosen[m_nMaxTotalOptionalRooms];
	Q_memset( isRoomChosen, 0, sizeof( isRoomChosen ) );

	// Simplest but probably not the most efficient way to randomly choose N rooms from a list of X rooms.
	int nNumOptionalRoomsChosen = 0;
	Msg("Processing random rooms, need to add [%d] rooms.  Have [%d] options\n",nNumOptionalRooms, m_OptionalRooms.Count());
	Log_Msg(LOG_TilegenLayoutSystem, "Processing random rooms, need to add [%d] rooms.  Have [%d] options\n",nNumOptionalRooms, m_OptionalRooms.Count());
		
	while ( nNumOptionalRoomsChosen < nNumOptionalRooms )
	{

		//BUG: int nRoom = pLayoutSystem->GetRandomInt( 0, nNumOptionalRooms - 1 );
		//Should choose from all available rooms.
		int nRoom = pLayoutSystem->GetRandomInt( 0, m_OptionalRooms.Count() -1);
			
		if ( !isRoomChosen[nRoom] )
		{
			
			isRoomChosen[nRoom] = true;
			AddRoomPlacementInstance( pLayoutSystem, &m_OptionalRooms[nRoom] );
			++ nNumOptionalRoomsChosen;
			Msg("Room [%d] is id [%d]\n", nNumOptionalRoomsChosen, nRoom);
			Log_Msg(LOG_TilegenLayoutSystem,  "Room [%d] is id [%d]\n", nNumOptionalRoomsChosen, nRoom);			
		}
	}
	Msg("Done processing random rooms.\n");
}
Example #7
0
/*
================
R_AllocateMirrorTexture

Allocate the screen texture and make copy
================
*/
int R_AllocateMirrorTexture( void )
{
	rgbdata_t	r_screen;
	int	i, texture;
	char	txName[16];

	i = tr.num_mirrors_used;
	if( i >= MAX_MIRRORS )
	{
		MsgDev( D_ERROR, "R_AllocateMirrorTexture: mirror textures limit exceeded!\n" );
		return 0;	// disable
	}

	texture = tr.mirrorTextures[i];
	tr.num_mirrors_used++;

	if( !texture )
	{
		// not initialized ?
		Q_memset( &r_screen, 0, sizeof( r_screen ));
		Q_snprintf( txName, sizeof( txName ), "*screen%i", i );

		r_screen.width = RI.viewport[2];
		r_screen.height = RI.viewport[3];
		r_screen.type = PF_RGBA_32;
		r_screen.size = r_screen.width * r_screen.height * 4;
		r_screen.flags = IMAGE_HAS_COLOR;
		r_screen.buffer = NULL; // create empty texture for now
		tr.mirrorTextures[i] = GL_LoadTextureInternal( txName, &r_screen, TF_IMAGE, false );
		GL_SetTextureType( tr.mirrorTextures[i], TEX_SCREENCOPY );
		texture = tr.mirrorTextures[i];
	}

	GL_Bind( GL_TEXTURE0, texture );
	pglCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3], 0 );

	return texture;
}
Example #8
0
void Netchan_Setup(netsrc_t socketnumber, netchan_t *chan, netadr_t adr, int player_slot, void *connection_status, qboolean(*pfnNetchan_Blocksize)(void *))
{
	Netchan_Clear(chan);

	Q_memset(chan, 0, sizeof(netchan_t));

	chan->player_slot = player_slot + 1;
	chan->sock = socketnumber;
	chan->remote_address = adr;
	chan->last_received = (float)realtime;
	chan->connect_time = (float)realtime;

	chan->message.buffername = "netchan->message";
#ifdef REHLDS_FIXES
	if (player_slot != -1)
	{
		chan->message.data = g_GameClients[player_slot]->GetExtendedMessageBuffer();
		chan->message.maxsize = NET_MAX_PAYLOAD;
	}
	else
#endif
	{
		chan->message.data = chan->message_buf;
		chan->message.maxsize = sizeof(chan->message_buf);
	}
#ifdef REHLDS_FIXES
	chan->message.cursize = 0;
#endif // REHLDS_FIXES
	chan->message.flags = SIZEBUF_ALLOW_OVERFLOW;

	chan->rate = DEFAULT_RATE;

	// Prevent the first message from getting dropped after connection is set up.
	chan->outgoing_sequence = 1;

	chan->connection_status = connection_status;
	chan->pfnNetchan_Blocksize = pfnNetchan_Blocksize;
}
Example #9
0
void CL_WriteUsercmd( sizebuf_t *msg, int from, int to )
{
	usercmd_t	nullcmd;
	usercmd_t	*f, *t;

	ASSERT( from == -1 || ( from >= 0 && from < MULTIPLAYER_BACKUP ));
	ASSERT( to >= 0 && to < MULTIPLAYER_BACKUP );

	if( from == -1 )
	{
		Q_memset( &nullcmd, 0, sizeof( nullcmd ));
		f = &nullcmd;
	}
	else
	{
		f = &cl.cmds[from];
	}

	t = &cl.cmds[to];

	// write it into the buffer
	MSG_WriteDeltaUsercmd( msg, f, t );
}
Example #10
0
/*
==================
CL_ParseBaseline
==================
*/
void CL_ParseBaseline( sizebuf_t *msg )
{
	int		newnum;
	float		timebase;
	cl_entity_t	*ent;

	Delta_InitClient ();	// finalize client delta's

	newnum = BF_ReadWord( msg );

	if( newnum < 0 ) Host_Error( "CL_SpawnEdict: invalid number %i\n", newnum );
	if( newnum >= clgame.maxEntities ) Host_Error( "CL_AllocEdict: no free edicts\n" );

	ent = CL_EDICT_NUM( newnum );
	Q_memset( &ent->prevstate, 0, sizeof( ent->prevstate ));
	ent->index = newnum;

	if( cls.state == ca_active )
		timebase = cl.mtime[0];
	else timebase = 1.0f; // sv.state == ss_loading

	MSG_ReadDeltaEntity( msg, &ent->prevstate, &ent->baseline, newnum, CL_IsPlayerIndex( newnum ), timebase );
}
Example #11
0
void netadr_t::ToSockadr (struct sockaddr * s) const
{
	Q_memset ( s, 0, sizeof(struct sockaddr));

	if (type == NA_BROADCAST)
	{
		((struct sockaddr_in*)s)->sin_family = AF_INET;
		((struct sockaddr_in*)s)->sin_port = port;
		((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST;
	}
	else if (type == NA_IP)
	{
		((struct sockaddr_in*)s)->sin_family = AF_INET;
		((struct sockaddr_in*)s)->sin_addr.s_addr = *(int *)&ip;
		((struct sockaddr_in*)s)->sin_port = port;
	}
	else if (type == NA_LOOPBACK )
	{
		((struct sockaddr_in*)s)->sin_family = AF_INET;
		((struct sockaddr_in*)s)->sin_port = port;
		((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK ;
	}
}
Example #12
0
void Sys_CheckOSVersion(void)
{
	OSVERSIONINFO verInfo;

	Q_memset(&verInfo, 0, sizeof(verInfo));
	verInfo.dwOSVersionInfoSize = sizeof(verInfo);
	if (!GetVersionEx(&verInfo))
		Sys_Error("%s: Couldn't get OS info", __func__);

	g_WinNTOrHigher = verInfo.dwMajorVersion >= 4;
	if (verInfo.dwPlatformId == 1 && verInfo.dwMajorVersion == 4)
	{
		if (verInfo.dwMinorVersion)
		{
			if (verInfo.dwMinorVersion < 90)
				g_bIsWin98 = TRUE;
		}
		else
		{
			g_bIsWin95 = TRUE;
		}
	}
}
Example #13
0
void Q_atov( float *vec, const char *str, size_t siz )
{
    string	buffer;
    char	*pstr, *pfront;
    int	j;

    Q_strncpy( buffer, str, sizeof( buffer ));
    Q_memset( vec, 0, sizeof( vec_t ) * siz );
    pstr = pfront = buffer;

    for( j = 0; j < siz; j++ )
    {
        vec[j] = Q_atof( pfront );

        // valid separator is space
        while( *pstr && *pstr != ' ' )
            pstr++;

        if( !*pstr ) break;
        pstr++;
        pfront = pstr;
    }
}
Example #14
0
/*
=================
CL_FlushEntityPacket
=================
*/
void CL_FlushEntityPacket( sizebuf_t *msg )
{
	int		newnum;
	entity_state_t	from, to;

	MsgDev( D_INFO, "FlushEntityPacket()\n" );
	Q_memset( &from, 0, sizeof( from ));

	cl.frames[cl.parsecountmod].valid = false;
	cl.validsequence = 0; // can't render a frame

	// read it all, but ignore it
	while( 1 )
	{
		newnum = BF_ReadWord( msg );
		if( !newnum ) break; // done

		if( BF_CheckOverflow( msg ))
			Host_Error( "CL_FlushEntityPacket: read overflow\n" );

		MSG_ReadDeltaEntity( msg, &from, &to, newnum, CL_IsPlayerIndex( newnum ), cl.mtime[0] );
	}
}
Example #15
0
NOXREF void Sys_CheckOSVersion(void)
{
	struct _OSVERSIONINFOA verInfo;

	Q_memset(&verInfo, 0, sizeof(verInfo));
	verInfo.dwOSVersionInfoSize = sizeof(verInfo);
	if (!GetVersionExA(&verInfo))
		Sys_Error("Couldn't get OS info");

	g_WinNTOrHigher = verInfo.dwMajorVersion >= 4;
	if (verInfo.dwPlatformId == 1 && verInfo.dwMajorVersion == 4)
	{
		if (verInfo.dwMinorVersion)
		{
			if (verInfo.dwMinorVersion < 90)
				g_bIsWin98 = 1;
		}
		else
		{
			g_bIsWin95 = 1;
		}
	}
}
Example #16
0
/*
==============
GL_BackendEndFrame
==============
*/
void GL_BackendEndFrame( void )
{
	// go into 2D mode (in case we draw PlayerSetup between two 2d calls)
	if( !RI.drawWorld ) R_Set2DMode( true );

	if( r_speeds->integer <= 0 || !RI.drawWorld )
		return;

	switch( r_speeds->integer )
	{
	case 1:
		Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i wpoly, %3i bpoly\n%3i epoly, %3i spoly",
		r_stats.c_world_polys, r_stats.c_brush_polys, r_stats.c_studio_polys, r_stats.c_sprite_polys );
		break;		
	case 2:
		Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "visible leafs:\n%3i leafs\ncurrent leaf %3li",
		r_stats.c_world_leafs, r_viewleaf - cl.worldmodel->leafs );
		break;
	case 3:
		Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i studio models drawn\n%3i sprites drawn",
		r_stats.c_studio_models_drawn, r_stats.c_sprite_models_drawn );
		break;
	case 4:
		Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i static entities\n%3i normal entities",
		r_numStatics, r_numEntities - r_numStatics );
		break;
	case 5:
		Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i tempents\n%3i viewbeams\n%3i particles",
		r_stats.c_active_tents_count, r_stats.c_view_beams_count, r_stats.c_particle_count );
		break;
	case 6:
		Q_snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%3i mirrors\n", r_stats.c_mirror_passes );
		break;
	}

	Q_memset( &r_stats, 0, sizeof( r_stats ));
}
Example #17
0
/*
=================
Mod_LoadSpriteFrame
=================
*/
void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
{
    dspriteframe_t		*pinframe;
    mspriteframe_t		*pspriteframe;
    int					i, width, height, size, origin[2];
    unsigned short		*ppixout;
    byte				*ppixin;
    char				name[64];

    pinframe = (dspriteframe_t *)pin;

    width = LittleLong (pinframe->width);
    height = LittleLong (pinframe->height);
    size = width * height;

    pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);

    Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));

    *ppframe = pspriteframe;

    pspriteframe->width = width;
    pspriteframe->height = height;
    origin[0] = LittleLong (pinframe->origin[0]);
    origin[1] = LittleLong (pinframe->origin[1]);

    pspriteframe->up = origin[1];
    pspriteframe->down = origin[1] - height;
    pspriteframe->left = origin[0];
    pspriteframe->right = width + origin[0];

    sprintf (name, "%s_%i", loadmodel->name, framenum);
    pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);

    return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
}
Example #18
0
/*
=================
S_StartBackgroundTrack
=================
*/
void S_StartBackgroundTrack( const char *introTrack, const char *mainTrack, int position )
{
	S_StopBackgroundTrack();

	if( !dma.initialized ) return;

	// check for special symbols
	if( introTrack && *introTrack == '*' )
		introTrack = NULL;

	if( mainTrack && *mainTrack == '*' )
		mainTrack = NULL;

	if(( !introTrack || !*introTrack ) && ( !mainTrack || !*mainTrack ))
		return;

	if( !introTrack ) introTrack = mainTrack;
	if( !*introTrack ) return;

	if( !mainTrack || !*mainTrack ) s_bgTrack.loopName[0] = '\0';
	else Q_strncpy( s_bgTrack.loopName, mainTrack, sizeof( s_bgTrack.loopName ));

	// open stream
	s_bgTrack.stream = FS_OpenStream( va( "media/%s", introTrack ));
	Q_strncpy( s_bgTrack.current, introTrack, sizeof( s_bgTrack.current ));
	Q_memset( &musicfade, 0, sizeof( musicfade )); // clear any soundfade
	s_bgTrack.source = cls.key_dest;

	if( position != 0 )
	{
		// restore message, update song position
		FS_SetStreamPos( s_bgTrack.stream, position );
	}

	S_CheckLerpingState();
}
Example #19
0
void VID_StartupGamma( void )
{
	// Device supports gamma anyway, but cannot do anything with it.
	fs_offset_t	gamma_size;
	byte	*savedGamma;
	size_t	gammaTypeSize = sizeof(glState.stateRamp);

	// init gamma ramp
	Q_memset( glState.stateRamp, 0, gammaTypeSize);

#if defined(XASH_SDL)
	glConfig.deviceSupportsGamma = !SDL_GetWindowGammaRamp( host.hWnd, NULL, NULL, NULL);
#endif

	if( !glConfig.deviceSupportsGamma )
	{
		// force to set cvar
		Cvar_FullSet( "gl_ignorehwgamma", "1", CVAR_GLCONFIG );
		MsgDev( D_ERROR, "VID_StartupGamma: hardware gamma unsupported\n");
	}

	if( gl_ignorehwgamma->integer )
	{
		glConfig.deviceSupportsGamma = false;	// even if supported!
		BuildGammaTable( vid_gamma->value, vid_texgamma->value );
		MsgDev( D_NOTE, "VID_StartupGamma: software gamma initialized\n" );
		return;
	}

	// share this extension so engine can grab them
	GL_SetExtension( GL_HARDWARE_GAMMA_CONTROL, glConfig.deviceSupportsGamma );

	savedGamma = FS_LoadFile( "gamma.dat", &gamma_size, false );

	if( !savedGamma || gamma_size != (fs_offset_t)gammaTypeSize)
	{
		// saved gamma not found or corrupted file
		FS_WriteFile( "gamma.dat", glState.stateRamp, gammaTypeSize);
		MsgDev( D_NOTE, "VID_StartupGamma: gamma.dat initialized\n" );
		if( savedGamma ) Mem_Free( savedGamma );
	}
	else
	{
		GL_BuildGammaTable();

		// validate base gamma
		if( !Q_memcmp( savedGamma, glState.stateRamp, gammaTypeSize))
		{
			// all ok, previous gamma is valid
			MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - ok\n" );
		}
		else if( !Q_memcmp( glState.gammaRamp, glState.stateRamp, gammaTypeSize))
		{
			// screen gamma is equal to render gamma (probably previous instance crashed)
			// run additional check to make sure for it
			if( Q_memcmp( savedGamma, glState.stateRamp, gammaTypeSize))
			{
				// yes, current gamma it's totally wrong, restore it from gamma.dat
				MsgDev( D_NOTE, "VID_StartupGamma: restore original gamma after crash\n" );
				Q_memcpy( glState.stateRamp, savedGamma, gammaTypeSize);
			}
			else
			{
				// oops, savedGamma == glState.stateRamp == glState.gammaRamp
				// probably r_gamma set as default
				MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - disabled\n" ); 
			}
		}
		else if( !Q_memcmp( glState.gammaRamp, savedGamma, gammaTypeSize))
		{
			// saved gamma is equal render gamma, probably gamma.dat wroted after crash
			// run additional check to make sure it
			if( Q_memcmp( savedGamma, glState.stateRamp, gammaTypeSize))
			{
				// yes, saved gamma it's totally wrong, get origianl gamma from screen
				MsgDev( D_NOTE, "VID_StartupGamma: merge gamma.dat after crash\n" );
				FS_WriteFile( "gamma.dat", glState.stateRamp, gammaTypeSize);
			}
			else
			{
				// oops, savedGamma == glState.stateRamp == glState.gammaRamp
				// probably r_gamma set as default
				MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - disabled\n" ); 
			}
		}
		else
		{
			// current gamma unset by other application, so we can restore it here
			MsgDev( D_NOTE, "VID_StartupGamma: restore original gamma after crash\n" );
			Q_memcpy( glState.stateRamp, savedGamma, gammaTypeSize);
		}

		Mem_Free( savedGamma );
	}

	vid_gamma->modified = true;
}
Example #20
0
/*
============
Cbuf_Clear
============
*/
void Cbuf_Clear( void )
{
	Q_memset( cmd_text.data, 0, sizeof( cmd_text_buf ));
	cmd_text.cursize = 0;
}
Example #21
0
static void _reset( )
{
	Q_memset( &strobe, 0, sizeof( strobe ) );
	strobe.frameState  = ( PHASE_POSITIVE | FRAME_RENDER );
	strobe.initialTime = Sys_DoubleTime( );
}
Example #22
0
void R_ClearDecals( void )
{
	Q_memset( gDecalPool, 0, sizeof( gDecalPool ));
	gDecalCount = 0;
}
Example #23
0
/* 
============== 
WritePCXfile 
============== 
*/ 
void WritePCXfile (char *filename, byte *data, int width, int height,
	int rowbytes, byte *palette, qboolean upload) 
{
	int		i, j, length;
	pcx_t	*pcx;
	byte		*pack;
	  
	pcx = Hunk_TempAlloc (width*height*2+1000);
	if (pcx == NULL)
	{
		Con_Printf("SCR_ScreenShot_f: not enough memory\n");
		return;
	} 
 
	pcx->manufacturer = 0x0a;	// PCX id
	pcx->version = 5;			// 256 color
 	pcx->encoding = 1;		// uncompressed
	pcx->bits_per_pixel = 8;		// 256 color
	pcx->xmin = 0;
	pcx->ymin = 0;
	pcx->xmax = LittleShort((short)(width-1));
	pcx->ymax = LittleShort((short)(height-1));
	pcx->hres = LittleShort((short)width);
	pcx->vres = LittleShort((short)height);
	Q_memset (pcx->palette,0,sizeof(pcx->palette));
	pcx->color_planes = 1;		// chunky image
	pcx->bytes_per_line = LittleShort((short)width);
	pcx->palette_type = LittleShort(2);		// not a grey scale
	Q_memset (pcx->filler,0,sizeof(pcx->filler));

// pack the image
	pack = &pcx->data;
	
	for (i=0 ; i<height ; i++)
	{
		for (j=0 ; j<width ; j++)
		{
			if ( (*data & 0xc0) != 0xc0)
				*pack++ = *data++;
			else
			{
				*pack++ = 0xc1;
				*pack++ = *data++;
			}
		}

		data += rowbytes - width;
	}
			
// write the palette
	*pack++ = 0x0c;	// palette ID byte
	for (i=0 ; i<768 ; i++)
		*pack++ = *palette++;
		
// write output file 
	length = (int) (pack - (byte *)pcx);
	if (upload)
		CL_StartUpload((void *)pcx, length);
	else
		COM_WriteFile (filename, pcx, length);
} 
// Load a static copy buffer (g_temppaintbuffer) with the requested number of samples, 
// with the first sample(s) in the buffer always set up as the last sample(s) of the previous load.
// Return a pointer to the head of the copy buffer.
// This ensures that interpolating pitch shifters always have the previous sample to reference.
//		pChannel:				sound's channel data
//		sample_load_request:	number of samples to load from source data
//		pSamplesLoaded:			returns the actual number of samples loaded (should always = sample_load_request)
//		copyBuf:				req'd by GetOutputData, used by some Mixers
// Returns: NULL ptr to data if no samples available, otherwise always fills remainder of copy buffer with
// 0 to pad remainder.
// NOTE: DO NOT MODIFY THIS ROUTINE (KELLYB)
char *CAudioMixerWave::LoadMixBuffer( channel_t *pChannel, int sample_load_request, int *pSamplesLoaded, char copyBuf[AUDIOSOURCE_COPYBUF_SIZE] )
{
	int samples_loaded;
	char *pSample = NULL;
	char *pData = NULL;
	int cCopySamps = 0;

	// save index of last sample loaded (updated in GetOutputData)
	int sample_loaded_index = m_sample_loaded_index;

	// get data from source (copyBuf is expected to be available for use)
	samples_loaded = GetOutputData( (void **)&pData, sample_load_request, copyBuf );
	if ( !samples_loaded && sample_load_request )
	{
		// none available, bail out
		// 360 might not be able to get samples due to latency of loop seek
		// could also be the valid EOF for non-loops (caller keeps polling for data, until no more)
		AssertOnce( IsX360() || !m_pData->Source().IsLooped() );
		*pSamplesLoaded = 0;
		return NULL;
	}

	int samplesize = GetMixSampleSize();
	char *pCopy = (char *)g_temppaintbuffer;

	if ( IsX360() || IsDebug() )
	{	
		// for safety, 360 always validates sample request, due to new xma audio code and possible logic flaws
		// PC can expect number of requested samples to be within tolerances due to exisiting aged code
		// otherwise buffer overruns cause hard to track random crashes
		if ( ( ( sample_load_request + 1 ) * samplesize ) > ( TEMP_COPY_BUFFER_SIZE * sizeof( portable_samplepair_t ) ) )
		{
			// make sure requested samples will fit in temp buffer.
			// if this assert fails, then pitch is too high (ie: > 2.0) or the sample counters have diverged.
			// NOTE: to prevent this, pitch should always be capped in MixDataToDevice (but isn't nor are the sample counters).
			DevWarning( "LoadMixBuffer: sample load request %d exceeds buffer sizes\n", sample_load_request );
			Assert( 0 );
			*pSamplesLoaded = 0;
			return NULL;
		}
	}

	// copy all samples from pData to copy buffer, set 0th sample to saved previous sample - this ensures
	// interpolation pitch shift routines always have a previous sample to reference.

	// copy previous sample(s) to head of copy buffer pCopy
	// In some cases, we'll need the previous 2 samples.  This occurs when
	// Rate < 1.0 - in example below, sample 4.86 - 6.48 requires samples 4-7 (previous samples saved are 4 & 5)

	/*
	Example:
		rate = 0.81, sampleCount = 3 (ie: # of samples to return )

		_____load 3______       ____load 3_______       __load 2__

		0		1		 2		 3		 4		 5		6		7		sample_index     (whole samples)

		^     ^      ^      ^      ^     ^     ^     ^     ^        
		|     |      |      |      |     |     |     |     |   
		0    0.81   1.68   2.43   3.24  4.05  4.86  5.67  6.48          m_fsample_index  (rate*sample)
		_______________    ________________   ________________
						^   ^                  ^ ^        	
						|   |                  | |                                    
	m_sample_loaded_index   |                  | m_sample_loaded_index
							|                  |
		m_fsample_index----   		       ----m_fsample_index

		[return 3 samp]     [return 3 samp]    [return 3 samp]
	*/
	pSample = &(pChannel->sample_prev[0]);

	// determine how many saved samples we need to copy to head of copy buffer (0,1 or 2)
	// so that pitch interpolation will correctly reference samples.
	// NOTE: pitch interpolators always reference the sample before and after the indexed sample.

	// cCopySamps = sample_max_loaded - floor(m_fsample_index);

	if ( sample_loaded_index < 0 || (floor(m_fsample_index) > sample_loaded_index))
	{
		// no samples previously loaded, or
		// next sample index is entirely within the next block of samples to be loaded,
		// so we won't need any samples from the previous block. (can occur when rate > 2.0)
		cCopySamps = 0;
	}
	else if ( m_fsample_index < sample_loaded_index )
	{
		// next sample index is entirely within the previous block of samples loaded,
		// so we'll need the last 2 samples loaded.  (can occur when rate < 1.0)		
		Assert ( ceil(m_fsample_index + 0.00000001) == sample_loaded_index );
		cCopySamps = 2;
	}
	else
	{
		// next sample index is between the next block and the previously loaded block,
		// so we'll need the last sample loaded.  (can occur when 1.0 < rate < 2.0)
		Assert( floor(m_fsample_index) == sample_loaded_index );
		cCopySamps = 1;
	}
	Assert( cCopySamps >= 0 && cCopySamps <= 2 );

	// point to the sample(s) we are to copy
	if ( cCopySamps )
	{
		pSample = cCopySamps == 1 ? pSample + samplesize : pSample;
		Q_memcpy( pCopy, pSample, samplesize * cCopySamps );
		pCopy += samplesize * cCopySamps;
	}

	// don't overflow copy buffer
	Assert ( (PAINTBUFFER_MEM_SIZE * sizeof( portable_samplepair_t )) > ( ( samples_loaded + 1 ) * samplesize ) );
	
	// copy loaded samples from pData into pCopy
	// and update pointer to free space in copy buffer
	if ( ( samples_loaded * samplesize ) != 0 && !pData )
	{
		char const *pWavName = "";
		CSfxTable *source = pChannel->sfx;
		if ( source )
		{
			pWavName = source->getname();
		}
		
		Warning( "CAudioMixerWave::LoadMixBuffer: '%s' samples_loaded * samplesize = %i but pData == NULL\n", pWavName, ( samples_loaded * samplesize ) );
		*pSamplesLoaded = 0;
		return NULL;
	}

	Q_memcpy( pCopy, pData, samples_loaded * samplesize );
	pCopy += samples_loaded * samplesize;
	
	// if we loaded fewer samples than we wanted to, and we're not
	// delaying, load more samples or, if we run out of samples from non-looping source, 
	// pad copy buffer.
	if ( samples_loaded < sample_load_request )
	{
		// retry loading source data until 0 bytes returned, or we've loaded enough data.
		// if we hit 0 bytes, fill remaining space in copy buffer with 0 and exit
		int samples_load_extra;
		int samples_loaded_retry = -1;
			
		for ( int k = 0; (k < 10000 && samples_loaded_retry && samples_loaded < sample_load_request); k++ )
		{
			// how many more samples do we need to satisfy load request
			samples_load_extra = sample_load_request - samples_loaded;
			samples_loaded_retry = GetOutputData( (void**)&pData, samples_load_extra, copyBuf );

			// copy loaded samples from pData into pCopy
			if ( samples_loaded_retry )
			{
				if ( ( samples_loaded_retry * samplesize ) != 0 && !pData )
				{
					Warning( "CAudioMixerWave::LoadMixBuffer:  samples_loaded_retry * samplesize = %i but pData == NULL\n", ( samples_loaded_retry * samplesize ) );
					*pSamplesLoaded = 0;
					return NULL;
				}

				Q_memcpy( pCopy, pData, samples_loaded_retry * samplesize );
				pCopy += samples_loaded_retry * samplesize;
				samples_loaded += samples_loaded_retry;
			}
		}
	}

	// if we still couldn't load the requested samples, fill rest of copy buffer with 0
	if ( samples_loaded < sample_load_request )
	{
		// should always be able to get as many samples as we request from looping sound sources
		AssertOnce ( IsX360() || !m_pData->Source().IsLooped() );

		// these samples are filled with 0, not loaded.
		// non-looping source hit end of data, fill rest of g_temppaintbuffer with 0
		int samples_zero_fill = sample_load_request - samples_loaded;

		Q_memset( pCopy, 0, samples_zero_fill * samplesize );
		pCopy += samples_zero_fill * samplesize;
		samples_loaded += samples_zero_fill;
	}

	if ( samples_loaded >= 2 )
	{
		// always save last 2 samples from copy buffer to channel 
		// (we'll need 0,1 or 2 samples as start of next buffer for interpolation)
		Assert( sizeof( pChannel->sample_prev ) >= samplesize*2 );
		pSample = pCopy - samplesize*2;
		Q_memcpy( &(pChannel->sample_prev[0]), pSample, samplesize*2 );
	}

	// this routine must always return as many samples loaded (or zeros) as requested.
	Assert( samples_loaded == sample_load_request );

	*pSamplesLoaded = samples_loaded;

	return (char *)g_temppaintbuffer;
}
Example #25
0
// Called during player movement to set up/restore after lag compensation
void CLagCompensationManager::StartLagCompensation( CBasePlayer *player, CUserCmd *cmd )
{
	//DONT LAG COMP AGAIN THIS FRAME IF THERES ALREADY ONE IN PROGRESS
	//IF YOU'RE HITTING THIS THEN IT MEANS THERES A CODE BUG
	if ( m_pCurrentPlayer )
	{
		Assert( m_pCurrentPlayer == NULL );
		Warning( "Trying to start a new lag compensation session while one is already active!\n" );
		return;
	}

	// sort out any changes to the AI indexing
	if ( m_bNeedsAIUpdate ) // to be called once per frame... must happen BEFORE lag compensation -
	{// if that happens, that is. if not its called at the end of the frame
		m_bNeedsAIUpdate = false;
		UpdateAIIndexes();
	}

	// Assume no players or entities need to be restored
	m_RestorePlayer.ClearAll();
	m_RestoreEntity.ClearAll();
	m_bNeedToRestore = false;

	m_pCurrentPlayer = player;
	
	if ( !player->m_bLagCompensation		// Player not wanting lag compensation
		 || (gpGlobals->maxClients <= 1)	// no lag compensation in single player
		 || !sv_unlag.GetBool()				// disabled by server admin
		 || player->IsBot() 				// not for bots
		 || player->IsObserver()			// not for spectators
		)
		return;

	// NOTE: Put this here so that it won't show up in single player mode.
	VPROF_BUDGET( "StartLagCompensation", VPROF_BUDGETGROUP_OTHER_NETWORKING );
	Q_memset( m_RestoreData, 0, sizeof( m_RestoreData ) );
	Q_memset( m_ChangeData, 0, sizeof( m_ChangeData ) );
	Q_memset( m_EntityRestoreData, 0, sizeof( m_EntityRestoreData ) );
	Q_memset( m_EntityChangeData, 0, sizeof( m_EntityChangeData ) );

	// Get true latency

	// correct is the amout of time we have to correct game time
	float correct = 0.0f;

	INetChannelInfo *nci = engine->GetPlayerNetInfo( player->entindex() ); 

	if ( nci )
	{
		// add network latency
		correct+= nci->GetLatency( FLOW_OUTGOING );
	}

	// calc number of view interpolation ticks - 1
	int lerpTicks = TIME_TO_TICKS( player->m_fLerpTime );

	// add view interpolation latency see C_BaseEntity::GetInterpolationAmount()
	correct += TICKS_TO_TIME( lerpTicks );
	
	// check bouns [0,sv_maxunlag]
	correct = clamp( correct, 0.0f, sv_maxunlag.GetFloat() );

	// correct tick send by player 
	int targettick = cmd->tick_count - lerpTicks;

	// calc difference between tick send by player and our latency based tick
	float deltaTime =  correct - TICKS_TO_TIME(gpGlobals->tickcount - targettick);

	if ( fabs( deltaTime ) > 0.2f )
	{
		// difference between cmd time and latency is too big > 200ms, use time correction based on latency
		// DevMsg("StartLagCompensation: delta too big (%.3f)\n", deltaTime );
		targettick = gpGlobals->tickcount - TIME_TO_TICKS( correct );
	}
	
	// Iterate all active players
	const CBitVec<MAX_EDICTS> *pEntityTransmitBits = engine->GetEntityTransmitBitsForClient( player->entindex() - 1 );
	for ( int i = 1; i <= gpGlobals->maxClients; i++ )
	{
		CBasePlayer *pPlayer = UTIL_PlayerByIndex( i );
		if ( !pPlayer || player == pPlayer )
			continue;

		// Custom checks for if things should lag compensate (based on things like what team the player is on).
		if ( !player->WantsLagCompensationOnEntity( pPlayer, cmd, pEntityTransmitBits ) )
			continue;

		// Move other player back in time
		BacktrackPlayer( pPlayer, TICKS_TO_TIME( targettick ) );
	}

	// also iterate all monsters
	CAI_BaseNPC **ppAIs = g_AI_Manager.AccessAIs();
	int nAIs = g_AI_Manager.NumAIs();

	for ( int i = 0; i < nAIs; i++ )
	{
		CAI_BaseNPC *pNPC = ppAIs[i];
		// Custom checks for if things should lag compensate
		if ( !pNPC || !player->WantsLagCompensationOnEntity( pNPC, cmd, pEntityTransmitBits ) )
			continue;
		
		// Move NPC back in time
		BacktrackEntity( pNPC, TICKS_TO_TIME( targettick ) );
	}
}
Example #26
0
//-----------------------------------------------------------------------------
// Purpose: Clear out game stats
// Input  :  - 
//-----------------------------------------------------------------------------
void CTFGameStats::Clear( void )
{
	m_reportedStats.Clear();
	Q_memset( m_aPlayerStats, 0, sizeof( m_aPlayerStats ) );
	CBaseGameStats::Clear();
}
Example #27
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *fmt - 
//			... - 
//-----------------------------------------------------------------------------
void CBaseHudChat::ChatPrintf( int iPlayerIndex, int iFilter, const char *fmt, ... )
{
	va_list marker;
	char msg[4096];

	va_start(marker, fmt);
	Q_vsnprintf(msg, sizeof( msg), fmt, marker);
	va_end(marker);

	// Strip any trailing '\n'
	if ( strlen( msg ) > 0 && msg[ strlen( msg )-1 ] == '\n' )
	{
		msg[ strlen( msg ) - 1 ] = 0;
	}

	// Strip leading \n characters ( or notify/color signifiers ) for empty string check
	char *pmsg = msg;
	while ( *pmsg && ( *pmsg == '\n' || ( *pmsg > 0 && *pmsg < COLOR_MAX ) ) )
	{
		pmsg++;
	}

	if ( !*pmsg )
		return;

	// Now strip just newlines, since we want the color info for printing
	pmsg = msg;
	while ( *pmsg && ( *pmsg == '\n' ) )
	{
		pmsg++;
	}

	if ( !*pmsg )
		return;

	CBaseHudChatLine *line = (CBaseHudChatLine *)FindUnusedChatLine();
	if ( !line )
	{
		line = (CBaseHudChatLine *)FindUnusedChatLine();
	}

	if ( !line )
	{
		return;
	}

	if ( iFilter != CHAT_FILTER_NONE )
	{
		if ( !(iFilter & m_iFilterFlags ) )
			return;
	}

	if ( *pmsg < 32 )
	{
		hudlcd->AddChatLine( pmsg + 1 );
	}
	else
	{
		hudlcd->AddChatLine( pmsg );
	}

	line->SetText( "" );

	int iNameStart = 0;
	int iNameLength = 0;

	player_info_t sPlayerInfo;
	if ( iPlayerIndex == 0 )
	{
		Q_memset( &sPlayerInfo, 0, sizeof(player_info_t) );
		Q_strncpy( sPlayerInfo.name, "Console", sizeof(sPlayerInfo.name)  );	
	}
	else
	{
		engine->GetPlayerInfo( iPlayerIndex, &sPlayerInfo );
	}	

	int bufSize = (strlen( pmsg ) + 1 ) * sizeof(wchar_t);
	wchar_t *wbuf = static_cast<wchar_t *>( _alloca( bufSize ) );
	if ( wbuf )
	{
		Color clrNameColor = GetClientColor( iPlayerIndex );

		line->SetExpireTime();

		g_pVGuiLocalize->ConvertANSIToUnicode( pmsg, wbuf, bufSize);

		// find the player's name in the unicode string, in case there is no color markup
		const char *pName = sPlayerInfo.name;

		if ( pName )
		{
			wchar_t wideName[MAX_PLAYER_NAME_LENGTH];
			g_pVGuiLocalize->ConvertANSIToUnicode( pName, wideName, sizeof( wideName ) );

			const wchar_t *nameInString = wcsstr( wbuf, wideName );

			if ( nameInString )
			{
				iNameStart = (nameInString - wbuf);
				iNameLength = wcslen( wideName );
			}
		}

		line->SetVisible( false );
		line->SetNameStart( iNameStart );
		line->SetNameLength( iNameLength );
		line->SetNameColor( clrNameColor );

		line->InsertAndColorizeText( wbuf, iPlayerIndex );
	}
}
Example #28
0
void CMultiSource::Restart()
{
	Q_memset(m_rgTriggered, 0, sizeof(m_rgTriggered));
	Spawn();
}
Example #29
0
/*
===================
CL_ParseClientData
===================
*/
void CL_ParseClientData( sizebuf_t *msg )
{
	int		i, j;
	clientdata_t	*from_cd, *to_cd;
	weapon_data_t	*from_wd, *to_wd;
	weapon_data_t	nullwd[32];
	clientdata_t	nullcd;
	frame_t		*frame;
	int		idx;

	// this is the frame update that this message corresponds to
	i = cls.netchan.incoming_sequence;

	// did we drop some frames?
	if( i > cl.last_incoming_sequence + 1 )
	{
		// mark as dropped
		for( j = cl.last_incoming_sequence + 1; j < i; j++ )
		{
			if( cl.frames[j & CL_UPDATE_MASK].receivedtime >= 0.0 )
			{
				cl.frames[j & CL_UPDATE_MASK].receivedtime = -1;
				cl.frames[j & CL_UPDATE_MASK].latency = 0;
			}
		}
	}

	cl.parsecount = i;					// ack'd incoming messages.  
	cl.parsecountmod = cl.parsecount & CL_UPDATE_MASK;	// index into window.     
	frame = &cl.frames[cl.parsecountmod];			// frame at index.

	frame->time = cl.mtime[0];				// mark network received time
	frame->receivedtime = host.realtime;			// time now that we are parsing.  

	if( cl.last_command_ack != -1 )
	{
		int last_predicted;
		entity_state_t * ps;
		entity_state_t * pps;
		clientdata_t * pcd;
		clientdata_t * ppcd;
		weapon_data_t * wd;
		weapon_data_t * pwd;

		last_predicted = ( cl.last_incoming_sequence + (
							   cls.netchan.incoming_acknowledged - cl.last_command_ack)) & CL_UPDATE_MASK;

		pps = &cl.predict[last_predicted].playerstate;
		ppcd = &cl.predict[last_predicted].client;
		pwd = cl.predict[last_predicted].weapondata;

		ps = &frame->playerstate[cl.playernum];
		pcd = &frame->local.client;
		wd = frame->local.weapondata;

		clgame.dllFuncs.pfnTxferPredictionData( ps, pps, pcd, ppcd, wd, pwd );
	}

	// do this after all packets read for this frame?
	cl.last_command_ack = cls.netchan.incoming_acknowledged;
	cl.last_incoming_sequence = cls.netchan.incoming_sequence;

	if( hltv->integer ) return;	// clientdata for spectators ends here
	
	to_cd = &frame->local.client;
	to_wd = frame->local.weapondata;

	// clear to old value before delta parsing
	if( !BF_ReadOneBit( msg ))
	{
		Q_memset( &nullcd, 0, sizeof( nullcd ));
		Q_memset( nullwd, 0, sizeof( nullwd ));
		from_cd = &nullcd;
		from_wd = nullwd;
	}
	else
	{
		int	delta_sequence = BF_ReadByte( msg );

		from_cd = &cl.frames[delta_sequence & CL_UPDATE_MASK].local.client;
		from_wd = cl.frames[delta_sequence & CL_UPDATE_MASK].local.weapondata;
	}

	MSG_ReadClientData( msg, from_cd, to_cd, cl.mtime[0] );

	for( i = 0; i < MAX_WEAPONS; i++ )
	{
		// check for end of weapondata (and clientdata_t message)
		if( !BF_ReadOneBit( msg )) break;

		// read the weapon idx
		idx = BF_ReadUBitLong( msg, MAX_WEAPON_BITS );

		MSG_ReadWeaponData( msg, &from_wd[idx], &to_wd[idx], cl.mtime[0] );
	}
}
Example #30
0
/*
==================
CL_ParseServerData
==================
*/
void CL_ParseServerData( sizebuf_t *msg )
{
	string	gamefolder;
	qboolean	background;
	int	i;

	MsgDev( D_NOTE, "Serverdata packet received.\n" );

	cls.demowaiting = false;	// server is changed
	clgame.load_sequence++;	// now all hud sprites are invalid

	// wipe the client_t struct
	if( !cls.changelevel && !cls.changedemo )
		CL_ClearState ();
	cls.state = ca_connected;

	// parse protocol version number
	i = BF_ReadLong( msg );
	cls.serverProtocol = i;

	if( i != PROTOCOL_VERSION )
		Host_Error( "Server uses invalid protocol (%i should be %i)\n", i, PROTOCOL_VERSION );

	cl.servercount = BF_ReadLong( msg );
	cl.checksum = BF_ReadLong( msg );
	cl.playernum = BF_ReadByte( msg );
	cl.maxclients = BF_ReadByte( msg );
	clgame.maxEntities = BF_ReadWord( msg );
	clgame.maxEntities = bound( 600, clgame.maxEntities, 4096 );
	Q_strncpy( clgame.mapname, BF_ReadString( msg ), MAX_STRING );
	Q_strncpy( clgame.maptitle, BF_ReadString( msg ), MAX_STRING );
	background = BF_ReadOneBit( msg );
	Q_strncpy( gamefolder, BF_ReadString( msg ), MAX_STRING );
	host.features = (uint)BF_ReadLong( msg );

	if( cl.maxclients > 1 && host.developer < 1 )
		host.developer++;

	// set the background state
	if( cls.demoplayback && ( cls.demonum != -1 ))
	{
		// re-init mouse
		host.mouse_visible = false;
		cl.background = true;
	}
	else cl.background = background;

	if( cl.background )	// tell the game parts about background state
		Cvar_FullSet( "cl_background", "1", CVAR_READ_ONLY );
	else Cvar_FullSet( "cl_background", "0", CVAR_READ_ONLY );

	if( !cls.changelevel ) 
	{
		// continue playing if we are changing level
		S_StopBackgroundTrack ();
	}
#if 0
	// NOTE: this is not tested as well. Use with precaution
	CL_ChangeGame( gamefolder, false );
#endif
	if( !cls.changedemo )
		UI_SetActiveMenu( cl.background );

	cl.refdef.viewentity = cl.playernum + 1; // always keep viewent an actual

	menu.globals->maxClients = cl.maxclients;
	Q_strncpy( menu.globals->maptitle, clgame.maptitle, sizeof( menu.globals->maptitle ));

	if( cl.maxclients > 1 && r_decals->value > mp_decals->value )
		Cvar_SetFloat( "r_decals", mp_decals->value );

	if( !cls.changelevel && !cls.changedemo )
		CL_InitEdicts (); // re-arrange edicts

	// get splash name
	if( cls.demoplayback && ( cls.demonum != -1 ))
		Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", cls.demoname, glState.wideScreen ? "16x9" : "4x3" ));
	else Cvar_Set( "cl_levelshot_name", va( "levelshots/%s_%s", clgame.mapname, glState.wideScreen ? "16x9" : "4x3" ));
	Cvar_SetFloat( "scr_loading", 0.0f ); // reset progress bar

	if(( cl_allow_levelshots->integer && !cls.changelevel ) || cl.background )
	{
		if( !FS_FileExists( va( "%s.bmp", cl_levelshot_name->string ), true )) 
			Cvar_Set( "cl_levelshot_name", "*black" ); // render a black screen
		cls.scrshot_request = scrshot_plaque; // request levelshot even if exist (check filetime)
	}

	if( scr_dark->integer )
	{
		screenfade_t		*sf = &clgame.fade;
		client_textmessage_t	*title;

		title = CL_TextMessageGet( "GAMETITLE" );

		if( title )
		{
			// get settings from titles.txt
			sf->fadeEnd = title->holdtime + title->fadeout;
			sf->fadeReset = title->fadeout;
		}
		else sf->fadeEnd = sf->fadeReset = 4.0f;
	
		sf->fadeFlags = FFADE_IN;
		sf->fader = sf->fadeg = sf->fadeb = 0;
		sf->fadealpha = 255;
		sf->fadeSpeed = (float)sf->fadealpha / sf->fadeReset;
		sf->fadeReset += cl.time;
		sf->fadeEnd += sf->fadeReset;
		
		Cvar_SetFloat( "v_dark", 0.0f );
	}

	// need to prep refresh at next oportunity
	cl.video_prepped = false;
	cl.audio_prepped = false;

	Q_memset( &clgame.movevars, 0, sizeof( clgame.movevars ));
	Q_memset( &clgame.oldmovevars, 0, sizeof( clgame.oldmovevars ));
}