示例#1
0
/*
* CG_Event_Pain
*/
void CG_Event_Pain( entity_state_t *state, int parm )
{
	if( parm == PAIN_WARSHELL )
	{
		if( ISVIEWERENTITY( state->number ) )
			trap_S_StartGlobalSound( CG_MediaSfx( cgs.media.sfxShellHit ), CHAN_PAIN, cg_volume_players->value );
		else
			trap_S_StartRelativeSound( CG_MediaSfx( cgs.media.sfxShellHit ), state->number, CHAN_PAIN, cg_volume_players->value, ATTN_NORM );
	}
	else
	{
		CG_SexedSound( state->number, CHAN_PAIN, va( S_PLAYER_PAINS, 25*( parm+1 ) ), cg_volume_players->value );
	}

	switch( (int)brandom( 0, 3 ) )
	{
	case 0:
		CG_PModel_AddAnimation( state->number, 0, TORSO_PAIN1, 0, EVENT_CHANNEL );
		break;
	case 1:
		CG_PModel_AddAnimation( state->number, 0, TORSO_PAIN2, 0, EVENT_CHANNEL );
		break;
	case 2:
	default:
		CG_PModel_AddAnimation( state->number, 0, TORSO_PAIN3, 0, EVENT_CHANNEL );
		break;
	}
}
示例#2
0
//==============
// CG_ForceTeam
//==============
static int CG_ForceTeam( int entNum, int team )
{
	if( !GS_TeamBasedGametype() )
	{
		if( ISVIEWERENTITY( entNum ) )
		{
			if( cg_forceMyTeamAlpha->integer )
				return TEAM_ALPHA;
		}
		else
		{
			if( cg_forceTeamPlayersTeamBeta->integer )
				return TEAM_BETA;
		}

		return team;
	}
	else
	{
		int myteam = cg.predictedPlayerState.stats[STAT_TEAM];

		if( cg_forceMyTeamAlpha->integer && myteam != TEAM_SPECTATOR )
		{
			if( team == myteam )
				return TEAM_ALPHA;
			if( team == TEAM_ALPHA )
				return myteam;
		}

		return team;
	}
}
示例#3
0
/*
* CG_Event_Dash
*/
void CG_Event_Dash( entity_state_t *state, int parm )
{
	switch( parm )
	{
	default:
		break;
	case 0: // dash front
		CG_PModel_AddAnimation( state->number, LEGS_DASH, 0, 0, EVENT_CHANNEL );
		CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_DASH_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
		break;
	case 1: // dash left
		CG_PModel_AddAnimation( state->number, LEGS_DASH_LEFT, 0, 0, EVENT_CHANNEL );
		CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_DASH_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
		break;
	case 2: // dash right
		CG_PModel_AddAnimation( state->number, LEGS_DASH_RIGHT, 0, 0, EVENT_CHANNEL );
		CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_DASH_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
		break;
	case 3: // dash back
		CG_PModel_AddAnimation( state->number, LEGS_DASH_BACK, 0, 0, EVENT_CHANNEL );
		CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_DASH_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
		break;
	}
	CG_Dash( state ); // Dash smoke effect
	// since most dash animations jump with right leg, reset the jump to start with left leg after a dash
	cg_entities[state->number].jumpedLeft = qtrue;

  //racesow - lm: filter out other players
  if( ISVIEWERENTITY( state->number ))
    CG_AddJumpspeed();
  //!racesow
}
示例#4
0
/*
* CG_Event_WallJump
*/
void CG_Event_WallJump( entity_state_t *state, int parm, int ev )
{
	vec3_t normal, forward, right;

	ByteToDir( parm, normal );

	AngleVectors( tv( state->angles[0], state->angles[1], 0 ), forward, right, NULL );

	if( DotProduct( normal, right ) > 0.3 )
		CG_PModel_AddAnimation( state->number, LEGS_WALLJUMP_RIGHT, 0, 0, EVENT_CHANNEL );
	else if( -DotProduct( normal, right ) > 0.3 )
		CG_PModel_AddAnimation( state->number, LEGS_WALLJUMP_LEFT, 0, 0, EVENT_CHANNEL );
	else if( -DotProduct( normal, forward ) > 0.3 )
		CG_PModel_AddAnimation( state->number, LEGS_WALLJUMP_BACK, 0, 0, EVENT_CHANNEL );
	else
		CG_PModel_AddAnimation( state->number, LEGS_WALLJUMP, 0, 0, EVENT_CHANNEL );

	if( ev == EV_WALLJUMP_FAILED )
	{
		if( ISVIEWERENTITY( state->number ) )
			trap_S_StartGlobalSound( CG_MediaSfx( cgs.media.sfxWalljumpFailed ), CHAN_BODY, cg_volume_effects->value );
		else
			trap_S_StartRelativeSound( CG_MediaSfx( cgs.media.sfxWalljumpFailed ), state->number, CHAN_BODY, cg_volume_effects->value, ATTN_NORM );
	}
	else
	{
		CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_WALLJUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
	
		// smoke effect
		if( cg_cartoonEffects->integer & 1 )
		{
			vec3_t pos;
			VectorCopy( state->origin, pos );
			pos[2] += 15;
			CG_DustCircle( pos, normal, 65, 12 );
		}
	}

  //racesow - lm: filter out other players
  if( ISVIEWERENTITY( state->number ))
    CG_AddJumpspeed();
  //!racesow
}
示例#5
0
/*
* CG_PModel_SpawnTeleportEffect
*/
void CG_PModel_SpawnTeleportEffect( centity_t *cent )
{
	int j;
	cgs_skeleton_t *skel;
	lentity_t *le;
	vec3_t teleportOrigin;
	vec3_t rgb;

	skel = CG_SkeletonForModel( cent->ent.model );
	if( !skel || !cent->ent.boneposes )
		return;

	for( j = LOCALEFFECT_EV_PLAYER_TELEPORT_IN; j <= LOCALEFFECT_EV_PLAYER_TELEPORT_OUT; j++ )
	{
		if( cent->localEffects[j] )
		{
			cent->localEffects[j] = 0;

			VectorSet( rgb, 0.5, 0.5, 0.5 );
			if( j == LOCALEFFECT_EV_PLAYER_TELEPORT_OUT )
			{
				VectorCopy( cent->teleportedFrom, teleportOrigin );
			}
			else
			{
				VectorCopy( cent->teleportedTo, teleportOrigin );
				if( ISVIEWERENTITY( cent->current.number ) ) {
					VectorSet( rgb, 0.1, 0.1, 0.1 );
				}
			}

			// spawn a dummy model
			le = CG_AllocModel( LE_RGB_FADE, teleportOrigin, vec3_origin, 10, 
				rgb[0], rgb[1], rgb[2], 1, 0, 0, 0, 0, cent->ent.model, 
				CG_MediaShader( cgs.media.shaderTeleportShellGfx ) );

			if( cent->skel ) {
				// use static bone pose, no animation
				le->skel = cent->skel;
				le->static_boneposes = ( bonepose_t * )CG_Malloc( sizeof( bonepose_t ) * le->skel->numBones );
				memcpy( le->static_boneposes, cent->ent.boneposes, sizeof( bonepose_t ) * le->skel->numBones );
				le->ent.boneposes = le->static_boneposes;
				le->ent.oldboneposes = le->ent.boneposes;
			}

			le->ent.frame = cent->ent.frame;
			le->ent.oldframe = cent->ent.oldframe;
			le->ent.backlerp = 1.0f;
			Matrix3_Copy( cent->ent.axis, le->ent.axis );
		}
	}
}
示例#6
0
/*
* CG_Event_Jump
*/
void CG_Event_Jump( entity_state_t *state, int parm )
{
#define MOVEDIREPSILON 0.25f
	centity_t *cent;
	int xyspeedcheck;

	cent = &cg_entities[state->number];
	xyspeedcheck = SQRTFAST( cent->animVelocity[0]*cent->animVelocity[0] + cent->animVelocity[1]*cent->animVelocity[1] );
	if( xyspeedcheck < 100 )
	{                      // the player is jumping on the same place, not running
		CG_PModel_AddAnimation( state->number, LEGS_JUMP_NEUTRAL, 0, 0, EVENT_CHANNEL );
		CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
	}
	else
	{
		vec3_t movedir, viewaxis[3];
		movedir[0] = cent->animVelocity[0];
		movedir[1] = cent->animVelocity[1];
		movedir[2] = 0;
		VectorNormalizeFast( movedir );
		AngleVectors( tv( 0, cent->current.angles[YAW], 0 ), viewaxis[FORWARD], viewaxis[RIGHT], viewaxis[UP] );
		// see what's his relative movement direction
		if( DotProduct( movedir, viewaxis[FORWARD] ) > MOVEDIREPSILON )
		{
			cent->jumpedLeft = !cent->jumpedLeft;
			if( !cent->jumpedLeft )
			{
				CG_PModel_AddAnimation( state->number, LEGS_JUMP_LEG2, 0, 0, EVENT_CHANNEL );
				CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
			}
			else
			{
				CG_PModel_AddAnimation( state->number, LEGS_JUMP_LEG1, 0, 0, EVENT_CHANNEL );
				CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
			}
		}
		else
		{
			CG_PModel_AddAnimation( state->number, LEGS_JUMP_NEUTRAL, 0, 0, EVENT_CHANNEL );
			CG_SexedSound( state->number, CHAN_BODY, va( S_PLAYER_JUMP_1_to_2, ( rand()&1 )+1 ), cg_volume_players->value );
		}
	}
#undef MOVEDIREPSILON

  //racesow - lm: filter out other players
  if( ISVIEWERENTITY( state->number ))
    CG_AddJumpspeed();
  //!racesow
}
示例#7
0
/*
* CG_CalcViewBob
*/
static void CG_CalcViewBob( void )
{
	float bobMove, bobTime, bobScale;

	if( !cg.view.drawWeapon )
		return;

	// calculate speed and cycle to be used for all cyclic walking effects
	cg.xyspeed = sqrt( cg.predictedPlayerState.pmove.velocity[0]*cg.predictedPlayerState.pmove.velocity[0] + cg.predictedPlayerState.pmove.velocity[1]*cg.predictedPlayerState.pmove.velocity[1] );

	bobScale = 0;
	if( cg.xyspeed < 5 )
		cg.oldBobTime = 0;  // start at beginning of cycle again
	else if( cg_gunbob->integer )
	{
		if( !ISVIEWERENTITY( cg.view.POVent ) )
			bobScale = 0.0f;
		else if( CG_PointContents( cg.view.origin ) & MASK_WATER )
			bobScale =  0.75f;
		else
		{
			centity_t *cent;
			vec3_t mins, maxs;
			trace_t	trace;

			cent = &cg_entities[cg.view.POVent];
			GS_BBoxForEntityState( &cent->current, mins, maxs );
			maxs[2] = mins[2];
			mins[2] -= ( 1.6f*STEPSIZE );

			CG_Trace( &trace, cg.predictedPlayerState.pmove.origin, mins, maxs, cg.predictedPlayerState.pmove.origin, cg.view.POVent, MASK_PLAYERSOLID );
			if( trace.startsolid || trace.allsolid )
			{
				if( cg.predictedPlayerState.pmove.stats[PM_STAT_CROUCHTIME] )
					bobScale = 1.5f;
				else
					bobScale = 2.5f;
			}
		}
	}

	bobMove = cg.frameTime * bobScale;
	bobTime = ( cg.oldBobTime += bobMove );

	cg.bobCycle = (int)bobTime;
	cg.bobFracSin = fabs( sin( bobTime*M_PI ) );
}
示例#8
0
/*
* SCR_DrawPlayerTab
*/
static int SCR_DrawPlayerTab( const char **ptrptr, int team, int x, int y, int panelWidth, struct qfontface_s *font, int pass )
{
	int dir, align, i, columncount;
	char type, string[MAX_STRING_CHARS];
	const char *token, *layout;
	int height, width, xoffset, yoffset;
	vec4_t teamcolor = { 0.0f, 0.0f, 0.0f, 1.0f }, color;
	int iconnum;
	struct shader_s *icon;
	bool highlight = false, trans = false;

	if( GS_TeamBasedGametype() )
	{
		dir = ( team == TEAM_ALPHA ) ? -1 : 1;
		align = ( team == TEAM_ALPHA ) ? ALIGN_RIGHT_TOP : ALIGN_LEFT_TOP;
	}
	else
	{
		dir = 0;
		align = ALIGN_CENTER_TOP;
	}

	xoffset = 0;
	yoffset = 0;

	height = trap_SCR_FontHeight( font );

	// start from the center again
	xoffset = CG_HorizontalAlignForWidth( 0, align, panelWidth );
	xoffset += ( SCB_CENTERMARGIN * dir );

	// draw the background
	columncount = 0;
	if( ( team == TEAM_ALPHA ) || ( team == TEAM_BETA ) )
		CG_TeamColor( team, teamcolor );

	// draw the player tab column titles
	layout = cgs.configStrings[CS_SCB_PLAYERTAB_LAYOUT];

	while( SCR_GetNextColumnLayout( &layout, NULL, &type, &width, font ) != NULL )
	{
		// grab the actual scoreboard data
		if( !SCR_ParseToken( ptrptr, &token ) )
			break;

		if( SCR_SkipColumn( type ) )
			continue;

		Vector4Copy( colorWhite, color ); // reset to white after each column
		icon = NULL;
		string[0] = 0;

		// interpret the data based on the type defined in the layout
		switch( type )
		{
		default:
			CG_Error( "SCR_DrawPlayerTab: Invalid player tab layout\n" );
			break;

		case 's': // is a string
			{
				char l10n[MAX_STRING_CHARS];
				Q_strncpyz( string, CG_TranslateColoredString( token, l10n, sizeof( l10n ) ), sizeof( string ) );
			}
			break;

		case 'n': // is a player name indicated by player number
			i = atoi( token );

			if( i < 0 ) // negative numbers toggle transparency on
			{
				trans = true;
				i = -1 - i;
			}

			if( i < 0 || i >= gs.maxclients )
				Q_strncpyz( string, "invalid", sizeof( string ) );
			else
				Q_strncpyz( string, cgs.clientInfo[i].name, sizeof( string ) );

			if( ISVIEWERENTITY( i + 1 ) ) // highlight if it's our own player
				highlight = true;

			break;
		case 'i': // is a integer (negatives are colored in red)
			i = atoi( token );
			Q_snprintfz( string, sizeof( string ), "%i", i );
			VectorCopy( i >= 0 ? colorWhite : colorRed, color );
			break;

		case 'f': // is a float
			Q_snprintfz( string, sizeof( string ), "%.2f", atof( token ) );
			break;

		case 'l': // p is an integer colored in latency style
			i = atoi( token );
			Q_snprintfz( string, sizeof( string ), "%i", i );
			CG_PingColor( i, color );
			break;

		case 'b': // is a Y/N boolean
			i = atoi( token );
			Q_snprintfz( string, sizeof( string ), "%s", CG_TranslateString( ( i != 0 ) ? "Yes" : "No" ) );
			VectorCopy( i ? colorGreen : colorRed, color );
			break;

		case 'p': // is a picture. It uses height for width to get a square
			iconnum = atoi( token );
			if( ( iconnum > 0 ) && ( iconnum < MAX_IMAGES ) )
				icon = cgs.imagePrecache[iconnum];
			break;

		case 't': // is a race time. Convert time into MM:SS:mm
			{
				unsigned int milli, min, sec;

				milli = (unsigned int)( atoi( token ) );
				if( !milli )
					Q_snprintfz( string, sizeof( string ), CG_TranslateString( "no time" ) );
				else
				{
					min = milli / 60000;
					milli -= min * 60000;
					sec = milli / 1000;
					milli -= sec * 1000;
					Q_snprintfz( string, sizeof( string ), va( "%02i:%02i.%03i", min, sec, milli ) );
				}
			}
			break;

		case 'r': // is a ready state tick that is hidden when not in warmup
			if( atoi( token ) )
				icon = CG_MediaShader( cgs.media.shaderVSayIcon[VSAY_YES] );
			break;
		}

		if( !width )
			continue;

		// draw the column background
		teamcolor[3] = SCB_BACKGROUND_ALPHA;
		if( columncount & 1 )
			teamcolor[3] -= 0.15;

		if( highlight )
			teamcolor[3] += 0.3;

		if( trans )
			color[3] = 0.3;

		if( !pass ) {
			trap_R_DrawStretchPic( x + xoffset, y + yoffset, width, height, 0, 0, 1, 1, teamcolor, cgs.shaderWhite );

			if( icon )
				SCR_AddPlayerIcon( icon, x + xoffset, y + yoffset, color[3], font );
		}

		// draw the column value
		if( pass && string[0] )
		{
			trap_SCR_DrawClampString( x + xoffset, y + yoffset, string,
				x + xoffset, y + yoffset,
				x + xoffset + width, y + yoffset + height, font, color );
		}

		columncount++;

		xoffset += width;
	}

	yoffset += height;
	return yoffset;
}
示例#9
0
/*
* CG_BulletExplosion
*/
void CG_BulletExplosion( vec3_t pos, vec_t *dir, trace_t *trace )
{
	lentity_t *le;
	vec3_t angles;
	vec3_t local_dir, end;
	trace_t	local_trace, *tr;

	assert( dir || trace );

	if( dir )
	{
		// find what are we hitting
		tr = &local_trace;
		VectorMA( pos, -1.0, dir, end );
		CG_Trace( tr, pos, vec3_origin, vec3_origin, end, cg.view.POVent, MASK_SHOT );
		if( tr->fraction == 1.0 )
			return;
	}
	else
	{
		tr = trace;
		dir = local_dir;
		VectorCopy( tr->plane.normal, dir );
	}

	VecToAngles( dir, angles );

	if( tr->surfFlags & SURF_FLESH ||
		( tr->ent > 0 && cg_entities[tr->ent].current.type == ET_PLAYER ) ||
		( tr->ent > 0 && cg_entities[tr->ent].current.type == ET_CORPSE ) )
	{
		le = CG_AllocModel( LE_ALPHA_FADE, pos, angles, 3, //3 frames for weak
			1, 0, 0, 1, //full white no inducted alpha
			0, 0, 0, 0, //dlight
			CG_MediaModel( cgs.media.modBulletExplode ),
			NULL );
		le->ent.rotation = rand() % 360;
		le->ent.scale = 1.0f;
		if( ISVIEWERENTITY( tr->ent ) )
			le->ent.renderfx |= RF_VIEWERMODEL;
	}
	else if( tr->surfFlags & SURF_DUST )
	{
		// throw particles on dust
		CG_ImpactSmokePuff( tr->endpos, tr->plane.normal, 4, 0.6f, 6, 8 );
	}
	else
	{
		le = CG_AllocModel( LE_ALPHA_FADE, pos, angles, 3, //3 frames for weak
			1, 1, 1, 1, //full white no inducted alpha
			0, 0, 0, 0, //dlight
			CG_MediaModel( cgs.media.modBulletExplode ),
			NULL );
		le->ent.rotation = rand() % 360;
		le->ent.scale = 1.0f;

		CG_ImpactSmokePuff( tr->endpos, tr->plane.normal, 2, 0.6f, 6, 8 );

		if( !( tr->surfFlags & SURF_NOMARKS ) )
			CG_SpawnDecal( pos, dir, random()*360, 8, 1, 1, 1, 1, 10, 1, qfalse, CG_MediaShader( cgs.media.shaderBulletMark ) );
	}
}
示例#10
0
/*
* CG_Event_Fall
*/
void CG_Event_Fall( entity_state_t *state, int parm )
{
	if( ISVIEWERENTITY( state->number ) )
	{
		if( cg.frame.playerState.pmove.pm_type != PM_NORMAL )
		{
			CG_SexedSound( state->number, CHAN_AUTO, "*fall_0", cg_volume_players->value );
			return;
		}

		CG_ViewWeapon_StartFallKickEff( parm );

		if( parm > 0 )
			CG_DamageIndicatorAdd( parm, tv( 0, 0, 1 ) );
	}

	if( parm > 10 )
	{
		CG_SexedSound( state->number, CHAN_PAIN, "*fall_2", cg_volume_players->value );
		switch( (int)brandom( 0, 3 ) )
		{
		case 0:
			CG_PModel_AddAnimation( state->number, 0, TORSO_PAIN1, 0, EVENT_CHANNEL );
			break;
		case 1:
			CG_PModel_AddAnimation( state->number, 0, TORSO_PAIN2, 0, EVENT_CHANNEL );
			break;
		case 2:
		default:
			CG_PModel_AddAnimation( state->number, 0, TORSO_PAIN3, 0, EVENT_CHANNEL );
			break;
		}
	}
	else if( parm > 0 )
	{
		CG_SexedSound( state->number, CHAN_PAIN, "*fall_1", cg_volume_players->value );
	}
	else
		CG_SexedSound( state->number, CHAN_PAIN, "*fall_0", cg_volume_players->value );

	// smoke effect
	if( parm > 0 && ( cg_cartoonEffects->integer & 2 ) )
	{
		vec3_t start, end;
		trace_t trace;

		if( ISVIEWERENTITY( state->number ) )
			VectorCopy( cg.predictedPlayerState.pmove.origin, start );
		else
			VectorCopy( state->origin, start );

		VectorCopy( start, end );
		end[2] += playerbox_stand_mins[2] - 48.0f;

		CG_Trace( &trace, start, vec3_origin, vec3_origin, end, state->number, MASK_PLAYERSOLID );
		if( trace.ent == -1 )
		{
			start[2] += playerbox_stand_mins[2] + 8;
			CG_DustCircle( start, tv( 0, 0, 1 ), 50, 12 );
		}
		else if( !(trace.surfFlags & SURF_NODAMAGE) )
		{
			VectorMA( trace.endpos, 8, trace.plane.normal, end );
			CG_DustCircle( end, trace.plane.normal, 50, 12 );
		}
	}
}
示例#11
0
/*
* CG_FireWeaponEvent
*/
static void CG_FireWeaponEvent( int entNum, int weapon, int fireMode )
{
	float attenuation;
	struct sfx_s *sound = NULL;
	weaponinfo_t *weaponInfo;

	if( !weapon )
		return;

	// hack idle attenuation on the plasmagun to reduce sound flood on the scene
	if( weapon == WEAP_PLASMAGUN )
		attenuation = ATTN_IDLE;
	else
		attenuation = ATTN_NORM;

	weaponInfo = CG_GetWeaponInfo( weapon );

	// sound
	if( fireMode == FIRE_MODE_STRONG )
	{
		if( weaponInfo->num_strongfire_sounds )
			sound = weaponInfo->sound_strongfire[(int)brandom( 0, weaponInfo->num_strongfire_sounds )];
	}
	else
	{
		if( weaponInfo->num_fire_sounds )
			sound = weaponInfo->sound_fire[(int)brandom( 0, weaponInfo->num_fire_sounds )];
	}

	if( sound )
	{
		if( ISVIEWERENTITY( entNum ) )
			trap_S_StartGlobalSound( sound, CHAN_MUZZLEFLASH, cg_volume_effects->value );
		else
			// fixed position is better for location, but the channels are used from worldspawn
			// and openal runs out of channels quick on cheap cards. Relative sound uses per-entity channels.
			trap_S_StartRelativeSound( sound, entNum, CHAN_MUZZLEFLASH, cg_volume_effects->value, attenuation );

		if( ( cg_entities[entNum].current.effects & EF_QUAD ) && ( weapon != WEAP_LASERGUN ) )
		{
			struct sfx_s *quadSfx = CG_MediaSfx( cgs.media.sfxQuadFireSound );
			if( ISVIEWERENTITY( entNum ) )
				trap_S_StartGlobalSound( quadSfx, CHAN_AUTO, cg_volume_effects->value );
			else
				trap_S_StartRelativeSound( quadSfx, entNum, CHAN_AUTO, cg_volume_effects->value, attenuation );
		}
	}

	// flash and barrel effects
	
	if( weapon == WEAP_GUNBLADE ) // gunblade is special
	{
		if( fireMode == FIRE_MODE_STRONG )
		{
			// light flash
			if( cg_weaponFlashes->integer && weaponInfo->flashTime )
				cg_entPModels[entNum].flash_time = cg.time + weaponInfo->flashTime;
		}
		else
		{
			// start barrel rotation or offsetting
			if( weaponInfo->barrelTime )
				cg_entPModels[entNum].barrel_time = cg.time + weaponInfo->barrelTime;
		}
	}
	else
	{
		// light flash
		if( cg_weaponFlashes->integer && weaponInfo->flashTime )
			cg_entPModels[entNum].flash_time = cg.time + weaponInfo->flashTime;

		// start barrel rotation or offsetting
		if( weaponInfo->barrelTime )
			cg_entPModels[entNum].barrel_time = cg.time + weaponInfo->barrelTime;
	}

	// add animation to the player model
	switch( weapon )
	{
	case WEAP_NONE:
		break;

	case WEAP_GUNBLADE:
		if( fireMode == FIRE_MODE_WEAK )
			CG_PModel_AddAnimation( entNum, 0, TORSO_SHOOT_BLADE, 0, EVENT_CHANNEL );
		else
			CG_PModel_AddAnimation( entNum, 0, TORSO_SHOOT_PISTOL, 0, EVENT_CHANNEL );
		break;

	case WEAP_LASERGUN:
		CG_PModel_AddAnimation( entNum, 0, TORSO_SHOOT_PISTOL, 0, EVENT_CHANNEL );
		break;

	default:
	case WEAP_RIOTGUN:
	case WEAP_PLASMAGUN:
		CG_PModel_AddAnimation( entNum, 0, TORSO_SHOOT_LIGHTWEAPON, 0, EVENT_CHANNEL );
		break;

	case WEAP_ROCKETLAUNCHER:
	case WEAP_GRENADELAUNCHER:
		CG_PModel_AddAnimation( entNum, 0, TORSO_SHOOT_HEAVYWEAPON, 0, EVENT_CHANNEL );
		break;

	case WEAP_ELECTROBOLT:
		CG_PModel_AddAnimation( entNum, 0, TORSO_SHOOT_AIMWEAPON, 0, EVENT_CHANNEL );
		break;
	}

	// add animation to the view weapon model
	if( ISVIEWERENTITY( entNum ) && !cg.view.thirdperson )
		CG_ViewWeapon_StartAnimationEvent( fireMode == FIRE_MODE_STRONG ? WEAPMODEL_ATTACK_STRONG : WEAPMODEL_ATTACK_WEAK );
}
示例#12
0
void CG_LaserBeamEffect( centity_t *cent )
{
	struct sfx_s *sound = NULL;
	float range;
	trace_t trace;
	orientation_t projectsource;
	vec4_t color;
	vec3_t laserOrigin, laserAngles, laserPoint;
	int i, j;

	if( cent->localEffects[LOCALEFFECT_LASERBEAM] <= cg.time )
		return;

	laserOwner = cent;

	if( cg_teamColoredBeams->integer && ( cent->current.team == TEAM_ALPHA || cent->current.team == TEAM_BETA ) )
		CG_TeamColor( cent->current.team, color );
	else
		Vector4Set( color, 1, 1, 1, 1 );

	// interpolate the positions

	if( ISVIEWERENTITY( cent->current.number ) && !cg.view.thirdperson )
	{
		VectorCopy( cg.predictedPlayerState.pmove.origin, laserOrigin );
		laserOrigin[2] += cg.predictedPlayerState.viewheight;
		VectorCopy( cg.predictedPlayerState.viewangles, laserAngles );

		VectorLerp( cent->laserPointOld, cg.lerpfrac, cent->laserPoint, laserPoint );
	}
	else
	{
		VectorLerp( cent->laserOriginOld, cg.lerpfrac, cent->laserOrigin, laserOrigin );
		VectorLerp( cent->laserPointOld, cg.lerpfrac, cent->laserPoint, laserPoint );
		if( !cent->laserCurved )
		{
			vec3_t dir;

			// make up the angles from the start and end points (s->angles is not so precise)
			VectorSubtract( laserPoint, laserOrigin, dir );
			VecToAngles( dir, laserAngles );
		}
		else // use player entity angles
		{
			for( i = 0; i < 3; i++ )
				laserAngles[i] = LerpAngle( cent->prev.angles[i], cent->current.angles[i], cg.lerpfrac );
		}
	}

	if( !cent->laserCurved )
	{
		range = GS_GetWeaponDef( WEAP_LASERGUN )->firedef.timeout;

		if( cent->current.effects & EF_QUAD )
			sound = CG_MediaSfx( cgs.media.sfxLasergunStrongQuadHum );
		else
			sound = CG_MediaSfx( cgs.media.sfxLasergunStrongHum );

		// trace the beam: for tracing we use the real beam origin
		GS_TraceLaserBeam( &trace, laserOrigin, laserAngles, range, cent->current.number, 0, _LaserImpact );
		
		// draw the beam: for drawing we use the weapon projection source (already handles the case of viewer entity)
		if( !CG_PModel_GetProjectionSource( cent->current.number, &projectsource ) )
			VectorCopy( laserOrigin, projectsource.origin );

		CG_KillPolyBeamsByTag( cent->current.number );
		CG_LaserGunPolyBeam( projectsource.origin, trace.endpos, color, cent->current.number );
	}
	else
	{
		float frac, subdivisions = cg_laserBeamSubdivisions->integer;
		vec3_t from, dir, end, blendPoint;
		int passthrough = cent->current.number;
		vec3_t tmpangles, blendAngles;

		range = GS_GetWeaponDef( WEAP_LASERGUN )->firedef_weak.timeout;

		if( cent->current.effects & EF_QUAD )
			sound = CG_MediaSfx( cgs.media.sfxLasergunWeakQuadHum );
		else
			sound = CG_MediaSfx( cgs.media.sfxLasergunWeakHum );

		// trace the beam: for tracing we use the real beam origin
		GS_TraceCurveLaserBeam( &trace, laserOrigin, laserAngles, laserPoint, cent->current.number, 0, _LaserImpact );

		// draw the beam: for drawing we use the weapon projection source (already handles the case of viewer entity)
		if( !CG_PModel_GetProjectionSource( cent->current.number, &projectsource ) )
			VectorCopy( laserOrigin, projectsource.origin );

		if( subdivisions < CURVELASERBEAM_SUBDIVISIONS )
			subdivisions = CURVELASERBEAM_SUBDIVISIONS;

		CG_KillPolyBeamsByTag( cent->current.number );

		// we redraw the full beam again, and trace each segment for stop dead impact
		VectorCopy( laserPoint, blendPoint );
		VectorCopy( projectsource.origin, from );
		VectorSubtract( blendPoint, projectsource.origin, dir );
		VecToAngles( dir, blendAngles );

		for( i = 1; i <= (int)subdivisions; i++ )
		{
			frac = ( ( range/subdivisions )*(float)i ) / (float)range;

			for( j = 0; j < 3; j++ )
				tmpangles[j] = LerpAngle( laserAngles[j], blendAngles[j], frac );

			AngleVectors( tmpangles, dir, NULL, NULL );
			VectorMA( projectsource.origin, range * frac, dir, end );

			GS_TraceLaserBeam( &trace, from, tmpangles, DistanceFast( from, end ), passthrough, 0, NULL );
			CG_LaserGunPolyBeam( from, trace.endpos, color, cent->current.number );
			if( trace.fraction != 1.0f )
				break;

			passthrough = trace.ent;
			VectorCopy( trace.endpos, from );
		}
	}

	// enable continuous flash on the weapon owner
	if( cg_weaponFlashes->integer )
		cg_entPModels[cent->current.number].flash_time = cg.time + CG_GetWeaponInfo( WEAP_LASERGUN )->flashTime;

	if( sound )
	{
		if( ISVIEWERENTITY( cent->current.number ) )
			trap_S_AddLoopSound( sound, cent->current.number, 1.0, ATTN_NONE );
		else
			trap_S_AddLoopSound( sound, cent->current.number, 1.0, ATTN_STATIC );
	}

	laserOwner = NULL;
}
示例#13
0
/*
* CG_EntityEvent
*/
void CG_EntityEvent( entity_state_t *ent, int ev, int parm, qboolean predicted )
{
	//static orientation_t projection;
	vec3_t dir;
	qboolean viewer = ISVIEWERENTITY( ent->number );
	vec4_t color;
	int weapon = 0, fireMode = 0, count = 0;

	if( viewer && ( ev < PREDICTABLE_EVENTS_MAX ) && ( predicted != cg.view.playerPrediction ) )
		return;

	switch( ev )
	{
	case EV_NONE:
	default:
		break;

	//  PREDICTABLE EVENTS

	case EV_WEAPONACTIVATE:
		CG_PModel_AddAnimation( ent->number, 0, TORSO_WEAPON_SWITCHIN, 0, EVENT_CHANNEL );
		weapon = ( parm & ~EV_INVERSE );
		fireMode = ( parm & EV_INVERSE ) ? FIRE_MODE_STRONG : FIRE_MODE_WEAK;
		if( predicted )
		{
			cg_entities[ent->number].current.weapon = weapon;
			if( fireMode == FIRE_MODE_STRONG )
				cg_entities[ent->number].current.effects |= EF_STRONG_WEAPON;

			CG_ViewWeapon_RefreshAnimation( &cg.weapon );
		}

		if( viewer )
			cg.predictedWeaponSwitch = 0;

		if( viewer )
			trap_S_StartGlobalSound( CG_MediaSfx( cgs.media.sfxWeaponUp ), CHAN_AUTO, cg_volume_effects->value );
		else
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxWeaponUp ), ent->origin, CHAN_AUTO, cg_volume_effects->value, ATTN_NORM );
		break;

	case EV_SMOOTHREFIREWEAPON: // the server never sends this event
		if( predicted )
		{
			weapon = ( parm & ~EV_INVERSE );
			fireMode = ( parm & EV_INVERSE ) ? FIRE_MODE_STRONG : FIRE_MODE_WEAK;

			cg_entities[ent->number].current.weapon = weapon;
			if( fireMode == FIRE_MODE_STRONG )
				cg_entities[ent->number].current.effects |= EF_STRONG_WEAPON;

			CG_ViewWeapon_RefreshAnimation( &cg.weapon );

			if( weapon == WEAP_LASERGUN )
				CG_Event_LaserBeam( ent->number, weapon, fireMode );
		}
		break;

	case EV_FIREWEAPON:
		weapon = ( parm & ~EV_INVERSE );
		fireMode = ( parm & EV_INVERSE ) ? FIRE_MODE_STRONG : FIRE_MODE_WEAK;

		if( predicted )
		{
			cg_entities[ent->number].current.weapon = weapon;
			if( fireMode == FIRE_MODE_STRONG )
				cg_entities[ent->number].current.effects |= EF_STRONG_WEAPON;
		}

		CG_FireWeaponEvent( ent->number, weapon, fireMode );
		
		// riotgun bullets, electrobolt and instagun beams are predicted when the weapon is fired
		if( predicted )
		{
			vec3_t origin;

			if( ( weapon == WEAP_ELECTROBOLT 
#ifndef ELECTROBOLT_TEST
				&& fireMode == FIRE_MODE_STRONG
#endif
				) 
				|| weapon == WEAP_INSTAGUN )
			{
				VectorCopy( cg.predictedPlayerState.pmove.origin, origin );
				origin[2] += cg.predictedPlayerState.viewheight;
				AngleVectors( cg.predictedPlayerState.viewangles, dir, NULL, NULL );
				CG_Event_WeaponBeam( origin, dir, cg.predictedPlayerState.POVnum, weapon, fireMode );
			}
			else if( weapon == WEAP_RIOTGUN || weapon == WEAP_MACHINEGUN )
			{
				int seed = cg.predictedEventTimes[EV_FIREWEAPON] & 255;

				VectorCopy( cg.predictedPlayerState.pmove.origin, origin );
				origin[2] += cg.predictedPlayerState.viewheight;
				AngleVectors( cg.predictedPlayerState.viewangles, dir, NULL, NULL );

				if( weapon == WEAP_RIOTGUN )
					CG_Event_FireRiotgun( origin, dir, weapon, fireMode, seed, cg.predictedPlayerState.POVnum );
				else
					CG_Event_FireMachinegun( origin, dir, weapon, fireMode, seed, cg.predictedPlayerState.POVnum );
			}
			else if( weapon == WEAP_LASERGUN )
			{
				CG_Event_LaserBeam( ent->number, weapon, fireMode );
			}
		}
		break;

	case EV_ELECTROTRAIL:
		// check the owner for predicted case
		if( ISVIEWERENTITY( parm ) && ( ev < PREDICTABLE_EVENTS_MAX ) && ( predicted != cg.view.playerPrediction ) )
			return;
		CG_Event_WeaponBeam( ent->origin, ent->origin2, parm, WEAP_ELECTROBOLT, ent->firemode );
		break;

	case EV_INSTATRAIL:
		// check the owner for predicted case
		if( ISVIEWERENTITY( parm ) && ( ev < PREDICTABLE_EVENTS_MAX ) && ( predicted != cg.view.playerPrediction ) )
			return;
		CG_Event_WeaponBeam( ent->origin, ent->origin2, parm, WEAP_INSTAGUN, FIRE_MODE_STRONG );
		break;

	case EV_FIRE_RIOTGUN:
	case EV_FIRE_BULLET:
		{
			// check the owner for predicted case
			if( ISVIEWERENTITY( ent->ownerNum ) && ( ev < PREDICTABLE_EVENTS_MAX ) && ( predicted != cg.view.playerPrediction ) )
				return;

			if( ev == EV_FIRE_RIOTGUN )
				CG_Event_FireRiotgun( ent->origin, ent->origin2, ( ent->weapon & ~EV_INVERSE ),
					( ent->weapon & EV_INVERSE ), parm, ent->ownerNum );
			else
				CG_Event_FireMachinegun( ent->origin, ent->origin2, ( ent->weapon & ~EV_INVERSE ), 
					( ent->weapon & EV_INVERSE ), parm, ent->ownerNum );
		}
		break;

	case EV_NOAMMOCLICK:
		if( viewer )
			trap_S_StartGlobalSound( CG_MediaSfx( cgs.media.sfxWeaponUpNoAmmo ), CHAN_ITEM, cg_volume_effects->value );
		else
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxWeaponUpNoAmmo ), ent->origin, CHAN_ITEM, cg_volume_effects->value, ATTN_IDLE );
		break;

	case EV_DASH:
		CG_Event_Dash( ent, parm );
		break;

	case EV_WALLJUMP:
	case EV_WALLJUMP_FAILED:
		CG_Event_WallJump( ent, parm, ev );
		break;

	case EV_DOUBLEJUMP:
		CG_Event_DoubleJump( ent, parm );
		break;

	case EV_JUMP:
		CG_Event_Jump( ent, parm );
		break;

	case EV_JUMP_PAD:
		CG_TouchJumpPad( ent->number );
		break;

	case EV_FALL:
		CG_Event_Fall( ent, parm );
		break;


		//  NON PREDICTABLE EVENTS

	case EV_WEAPONDROP: // deactivate is not predictable
		CG_PModel_AddAnimation( ent->number, 0, TORSO_WEAPON_SWITCHOUT, 0, EVENT_CHANNEL );
		break;

	case EV_SEXEDSOUND:
		if( parm == 2 )
			CG_SexedSound( ent->number, CHAN_AUTO, S_PLAYER_GASP, cg_volume_players->value );
		else if( parm == 1 )
			CG_SexedSound( ent->number, CHAN_AUTO, S_PLAYER_DROWN, cg_volume_players->value );
		break;

	case EV_PAIN:
		CG_Event_Pain( ent, parm );
		break;

	case EV_DIE:
		CG_Event_Die( ent, parm );
		break;

	case EV_GIB:
		break;

	case EV_EXPLOSION1:
		CG_GenericExplosion( ent->origin, vec3_origin, FIRE_MODE_WEAK, parm * 8 );
		break;

	case EV_EXPLOSION2:
		CG_GenericExplosion( ent->origin, vec3_origin, FIRE_MODE_STRONG, parm * 16 );
		break;

	case EV_GREEN_LASER:
		CG_GreenLaser( ent->origin, ent->origin2 );
		break;

	case EV_PNODE:
		color[0] = COLOR_R( ent->colorRGBA ) * ( 1.0 / 255.0 );
		color[1] = COLOR_G( ent->colorRGBA ) * ( 1.0 / 255.0 );
		color[2] = COLOR_B( ent->colorRGBA ) * ( 1.0 / 255.0 );
		color[3] = COLOR_A( ent->colorRGBA ) * ( 1.0 / 255.0 );
		CG_PLink( ent->origin, ent->origin2, color, parm );
		break;

	case EV_SPARKS:
		ByteToDir( parm, dir );
		if( ent->damage > 0 )
		{
			count = (int)( ent->damage * 0.25f );
			clamp( count, 1, 10 );
		}
		else
			count = 6;

		CG_ParticleEffect( ent->origin, dir, 1.0f, 0.67f, 0.0f, count );
		break;

	case EV_BULLET_SPARKS:
		ByteToDir( parm, dir );
		CG_BulletExplosion( ent->origin, dir, NULL );
		CG_ParticleEffect( ent->origin, dir, 1.0f, 0.67f, 0.0f, 6 );
		trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxRic[rand()&2] ), ent->origin, CHAN_AUTO,
			cg_volume_effects->value, ATTN_STATIC );
		break;

	case EV_LASER_SPARKS:
		ByteToDir( parm, dir );
		CG_ParticleEffect2( ent->origin, dir,
			COLOR_R( ent->colorRGBA ) * ( 1.0 / 255.0 ),
			COLOR_G( ent->colorRGBA ) * ( 1.0 / 255.0 ),
			COLOR_B( ent->colorRGBA ) * ( 1.0 / 255.0 ),
			ent->eventCount );
		break;

	case EV_GESTURE:
		CG_SexedSound( ent->number, CHAN_BODY, "*taunt", cg_volume_players->value );
		break;

	case EV_DROP:
		CG_PModel_AddAnimation( ent->number, 0, TORSO_DROP, 0, EVENT_CHANNEL );
		break;

	case EV_SPOG:
		CG_SmallPileOfGibs( ent->origin, parm, ent->origin2 );
		break;

	case EV_ITEM_RESPAWN:
		cg_entities[ent->number].respawnTime = cg.time;
		trap_S_StartRelativeSound( CG_MediaSfx( cgs.media.sfxItemRespawn ), ent->number, CHAN_AUTO,
			cg_volume_effects->value, ATTN_IDLE );
		break;

	case EV_PLAYER_RESPAWN:
		if( (unsigned)ent->ownerNum == cgs.playerNum + 1 )
		{
			CG_ResetKickAngles();
			CG_ResetColorBlend();
			CG_ResetDamageIndicator();
		}
		// fallthrough
	case EV_PLAYER_TELEPORT_IN:
		if( ISVIEWERENTITY( ent->ownerNum ) )
		{
			trap_S_StartGlobalSound( CG_MediaSfx( cgs.media.sfxTeleportIn ), CHAN_AUTO,
				cg_volume_effects->value );
		}
		else
		{
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxTeleportIn ), ent->origin, CHAN_AUTO,
				cg_volume_effects->value, ATTN_NORM );
		}

		if( ent->ownerNum && ent->ownerNum < gs.maxclients + 1 )
			cg_entities[ent->ownerNum].localEffects[LOCALEFFECT_EV_PLAYER_TELEPORT_IN] = cg.time;
		break;

	case EV_PLAYER_TELEPORT_OUT:
		if( ISVIEWERENTITY( ent->ownerNum ) )
		{
			trap_S_StartGlobalSound( CG_MediaSfx( cgs.media.sfxTeleportOut ), CHAN_AUTO,
				cg_volume_effects->value );
		}
		else
		{
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxTeleportOut ), ent->origin, CHAN_AUTO,
				cg_volume_effects->value, ATTN_NORM );
		}
		if( ent->ownerNum && ent->ownerNum < gs.maxclients + 1 )
		{
			cg_entities[ent->ownerNum].localEffects[LOCALEFFECT_EV_PLAYER_TELEPORT_OUT] = cg.time;
			VectorCopy( ent->origin, cg_entities[ent->ownerNum].teleportedFrom );
		}
		break;

	case EV_PLASMA_EXPLOSION:
		ByteToDir( parm, dir );
		CG_PlasmaExplosion( ent->origin, dir, ent->firemode, (float)ent->weapon * 8.0f );
		if( ent->firemode == FIRE_MODE_STRONG )
		{
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxPlasmaStrongHit ), ent->origin, CHAN_AUTO, cg_volume_effects->value, ATTN_IDLE );
			CG_StartKickAnglesEffect( ent->origin, 50, ent->weapon * 8, 100 );
		}
		else
		{
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxPlasmaWeakHit ), ent->origin, CHAN_AUTO, cg_volume_effects->value, ATTN_IDLE );
			CG_StartKickAnglesEffect( ent->origin, 30, ent->weapon * 8, 75 );
		}
		break;

	case EV_BOLT_EXPLOSION:
		ByteToDir( parm, dir );
		CG_BoltExplosionMode( ent->origin, dir, ent->firemode );
		break;

	case EV_INSTA_EXPLOSION:
		ByteToDir( parm, dir );
		CG_InstaExplosionMode( ent->origin, dir, ent->firemode );
		break;

	case EV_GRENADE_EXPLOSION:
		if( parm )
		{    // we have a direction
			ByteToDir( parm, dir );
			CG_GrenadeExplosionMode( ent->origin, dir, ent->firemode, (float)ent->weapon*8.0f );
		}
		else
		{ // no direction
			CG_GrenadeExplosionMode( ent->origin, vec3_origin, ent->firemode, (float)ent->weapon*8.0f );
		}

		if( ent->firemode == FIRE_MODE_STRONG )
			CG_StartKickAnglesEffect( ent->origin, 135, ent->weapon*8, 325 );
		else
			CG_StartKickAnglesEffect( ent->origin, 125, ent->weapon*8, 300 );
		break;

	case EV_ROCKET_EXPLOSION:
		ByteToDir( parm, dir );
		CG_RocketExplosionMode( ent->origin, dir, ent->firemode, (float)ent->weapon * 8.0f );

		if( ent->firemode == FIRE_MODE_STRONG )
			CG_StartKickAnglesEffect( ent->origin, 135, ent->weapon * 8, 300 );
		else
			CG_StartKickAnglesEffect( ent->origin, 125, ent->weapon * 8, 275 );
		break;

	case EV_GRENADE_BOUNCE:
		if( parm == FIRE_MODE_STRONG )
			trap_S_StartRelativeSound( CG_MediaSfx( cgs.media.sfxGrenadeStrongBounce[rand()&1] ), ent->number, CHAN_AUTO, cg_volume_effects->value, ATTN_IDLE );
		else
			trap_S_StartRelativeSound( CG_MediaSfx( cgs.media.sfxGrenadeWeakBounce[rand()&1] ), ent->number, CHAN_AUTO, cg_volume_effects->value, ATTN_IDLE );
		break;

	case EV_BLADE_IMPACT:
		CG_BladeImpact( ent->origin, ent->origin2 );
		break;

	case EV_GUNBLADEBLAST_IMPACT:
		ByteToDir( parm, dir );
		CG_GunBladeBlastImpact( ent->origin, dir, (float)ent->weapon*8 );
		if( ent->skinnum > 64 )
		{
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxGunbladeStrongHit[2] ), ent->origin, CHAN_AUTO,
				cg_volume_effects->value, ATTN_DISTANT );
		}
		else if( ent->skinnum > 34 )
		{
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxGunbladeStrongHit[1] ), ent->origin, CHAN_AUTO,
				cg_volume_effects->value, ATTN_NORM );
		}
		else
		{
			trap_S_StartFixedSound( CG_MediaSfx( cgs.media.sfxGunbladeStrongHit[0] ), ent->origin, CHAN_AUTO,
				cg_volume_effects->value, ATTN_IDLE );
		}

		//ent->skinnum is knockback value
		CG_StartKickAnglesEffect( ent->origin, ent->skinnum*8, ent->weapon*8, 200 );
		break;

	case EV_BLOOD:
		if( cg_showBloodTrail->integer == 2 && ISVIEWERENTITY( ent->ownerNum ) )
			break;
		ByteToDir( parm, dir );
		CG_BloodDamageEffect( ent->origin, dir, ent->damage );
		CG_CartoonHitEffect( ent->origin, dir, ent->damage );
		break;

		// func movers
	case EV_PLAT_HIT_TOP:
	case EV_PLAT_HIT_BOTTOM:
	case EV_PLAT_START_MOVING:
	case EV_DOOR_HIT_TOP:
	case EV_DOOR_HIT_BOTTOM:
	case EV_DOOR_START_MOVING:
	case EV_BUTTON_FIRE:
	case EV_TRAIN_STOP:
	case EV_TRAIN_START:
		{
			vec3_t so;
			CG_GetEntitySpatilization( ent->number, so, NULL );
			trap_S_StartFixedSound( cgs.soundPrecache[parm], so, CHAN_AUTO, cg_volume_effects->value, ATTN_STATIC );
		}
		break;

	case EV_VSAY:
		CG_StartVoiceTokenEffect( ent->ownerNum, EV_VSAY, parm );
		break;
	}
}