Example #1
0
/*
===============
CL_SparkShower

Creates 8 random tracers
===============
*/
void CL_SparkShower( const vec3_t org )
{
	vec3_t	pos, dir;
	model_t	*pmodel;
	float	vel;
	int	i;

	// randomize position
	pos[0] = org[0] + Com_RandomFloat( -2.0f, 2.0f );
	pos[1] = org[1] + Com_RandomFloat( -2.0f, 2.0f );
	pos[2] = org[2] + Com_RandomFloat( -2.0f, 2.0f );

	pmodel = Mod_Handle( CL_FindModelIndex( "sprites/richo1.spr" ));
	CL_RicochetSprite( pos, pmodel, 0.0f, Com_RandomFloat( 0.4, 0.6f ));

	// create a 8 random spakle tracers
	for( i = 0; i < 8; i++ )
	{
		dir[0] = Com_RandomFloat( -1.0f, 1.0f );
		dir[1] = Com_RandomFloat( -1.0f, 1.0f );
		dir[2] = Com_RandomFloat( -1.0f, 1.0f );
		vel = Com_RandomFloat( SPARK_ELECTRIC_MINSPEED, SPARK_ELECTRIC_MAXSPEED );

		CL_SparkleTracer( pos, dir, vel );
	}
}
Example #2
0
/*
* R_CullAliasModel
*/
qboolean R_CullAliasModel( entity_t *e )
{
	int i, j, clipped;
	qboolean frustum, query;
	unsigned int modhandle;
	model_t	*mod;
	shader_t *shader;
	maliasmodel_t *aliasmodel;
	maliasmesh_t *mesh;

	mod = R_AliasModelLOD( e );
	if( !( aliasmodel = ( ( maliasmodel_t * )mod->extradata ) ) || !aliasmodel->nummeshes )
		return qtrue;

	R_AliasModelLerpBBox( e, mod );
	modhandle = Mod_Handle( mod );

	clipped = R_CullModel( e, alias_mins, alias_maxs, alias_radius );
	frustum = clipped & 1;
	if( clipped & 2 )
		return qtrue;

	query = OCCLUSION_QUERIES_ENABLED( ri ) && OCCLUSION_TEST_ENTITY( e ) ? qtrue : qfalse;
	if( !frustum && query )
		R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_ENTITY, e - r_entities ), e, alias_mins, alias_maxs );

	if( ( ri.refdef.rdflags & RDF_NOWORLDMODEL )
		|| ( r_shadows->integer != SHADOW_PLANAR && !( r_shadows->integer == SHADOW_MAPPING && ( e->flags & RF_PLANARSHADOW ) ) )
		|| R_CullPlanarShadow( e, alias_mins, alias_maxs, query ) )
		return frustum; // entity is not in PVS or shadow is culled away by frustum culling

	for( i = 0, mesh = aliasmodel->meshes; i < aliasmodel->nummeshes; i++, mesh++ )
	{
		shader = NULL;

		if( e->customSkin )
			shader = R_FindShaderForSkinFile( e->customSkin, mesh->name );
		else if( e->customShader )
			shader = e->customShader;
		else if( mesh->numskins )
		{
			for( j = 0; j < mesh->numskins; j++ )
			{
				shader = mesh->skins[j].shader;
				if( shader && shader->sort <= SHADER_SORT_ALPHATEST )
					break;
				shader = NULL;
			}
		}

		if( shader && ( shader->sort <= SHADER_SORT_ALPHATEST ) ) {
			R_AddModelMeshToList( modhandle, mesh->vbo, NULL, R_PlanarShadowShader(), i, 0, mesh->numverts, mesh->numtris * 3 );
		}
	}

	return frustum;
}
Example #3
0
/*
===============
V_SetupRefDef

update refdef values each frame
===============
*/
void V_SetupRefDef( void )
{
	cl_entity_t	*clent;

	clent = CL_GetLocalPlayer ();

	clgame.entities->curstate.scale = clgame.movevars.waveHeight;
	VectorCopy( cl.frame.local.client.punchangle, cl.refdef.punchangle );
	clgame.viewent.curstate.modelindex = cl.frame.local.client.viewmodel;
	clgame.viewent.model = Mod_Handle( clgame.viewent.curstate.modelindex );
	clgame.viewent.curstate.entityType = ET_NORMAL;
	clgame.viewent.index = cl.playernum + 1;

	cl.refdef.movevars = &clgame.movevars;
	cl.refdef.onground = ( cl.frame.local.client.flags & FL_ONGROUND ) ? 1 : 0;
	cl.refdef.health = cl.frame.local.client.health;
	cl.refdef.playernum = cl.playernum;
	cl.refdef.max_entities = clgame.maxEntities;
	cl.refdef.maxclients = cl.maxclients;
	cl.refdef.time = cl.time;
	cl.refdef.frametime = cl.time - cl.oldtime;
	cl.refdef.demoplayback = cls.demoplayback;
	cl.refdef.smoothing = cl_smooth->integer;
	cl.refdef.waterlevel = cl.frame.local.client.waterlevel;		
	cl.refdef.onlyClientDraw = 0;	// reset clientdraw
	cl.refdef.viewsize = scr_viewsize->integer;
	cl.refdef.hardware = true;	// always true
	cl.refdef.spectator = cl.spectator;
	cl.refdef.nextView = 0;

	// setup default viewport
	cl.refdef.viewport[0] = cl.refdef.viewport[1] = 0;
	cl.refdef.viewport[2] = scr_width->integer;
	cl.refdef.viewport[3] = scr_height->integer;

	// calc FOV
	cl.refdef.fov_x = cl.data.fov; // this is a final fov value
	cl.refdef.fov_y = V_CalcFov( &cl.refdef.fov_x, cl.refdef.viewport[2], cl.refdef.viewport[3] );

	if( CL_IsPredicted( ) && !cl.refdef.demoplayback )
	{	
		VectorCopy( cl.predicted_origin, cl.refdef.simorg );
		VectorCopy( cl.predicted_velocity, cl.refdef.simvel );
		VectorCopy( cl.predicted_viewofs, cl.refdef.viewheight );
	}
	else
	{
		VectorCopy( cl.frame.local.client.origin, cl.refdef.simorg );
		VectorCopy( cl.frame.local.client.view_ofs, cl.refdef.viewheight );
		VectorCopy( cl.frame.local.client.velocity, cl.refdef.simvel );
	}
}
Example #4
0
/*
============
SV_AllowPushRotate

Allows to change entity yaw?
============
*/
qboolean SV_AllowPushRotate( edict_t *ent )
{
	model_t	*mod;

	mod = Mod_Handle( ent->v.modelindex );
	if( !mod || mod->type != mod_brush )
		return true;

	if( !sv_allow_rotate_pushables->integer )
		return false;

	return (mod->flags & MODEL_HAS_ORIGIN) ? true : false;
}
Example #5
0
/*
====================
StudioGetAttachment
====================
*/
void Mod_StudioGetAttachment( const edict_t *e, int iAttachment, float *origin, float *angles )
{
	mstudioattachment_t		*pAtt;
	vec3_t			angles2;
	model_t			*mod;

	mod = Mod_Handle( e->v.modelindex );
	mod_studiohdr = (studiohdr_t *)Mod_Extradata( mod );
	if( !mod_studiohdr ) return;

	if( mod_studiohdr->numattachments <= 0 )
		return;

	ASSERT( pBlendAPI != NULL );

	if( mod_studiohdr->numattachments > MAXSTUDIOATTACHMENTS )
	{
		mod_studiohdr->numattachments = MAXSTUDIOATTACHMENTS; // reduce it
		MsgDev( D_WARN, "SV_StudioGetAttahment: too many attachments on %s\n", mod_studiohdr->name );
	}

	iAttachment = bound( 0, iAttachment, mod_studiohdr->numattachments );

	// calculate attachment origin and angles
	pAtt = (mstudioattachment_t *)((byte *)mod_studiohdr + mod_studiohdr->attachmentindex);

	VectorCopy( e->v.angles, angles2 );

	if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG ))
		angles2[PITCH] = -angles2[PITCH];

	pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, angles2, e->v.origin,
		e->v.controller, e->v.blending, pAtt[iAttachment].bone, e );

	// compute pos and angles
	if( origin != NULL )
		Matrix3x4_VectorTransform( studio_bones[pAtt[iAttachment].bone], pAtt[iAttachment].org, origin );

	if( sv_allow_studio_attachment_angles->integer && origin != NULL && angles != NULL )
	{
		vec3_t	forward, bonepos;

		Matrix3x4_OriginFromMatrix( studio_bones[pAtt[iAttachment].bone], bonepos );
		VectorSubtract( origin, bonepos, forward ); // make forward
		VectorNormalizeFast( forward );
		VectorAngles( forward, angles );
	}
}
Example #6
0
/*
====================
GetBonePosition
====================
*/
void Mod_GetBonePosition( const edict_t *e, int iBone, float *origin, float *angles )
{
	model_t	*mod;

	mod = Mod_Handle( e->v.modelindex );
	mod_studiohdr = (studiohdr_t *)Mod_Extradata( mod );
	if( !mod_studiohdr ) return;

	ASSERT( pBlendAPI != NULL );

	pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, e->v.angles, e->v.origin,
		e->v.controller, e->v.blending, iBone, e );

	if( origin ) Matrix3x4_OriginFromMatrix( studio_bones[iBone], origin );
	if( angles ) VectorAngles( studio_bones[iBone][0], angles ); // bone forward to angles
}
Example #7
0
/*
==============
CL_ParseStudioDecal

Studio Decal message. Used by engine in case
we need save\restore decals
==============
*/
void CL_ParseStudioDecal( sizebuf_t *msg )
{
	modelstate_t	state;
	vec3_t		start, pos;
	int		decalIndex, entityIndex;
	int		modelIndex = 0;
	int		flags;

	pos[0] = BF_ReadCoord( msg );
	pos[1] = BF_ReadCoord( msg );
	pos[2] = BF_ReadCoord( msg );
	start[0] = BF_ReadCoord( msg );
	start[1] = BF_ReadCoord( msg );
	start[2] = BF_ReadCoord( msg );
	decalIndex = BF_ReadShort( msg );
	entityIndex = BF_ReadShort( msg );
	flags = BF_ReadByte( msg );

	state.sequence = BF_ReadShort( msg );
	state.frame = BF_ReadShort( msg );
	state.blending[0] = BF_ReadByte( msg );
	state.blending[1] = BF_ReadByte( msg );
	state.controller[0] = BF_ReadByte( msg );
	state.controller[1] = BF_ReadByte( msg );
	state.controller[2] = BF_ReadByte( msg );
	state.controller[3] = BF_ReadByte( msg );

	if( cls.state == ca_connected )
	{
		// this message came on restore.
		// read modelindex in case client models are not linked with entities
		// because first client frame has not yet received
		modelIndex = BF_ReadShort( msg );
	}

	if( clgame.drawFuncs.R_StudioDecalShoot )
	{
		int decalTexture = CL_DecalIndex( decalIndex );
		cl_entity_t *ent = CL_GetEntityByIndex( entityIndex );

		if( ent && !ent->model && modelIndex != 0 )
			ent->model = Mod_Handle( modelIndex );

		clgame.drawFuncs.R_StudioDecalShoot( decalTexture, ent, start, pos, flags, &state );
	}
}
Example #8
0
/*
==============
CL_ParseStudioDecal

Studio Decal message. Used by engine in case
we need save\restore decals
==============
*/
void CL_ParseStudioDecal( sizebuf_t *msg )
{
	modelstate_t	state;
	vec3_t		start, pos;
	int		decalIndex, entityIndex;
	int		modelIndex = 0;
	int		flags;

	BF_ReadVec3Coord( msg, pos );
	BF_ReadVec3Coord( msg, start );
	decalIndex = BF_ReadWord( msg );
	entityIndex = BF_ReadWord( msg );
	flags = BF_ReadByte( msg );

	state.sequence = BF_ReadShort( msg );
	state.frame = BF_ReadShort( msg );
	state.blending[0] = BF_ReadByte( msg );
	state.blending[1] = BF_ReadByte( msg );
	state.controller[0] = BF_ReadByte( msg );
	state.controller[1] = BF_ReadByte( msg );
	state.controller[2] = BF_ReadByte( msg );
	state.controller[3] = BF_ReadByte( msg );
	modelIndex = BF_ReadWord( msg );
	state.body = BF_ReadByte( msg );
	state.skin = BF_ReadByte( msg );

	if( clgame.drawFuncs.R_StudioDecalShoot != NULL )
	{
		int decalTexture = CL_DecalIndex( decalIndex );
		cl_entity_t *ent = CL_GetEntityByIndex( entityIndex );

		if( ent && !ent->model && modelIndex != 0 )
			ent->model = Mod_Handle( modelIndex );

		clgame.drawFuncs.R_StudioDecalShoot( decalTexture, ent, start, pos, flags, &state );
	}
}
Example #9
0
void CL_UpdateEntityFields( cl_entity_t *ent )
{
	// parametric rockets code
	if( ent->curstate.starttime != 0.0f && ent->curstate.impacttime != 0.0f )
	{
		float	lerp = ( cl.time - ent->curstate.starttime ) / ( ent->curstate.impacttime - ent->curstate.starttime );
		vec3_t	dir;

		lerp = bound( 0.0f, lerp, 1.0f );

		// first we need to calc actual origin
		VectorLerp( ent->curstate.startpos, lerp, ent->curstate.endpos, ent->curstate.origin );
		VectorSubtract( ent->curstate.endpos, ent->curstate.startpos, dir );
		VectorAngles( dir, ent->curstate.angles ); // re-aim projectile		
	}

	ent->model = Mod_Handle( ent->curstate.modelindex );
	ent->curstate.msg_time = cl.time;

	CL_InterpolateModel( ent );

	if( ent->player && RP_LOCALCLIENT( ent )) // stupid Half-Life bug
		ent->angles[PITCH] = -ent->angles[PITCH] / 3.0f;

	// make me lerp
	if( ent->model && ent->model->type == mod_brush && ent->curstate.animtime != 0.0f )
	{
		float		d, f = 0.0f;
		int		i;

		// don't do it if the goalstarttime hasn't updated in a while.
		// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
		// was increased to 1.0 s., which is 2x the max lag we are accounting for.
		if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime ))
			f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime );

		f = f - 1.0f;

		ent->origin[0] += ( ent->origin[0] - ent->latched.prevorigin[0] ) * f;
		ent->origin[1] += ( ent->origin[1] - ent->latched.prevorigin[1] ) * f;
		ent->origin[2] += ( ent->origin[2] - ent->latched.prevorigin[2] ) * f;

		for( i = 0; i < 3; i++ )
		{
			float	ang1, ang2;

			ang1 = ent->angles[i];
			ang2 = ent->latched.prevangles[i];
			d = ang1 - ang2;
			if( d > 180.0f ) d -= 360.0f;
			else if( d < -180.0f ) d += 360.0f;
			ent->angles[i] += d * f;
		}
	}
	else if( ent->curstate.eflags & EFLAG_SLERP )
	{
		float		d, f = 0.0f;
		cl_entity_t	*m_pGround = NULL;
		int		i;

		// don't do it if the goalstarttime hasn't updated in a while.
		// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
		// was increased to 1.0 s., which is 2x the max lag we are accounting for.
		if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime ))
			f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime );

		f = f - 1.0f;

		if( ent->curstate.movetype == MOVETYPE_FLY )
		{
			ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f;
			ent->origin[1] += ( ent->curstate.origin[1] - ent->latched.prevorigin[1] ) * f;
			ent->origin[2] += ( ent->curstate.origin[2] - ent->latched.prevorigin[2] ) * f;

			for( i = 0; i < 3; i++ )
			{
				float	ang1, ang2;

				ang1 = ent->curstate.angles[i];
				ang2 = ent->latched.prevangles[i];
				d = ang1 - ang2;
				if( d > 180.0f ) d -= 360.0f;
				else if( d < -180.0f ) d += 360.0f;
				ent->angles[i] += d * f;
			}
		}
		else if( ent->curstate.movetype == MOVETYPE_STEP )
		{
			vec3_t	vecSrc, vecEnd;
			pmtrace_t	trace;

			if( ent->model )
			{
				CL_SetTraceHull( 0 ); // g-cont. player hull for better detect moving platforms
				VectorSet( vecSrc, ent->origin[0], ent->origin[1], ent->origin[2] + ent->model->maxs[2] );
				VectorSet( vecEnd, vecSrc[0], vecSrc[1], vecSrc[2] - ent->model->mins[2] - 8.0f );		
				CL_PlayerTraceExt( vecSrc, vecEnd, PM_STUDIO_IGNORE, CL_PushMoveFilter, &trace );
				m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace ));
			}

			if( m_pGround && m_pGround->curstate.movetype == MOVETYPE_PUSH )
			{
				qboolean	applyVel, applyAvel;

				applyVel = !VectorCompare( m_pGround->curstate.origin, m_pGround->prevstate.origin );
				applyAvel = !VectorCompare( m_pGround->curstate.angles, m_pGround->prevstate.angles );

				if( applyVel || applyAvel )
				{
					ent->origin[0] += ( m_pGround->curstate.origin[0] - m_pGround->prevstate.origin[0] ) * -1.0f;
					ent->origin[1] += ( m_pGround->curstate.origin[1] - m_pGround->prevstate.origin[1] ) * -1.0f;
//					ent->origin[2] += ( m_pGround->curstate.origin[2] - m_pGround->prevstate.origin[2] ) * -1.0f;
					ent->latched.prevorigin[2] = ent->origin[2];
				}

				if( applyAvel )
				{
					for( i = 0; i < 3; i++ )
					{
						float	ang1, ang2;

						ang1 = m_pGround->curstate.angles[i];
						ang2 = m_pGround->prevstate.angles[i];
						d = ang1 - ang2;
						if( d > 180.0f ) d -= 360.0f;
						else if( d < -180.0f ) d += 360.0f;
						ent->angles[i] += d * -1.0f;
					}
				}
			}

			// moved code from StudioSetupTransform here
			if( host.features & ENGINE_COMPUTE_STUDIO_LERP )
			{
				ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f;
				ent->origin[1] += ( ent->curstate.origin[1] - ent->latched.prevorigin[1] ) * f;
				ent->origin[2] += ( ent->curstate.origin[2] - ent->latched.prevorigin[2] ) * f;

				for( i = 0; i < 3; i++ )
				{
					float	ang1, ang2;

					ang1 = ent->angles[i];
					ang2 = ent->latched.prevangles[i];
					d = ang1 - ang2;
					if( d > 180.0f ) d -= 360.0f;
					else if( d < -180.0f ) d += 360.0f;
					ent->angles[i] += d * f;
				}
			}
		}
	}
}
Example #10
0
qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
{
    model_t	*mod = Mod_Handle( ed->v.modelindex );

    if( !mod ) return false;
    pe->player = false;

    pe->info = NUM_FOR_EDICT( ed );
    VectorCopy( ed->v.origin, pe->origin );
    VectorCopy( ed->v.angles, pe->angles );

    if( ed->v.flags & ( FL_CLIENT|FL_FAKECLIENT ))
    {
        // client or bot
        if ( svs.currentPlayer )
            SV_GetTrueOrigin( svs.currentPlayer, (pe->info - 1), pe->origin );
        Q_strncpy( pe->name, "player", sizeof( pe->name ));
        pe->player = pe->info;
    }
    else
    {
        // otherwise copy the modelname
        Q_strncpy( pe->name, mod->name, sizeof( pe->name ));
    }

    pe->model = pe->studiomodel = NULL;

    switch( ed->v.solid )
    {
    case SOLID_NOT:
    case SOLID_BSP:
        pe->model = mod;
        VectorClear( pe->mins );
        VectorClear( pe->maxs );
        break;
    case SOLID_BBOX:
        if( mod && mod->type == mod_studio && mod->flags & STUDIO_TRACE_HITBOX )
            pe->studiomodel = mod;
        VectorCopy( ed->v.mins, pe->mins );
        VectorCopy( ed->v.maxs, pe->maxs );
        break;
    case SOLID_CUSTOM:
        pe->model = (mod->type == mod_brush) ? mod : NULL;
        pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
        VectorCopy( ed->v.mins, pe->mins );
        VectorCopy( ed->v.maxs, pe->maxs );
        break;
    default:
        pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
        VectorCopy( ed->v.mins, pe->mins );
        VectorCopy( ed->v.maxs, pe->maxs );
        break;
    }

    pe->solid = ed->v.solid;
    pe->rendermode = ed->v.rendermode;
    pe->skin = ed->v.skin;
    pe->frame = ed->v.frame;
    pe->sequence = ed->v.sequence;

    Q_memcpy( &pe->controller[0], &ed->v.controller[0], 4 * sizeof( byte ));
    Q_memcpy( &pe->blending[0], &ed->v.blending[0], 2 * sizeof( byte ));

    pe->movetype = ed->v.movetype;
    pe->takedamage = ed->v.takedamage;
    pe->team = ed->v.team;
    pe->classnumber = ed->v.playerclass;
    pe->blooddecal = 0;	// unused in GoldSrc

    // for mods
    pe->iuser1 = ed->v.iuser1;
    pe->iuser2 = ed->v.iuser2;
    pe->iuser3 = ed->v.iuser3;
    pe->iuser4 = ed->v.iuser4;
    pe->fuser1 = ed->v.fuser1;
    pe->fuser2 = ed->v.fuser2;
    pe->fuser3 = ed->v.fuser3;
    pe->fuser4 = ed->v.fuser4;

    VectorCopy( ed->v.vuser1, pe->vuser1 );
    VectorCopy( ed->v.vuser2, pe->vuser2 );
    VectorCopy( ed->v.vuser3, pe->vuser3 );
    VectorCopy( ed->v.vuser4, pe->vuser4 );

    return true;
}
Example #11
0
/*
* R_AddAliasModelToList
*/
void R_AddAliasModelToList( entity_t *e )
{
	int i, j;
	unsigned int modhandle, entnum = e - r_entities;
	mfog_t *fog = NULL;
	model_t	*mod;
	shader_t *shader;
	maliasmodel_t *aliasmodel;
	maliasmesh_t *mesh;
	float distance;

	mod = R_AliasModelLOD( e );
	aliasmodel = ( maliasmodel_t * )mod->extradata;
	modhandle = Mod_Handle( mod );

	// make sure weapon model is always closest to the viewer
	if( e->renderfx & RF_WEAPONMODEL ) {
		distance = 0;
	}
	else {
		distance = Distance( e->origin, ri.viewOrigin ) + 1;
	}

	if( ri.params & RP_SHADOWMAPVIEW )
	{
		if( r_entShadowBits[entnum] & ri.shadowGroup->bit )
		{
			if( !r_shadows_self_shadow->integer )
				r_entShadowBits[entnum] &= ~ri.shadowGroup->bit;
			if( e->flags & RF_WEAPONMODEL )
				return;
		}
		else
		{
			R_AliasModelLerpBBox( e, mod );
			if( !R_CullModel( e, alias_mins, alias_maxs, alias_radius ) )
				r_entShadowBits[entnum] |= ri.shadowGroup->bit;
			return; // mark as shadowed, proceed with caster otherwise
		}
	}
	else
	{
		fog = R_FogForSphere( e->origin, alias_radius );
#if 0
		if( !( e->flags & RF_WEAPONMODEL ) && fog )
		{
			R_AliasModelLerpBBox( e, mod );
			if( R_CompletelyFogged( fog, e->origin, alias_radius ) )
				return;
		}
#endif
	}

	for( i = 0, mesh = aliasmodel->meshes; i < aliasmodel->nummeshes; i++, mesh++ )
	{
		shader = NULL;

		if( e->customSkin )
			shader = R_FindShaderForSkinFile( e->customSkin, mesh->name );
		else if( e->customShader )
			shader = e->customShader;
		else if( mesh->numskins )
		{
			for( j = 0; j < mesh->numskins; j++ )
			{
				shader = mesh->skins[j].shader;
				if( shader )
					R_AddModelMeshToList( modhandle, mesh->vbo, fog, shader, i, distance, mesh->numverts, mesh->numtris * 3 );
			}
			continue;
		}

		if( shader )
			R_AddModelMeshToList( modhandle, mesh->vbo, fog, shader, i, distance, mesh->numverts, mesh->numtris * 3 );
	}
}
Example #12
0
// Shoots a decal onto the surface of the BSP.  position is the center of the decal in world coords
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis, float scale )
{
	decalinfo_t	decalInfo;
	hull_t		*hull;
	cl_entity_t	*ent = NULL;
	model_t		*model = NULL;
	int		width, height;

	if( textureIndex <= 0 || textureIndex >= MAX_TEXTURES )
	{
		MsgDev( D_ERROR, "Decal has invalid texture!\n" );
		return;
	}

	if( entityIndex > 0 )
	{
		ent = CL_GetEntityByIndex( entityIndex );

		if( modelIndex > 0 ) model = Mod_Handle( modelIndex );
		else if( ent != NULL ) model = Mod_Handle( ent->curstate.modelindex );
		else return;
	}
	else if( modelIndex > 0 )
		model = Mod_Handle( modelIndex );
	else model = cl.worldmodel;

	if( !model ) return;
	
	if( model->type != mod_brush )
	{
		MsgDev( D_ERROR, "Decals must hit mod_brush!\n" );
		return;
	}

	decalInfo.m_pModel = model;
	hull = &model->hulls[0];	// always use #0 hull

	if( ent && !( flags & FDECAL_LOCAL_SPACE ))
	{
		vec3_t	pos_l;

		// transform decal position in local bmodel space
		if( !VectorIsNull( ent->angles ))
		{
			matrix4x4	matrix;

			Matrix4x4_CreateFromEntity( matrix, ent->angles, ent->origin, 1.0f );
			Matrix4x4_VectorITransform( matrix, pos, pos_l );
		}
		else
		{
			VectorSubtract( pos, ent->origin, pos_l );
		}

		VectorCopy( pos_l, decalInfo.m_Position );
		flags |= FDECAL_LOCAL_SPACE; // decal position moved into local space
	}
	else
	{
		// pass position in global
		VectorCopy( pos, decalInfo.m_Position );
	}

	// deal with the s axis if one was passed in
	if( saxis )
	{
		flags |= FDECAL_USESAXIS;
		VectorCopy( saxis, decalInfo.m_SAxis );
	}

	// this decal must use landmark for correct transition
	if(!( model->flags & MODEL_HAS_ORIGIN ))
	{
		flags |= FDECAL_USE_LANDMARK;
	}

	// more state used by R_DecalNode()
	decalInfo.m_iTexture = textureIndex;
	decalInfo.m_Entity = entityIndex;
	decalInfo.m_Flags = flags;

	R_GetDecalDimensions( textureIndex, &width, &height );
	decalInfo.m_Size = width >> 1;
	if(( height >> 1 ) > decalInfo.m_Size )
		decalInfo.m_Size = height >> 1;

	decalInfo.m_scale = bound( MIN_DECAL_SCALE, scale, MAX_DECAL_SCALE );

	// compute the decal dimensions in world space
	decalInfo.m_decalWidth = width / decalInfo.m_scale;
	decalInfo.m_decalHeight = height / decalInfo.m_scale;

	R_DecalNode( model, &model->nodes[hull->firstclipnode], &decalInfo );
}
/*
=========================================================================

FRAME PARSING

=========================================================================
*/
void CL_UpdateEntityFields( cl_entity_t *ent )
{
	VectorCopy( ent->curstate.origin, ent->origin );
	VectorCopy( ent->curstate.angles, ent->angles );

	ent->model = Mod_Handle( ent->curstate.modelindex );
	ent->curstate.msg_time = cl.time;

	if( ent->player ) // stupid Half-Life bug
		ent->angles[PITCH] = -ent->angles[PITCH] / 3.0f;

	// make me lerp
	if( ent->model && ent->model->type == mod_brush && ent->curstate.animtime != 0.0f )
	{
		float		d, f = 0.0f;
		int		i;

		// don't do it if the goalstarttime hasn't updated in a while.
		// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
		// was increased to 1.0 s., which is 2x the max lag we are accounting for.
		if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime ))
			f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime );

		f = f - 1.0f;

		ent->origin[0] += ( ent->origin[0] - ent->latched.prevorigin[0] ) * f;
		ent->origin[1] += ( ent->origin[1] - ent->latched.prevorigin[1] ) * f;
		ent->origin[2] += ( ent->origin[2] - ent->latched.prevorigin[2] ) * f;

		for( i = 0; i < 3; i++ )
		{
			float	ang1, ang2;

			ang1 = ent->angles[i];
			ang2 = ent->latched.prevangles[i];
			d = ang1 - ang2;
			if( d > 180.0f ) d -= 360.0f;
			else if( d < -180.0f ) d += 360.0f;
			ent->angles[i] += d * f;
		}
	}
	else if( ent->curstate.eflags & EFLAG_SLERP )
	{
		float		d, f = 0.0f;
		cl_entity_t	*m_pGround = NULL;
		int		i;

		// don't do it if the goalstarttime hasn't updated in a while.
		// NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit
		// was increased to 1.0 s., which is 2x the max lag we are accounting for.
		if(( cl.time < ent->curstate.animtime + 1.0f ) && ( ent->curstate.animtime != ent->latched.prevanimtime ))
			f = ( cl.time - ent->curstate.animtime ) / ( ent->curstate.animtime - ent->latched.prevanimtime );

		f = f - 1.0f;

		if( ent->curstate.movetype == MOVETYPE_FLY )
		{
			ent->origin[0] += ( ent->curstate.origin[0] - ent->latched.prevorigin[0] ) * f;
			ent->origin[1] += ( ent->curstate.origin[1] - ent->latched.prevorigin[1] ) * f;
			ent->origin[2] += ( ent->curstate.origin[2] - ent->latched.prevorigin[2] ) * f;

			for( i = 0; i < 3; i++ )
			{
				float	ang1, ang2;

				ang1 = ent->curstate.angles[i];
				ang2 = ent->latched.prevangles[i];
				d = ang1 - ang2;
				if( d > 180.0f ) d -= 360.0f;
				else if( d < -180.0f ) d += 360.0f;
				ent->angles[i] += d * f;
			}
		}
		else if( ent->curstate.movetype == MOVETYPE_STEP )
		{
			vec3_t	vecSrc, vecEnd;
			pmtrace_t	trace;

			if( ent->model )
			{
				CL_SetTraceHull( 0 ); // g-cont. player hull for better detect moving platforms
				VectorSet( vecSrc, ent->origin[0], ent->origin[1], ent->origin[2] + ent->model->maxs[2] );
				VectorSet( vecEnd, vecSrc[0], vecSrc[1], vecSrc[2] - ent->model->mins[2] - 8.0f );		
				CL_PlayerTraceExt( vecSrc, vecEnd, PM_STUDIO_IGNORE, CL_PushMoveFilter, &trace );
				m_pGround = CL_GetEntityByIndex( pfnIndexFromTrace( &trace ));
			}

			if( m_pGround && m_pGround->curstate.movetype == MOVETYPE_PUSH )
			{
				qboolean	applyVel, applyAvel;

				d = -1.0f;

				applyVel = !VectorCompare( m_pGround->curstate.origin, m_pGround->prevstate.origin );
				applyAvel = !VectorCompare( m_pGround->curstate.angles, m_pGround->prevstate.angles );

				if( applyVel || applyAvel )
				{
					ent->origin[0] += ( m_pGround->curstate.origin[0] - m_pGround->prevstate.origin[0] ) * d;
					ent->origin[1] += ( m_pGround->curstate.origin[1] - m_pGround->prevstate.origin[1] ) * d;
//					ent->origin[2] += ( m_pGround->curstate.origin[2] - m_pGround->prevstate.origin[2] ) * d;
					ent->latched.prevorigin[2] = ent->origin[2];
				}

				if( applyAvel )
				{
					for( i = 0; i < 3; i++ )
					{
						float	ang1, ang2;

						ang1 = m_pGround->curstate.angles[i];
						ang2 = m_pGround->prevstate.angles[i];
						f = ang1 - ang2;
						if( d > 180.0f ) f -= 360.0f;
						else if( d < -180.0f ) f += 360.0f;
						ent->angles[i] += d * f;
					}
				}
			}
		}
	}
}
Example #14
0
/*
===============
V_SetupRefDef

update refdef values each frame
===============
*/
void V_SetupRefDef( void )
{
	cl_entity_t	*clent;
	int		size;
	int		sb_lines;

	clent = CL_GetLocalPlayer ();

	clgame.entities->curstate.scale = clgame.movevars.waveHeight;
	VectorCopy( cl.frame.local.client.punchangle, cl.refdef.punchangle );
	clgame.viewent.curstate.modelindex = cl.frame.local.client.viewmodel;
	clgame.viewent.model = Mod_Handle( clgame.viewent.curstate.modelindex );
	clgame.viewent.curstate.number = cl.playernum + 1;
	clgame.viewent.curstate.entityType = ET_NORMAL;
	clgame.viewent.index = cl.playernum + 1;

	cl.refdef.movevars = &clgame.movevars;
	cl.refdef.onground = ( cl.frame.local.client.flags & FL_ONGROUND ) ? 1 : 0;
	cl.refdef.health = cl.frame.local.client.health;
	cl.refdef.playernum = cl.playernum;
	cl.refdef.max_entities = clgame.maxEntities;
	cl.refdef.maxclients = cl.maxclients;
	cl.refdef.time = cl.time;
	cl.refdef.frametime = cl.time - cl.oldtime;
	cl.refdef.demoplayback = cls.demoplayback;
	cl.refdef.smoothing = cl_smooth->integer;
	cl.refdef.viewsize = scr_viewsize->integer;
	cl.refdef.waterlevel = cl.frame.local.client.waterlevel;		
	cl.refdef.onlyClientDraw = 0;	// reset clientdraw
	cl.refdef.hardware = true;	// always true
	cl.refdef.spectator = (clent->curstate.spectator != 0);
	cl.refdef.nextView = 0;

	SCR_AddDirtyPoint( 0, 0 );
	SCR_AddDirtyPoint( scr_width->integer - 1, scr_height->integer - 1 );

	if( cl.refdef.viewsize >= 120 )
		sb_lines = 0;		// no status bar at all
	else if( cl.refdef.viewsize >= 110 )
		sb_lines = 24;		// no inventory
	else sb_lines = 48;

	size = min( scr_viewsize->integer, 100 );

	cl.refdef.viewport[2] = scr_width->integer * size / 100;
	cl.refdef.viewport[3] = scr_height->integer * size / 100;

	if( cl.refdef.viewport[3] > scr_height->integer - sb_lines )
		cl.refdef.viewport[3] = scr_height->integer - sb_lines;
	if( cl.refdef.viewport[3] > scr_height->integer )
		cl.refdef.viewport[3] = scr_height->integer;

	cl.refdef.viewport[0] = (scr_width->integer - cl.refdef.viewport[2]) / 2;
	cl.refdef.viewport[1] = (scr_height->integer - sb_lines - cl.refdef.viewport[3]) / 2;

	// calc FOV
	cl.refdef.fov_x = cl.data.fov; // this is a final fov value
	cl.refdef.fov_y = V_CalcFov( &cl.refdef.fov_x, cl.refdef.viewport[2], cl.refdef.viewport[3] );

	// adjust FOV for widescreen
	if( glState.wideScreen && r_adjust_fov->integer )
		V_AdjustFov( &cl.refdef.fov_x, &cl.refdef.fov_y, cl.refdef.viewport[2], cl.refdef.viewport[3], false );

	if( CL_IsPredicted( ) && !cl.refdef.demoplayback )
	{	
		VectorCopy( cl.predicted_origin, cl.refdef.simorg );
		VectorCopy( cl.predicted_velocity, cl.refdef.simvel );
		VectorCopy( cl.predicted_viewofs, cl.refdef.viewheight );
	}
	else
	{
		VectorCopy( cl.frame.local.client.origin, cl.refdef.simorg );
		VectorCopy( cl.frame.local.client.view_ofs, cl.refdef.viewheight );
		VectorCopy( cl.frame.local.client.velocity, cl.refdef.simvel );
	}
}
Example #15
0
/*
=================
CL_PrepVideo

Call before entering a new level, or after changing dlls
=================
*/
void CL_PrepVideo( void )
{
	string	mdlname, mapname;
	int	i, mdlcount, step;
	int	map_checksum; // dummy

	if( !cl.model_precache[1][0] )
		return; // no map loaded

	Cvar_SetFloat( "scr_loading", 0.0f ); // reset progress bar
	MsgDev( D_NOTE, "CL_PrepVideo: %s\n", clgame.mapname );

	// let the render dll load the map
	Q_strncpy( mapname, cl.model_precache[1], MAX_STRING ); 
	Mod_LoadWorld( mapname, (uint *)&map_checksum, false );
	cl.worldmodel = Mod_Handle( 1 ); // get world pointer
	Cvar_SetFloat( "scr_loading", 25.0f );

	SCR_UpdateScreen();

	// make sure what map is valid
	if( !cls.demoplayback && map_checksum != cl.checksum )
		Host_Error( "Local map version differs from server: %i != '%i'\n", map_checksum, cl.checksum );

	for( i = 0, mdlcount = 0; i < MAX_MODELS && cl.model_precache[i+1][0]; i++ )
		mdlcount++; // total num models
	step = mdlcount/10;

	for( i = 0; i < MAX_MODELS && cl.model_precache[i+1][0]; i++ )
	{
		Q_strncpy( mdlname, cl.model_precache[i+1], MAX_STRING );
		Mod_RegisterModel( mdlname, i+1 );
		Cvar_SetFloat( "scr_loading", scr_loading->value + 75.0f / mdlcount );
		if( step && !( i % step ) && ( cl_allow_levelshots->integer || cl.background ) )
			SCR_UpdateScreen();
	}

	// update right muzzleflash indexes
	CL_RegisterMuzzleFlashes ();

	// invalidate all decal indexes
	Q_memset( cl.decal_index, 0, sizeof( cl.decal_index ));

	CL_ClearWorld ();

	R_NewMap(); // tell the render about new map

	V_SetupOverviewState(); // set overview bounds

	// must be called after lightmap loading!
	clgame.dllFuncs.pfnVidInit();

	// release unused SpriteTextures
	for( i = 1; i < MAX_IMAGES; i++ )
	{
		if( !clgame.sprites[i].name[0] ) continue; // free slot
		if( clgame.sprites[i].needload != clgame.load_sequence )
			Mod_UnloadSpriteModel( &clgame.sprites[i] );
	}

	Mod_FreeUnused ();

	Q_memset( cl.playermodels, 0, sizeof( cl.playermodels ) );

	Cvar_SetFloat( "scr_loading", 100.0f );	// all done

	if( host.decalList )
	{
		// need to reapply all decals after restarting
		for( i = 0; i < host.numdecals; i++ )
		{
			decallist_t *entry = &host.decalList[i];
			cl_entity_t *pEdict = CL_GetEntityByIndex( entry->entityIndex );
			int decalIndex = CL_DecalIndex( CL_DecalIndexFromName( entry->name ));
			int modelIndex = 0;

			if( pEdict ) modelIndex = pEdict->curstate.modelindex;
			CL_DecalShoot( decalIndex, entry->entityIndex, modelIndex, entry->position, entry->flags );
		}
		Z_Free( host.decalList );
	}

	host.decalList = NULL; 
	host.numdecals = 0;

	if( host.soundList )
	{
		// need to reapply all ambient sounds after restarting
		for( i = 0; i < host.numsounds; i++ )
		{
			soundlist_t *entry = &host.soundList[i];
			if( entry->looping && entry->entnum != -1 )
			{
				MsgDev( D_NOTE, "Restarting sound %s...\n", entry->name );
				S_AmbientSound( entry->origin, entry->entnum,
				S_RegisterSound( entry->name ), entry->volume, entry->attenuation,
				entry->pitch, 0 );
			}
		}
	}

	host.soundList = NULL; 
	host.numsounds = 0;
	
	if( host.developer <= 2 )
		Con_ClearNotify(); // clear any lines of console text

	SCR_UpdateScreen ();

	cl.video_prepped = true;
	cl.force_refdef = true;
}
Example #16
0
/*
================
SV_SpawnServer

Change the server to a new map, taking all connected
clients along with it.
================
*/
qboolean SV_SpawnServer( const char *mapname, const char *startspot )
{
	int	i, current_skill;
	qboolean	loadgame, paused;
	qboolean	background, changelevel;

	// save state
	loadgame = sv.loadgame;
	background = sv.background;
	changelevel = sv.changelevel;
	paused = sv.paused;

	if( sv.state == ss_dead )
		SV_InitGame(); // the game is just starting
	else if( !sv_maxclients->modified )
		Cmd_ExecuteString( "latch\n", src_command );
	else MsgDev( D_ERROR, "SV_SpawnServer: while 'maxplayers' was modified.\n" );

	sv_maxclients->modified = false;
	deathmatch->modified = false;
	teamplay->modified = false;
	coop->modified = false;

	if( !svs.initialized )
		return false;

	svgame.globals->changelevel = false; // will be restored later if needed
	svs.timestart = Sys_DoubleTime();
	svs.spawncount++; // any partially connected client will be restarted

	if( startspot )
	{
		MsgDev( D_INFO, "Spawn Server: %s [%s]\n", mapname, startspot );
	}
	else
	{
		MsgDev( D_INFO, "Spawn Server: %s\n", mapname );
	}

	sv.state = ss_dead;
	Host_SetServerState( sv.state );
	Q_memset( &sv, 0, sizeof( sv ));	// wipe the entire per-level structure

	// restore state
	sv.paused = paused;
	sv.loadgame = loadgame;
	sv.background = background;
	sv.changelevel = changelevel;
	sv.time = 1.0f;			// server spawn time it's always 1.0 second
	svgame.globals->time = sv.time;
	
	// initialize buffers
	BF_Init( &sv.datagram, "Datagram", sv.datagram_buf, sizeof( sv.datagram_buf ));
	BF_Init( &sv.reliable_datagram, "Datagram R", sv.reliable_datagram_buf, sizeof( sv.reliable_datagram_buf ));
	BF_Init( &sv.multicast, "Multicast", sv.multicast_buf, sizeof( sv.multicast_buf ));
	BF_Init( &sv.signon, "Signon", sv.signon_buf, sizeof( sv.signon_buf ));
	BF_Init( &sv.spectator_datagram, "Spectator Datagram", sv.spectator_buf, sizeof( sv.spectator_buf ));

	// leave slots at start for clients only
	for( i = 0; i < sv_maxclients->integer; i++ )
	{
		// needs to reconnect
		if( svs.clients[i].state > cs_connected )
			svs.clients[i].state = cs_connected;
	}

	// make cvars consistant
	if( Cvar_VariableInteger( "coop" )) Cvar_SetFloat( "deathmatch", 0 );
	current_skill = (int)(Cvar_VariableValue( "skill" ) + 0.5f);
	current_skill = bound( 0, current_skill, 3 );

	Cvar_SetFloat( "skill", (float)current_skill );

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

	// make sure what server name doesn't contain path and extension
	FS_FileBase( mapname, sv.name );

	if( startspot )
		Q_strncpy( sv.startspot, startspot, sizeof( sv.startspot ));
	else sv.startspot[0] = '\0';

	Q_snprintf( sv.model_precache[1], sizeof( sv.model_precache[0] ), "maps/%s.bsp", sv.name );
	Mod_LoadWorld( sv.model_precache[1], &sv.checksum, false );
	sv.worldmodel = Mod_Handle( 1 ); // get world pointer

	for( i = 1; i < sv.worldmodel->numsubmodels; i++ )
	{
		Q_sprintf( sv.model_precache[i+1], "*%i", i );
		Mod_RegisterModel( sv.model_precache[i+1], i+1 );
	}

	// precache and static commands can be issued during map initialization
	sv.state = ss_loading;

	Host_SetServerState( sv.state );

	// clear physics interaction links
	SV_ClearWorld();

	// tell dlls about new level started
	svgame.dllFuncs.pfnParmsNewLevel();

	return true;
}
Example #17
0
qboolean CL_CopyEntityToPhysEnt( physent_t *pe, cl_entity_t *ent )
{
	model_t	*mod = Mod_Handle( ent->curstate.modelindex );

	if( !mod ) return false;
	pe->player = false;

	if( ent->player )
	{
		// client or bot
		Q_strncpy( pe->name, "player", sizeof( pe->name ));
		pe->player = (int)(ent - clgame.entities);
	}
	else
	{
		// otherwise copy the modelname
		Q_strncpy( pe->name, mod->name, sizeof( pe->name ));
	}

	pe->model = pe->studiomodel = NULL;

	switch( ent->curstate.solid )
	{
	case SOLID_NOT:
	case SOLID_BSP:
		pe->model = mod;
		VectorClear( pe->mins );
		VectorClear( pe->maxs );
		break;
	case SOLID_BBOX:
		if( mod && mod->type == mod_studio && mod->flags & STUDIO_TRACE_HITBOX )
			pe->studiomodel = mod;
		VectorCopy( ent->curstate.mins, pe->mins );
		VectorCopy( ent->curstate.maxs, pe->maxs );
		break;
	case SOLID_CUSTOM:
		pe->model = (mod->type == mod_brush) ? mod : NULL;
		pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
		VectorCopy( ent->curstate.mins, pe->mins );
		VectorCopy( ent->curstate.maxs, pe->maxs );
		break;
	default:
		pe->studiomodel = (mod->type == mod_studio) ? mod : NULL;
		VectorCopy( ent->curstate.mins, pe->mins );
		VectorCopy( ent->curstate.maxs, pe->maxs );
		break;
	}

	pe->info = (int)(ent - clgame.entities);
	VectorCopy( ent->curstate.origin, pe->origin );
	VectorCopy( ent->curstate.angles, pe->angles );

	pe->solid = ent->curstate.solid;
	pe->rendermode = ent->curstate.rendermode;
	pe->skin = ent->curstate.skin;
	pe->frame = ent->curstate.frame;
	pe->sequence = ent->curstate.sequence;

	Q_memcpy( &pe->controller[0], &ent->curstate.controller[0], 4 * sizeof( byte ));
	Q_memcpy( &pe->blending[0], &ent->curstate.blending[0], 2 * sizeof( byte ));

	pe->movetype = ent->curstate.movetype;
	pe->takedamage = ( pe->player ) ? DAMAGE_AIM : DAMAGE_YES;
	pe->team = ent->curstate.team;
	pe->classnumber = ent->curstate.playerclass;
	pe->blooddecal = 0;	// unused in GoldSrc

	// for mods
	pe->iuser1 = ent->curstate.iuser1;
	pe->iuser2 = ent->curstate.iuser2;
	pe->iuser3 = ent->curstate.iuser3;
	pe->iuser4 = ent->curstate.iuser4;
	pe->fuser1 = ent->curstate.fuser1;
	pe->fuser2 = ent->curstate.fuser2;
	pe->fuser3 = ent->curstate.fuser3;
	pe->fuser4 = ent->curstate.fuser4;

	VectorCopy( ent->curstate.vuser1, pe->vuser1 );
	VectorCopy( ent->curstate.vuser2, pe->vuser2 );
	VectorCopy( ent->curstate.vuser3, pe->vuser3 );
	VectorCopy( ent->curstate.vuser4, pe->vuser4 );

	return true;
}