Exemple #1
0
/*
* CG_ViewWeapon_UpdateProjectionSource
*/
static void CG_ViewWeapon_UpdateProjectionSource( vec3_t hand_origin, mat3_t hand_axis, 
	vec3_t weap_origin, mat3_t weap_axis )
{
	orientation_t *tag_result = &cg.weapon.projectionSource;
	orientation_t tag_weapon;
	weaponinfo_t *weaponInfo;

	VectorCopy( vec3_origin, tag_weapon.origin );
	Matrix3_Copy( axis_identity, tag_weapon.axis );

	// move to tag_weapon
	CG_MoveToTag( tag_weapon.origin, tag_weapon.axis,
		hand_origin, hand_axis,
		weap_origin, weap_axis );

	weaponInfo = CG_GetWeaponInfo( cg.weapon.weapon );

	// move to projectionSource tag
	if( weaponInfo )
	{
		VectorCopy( vec3_origin, tag_result->origin );
		Matrix3_Copy( axis_identity, tag_result->axis );
		CG_MoveToTag( tag_result->origin, tag_result->axis,
			tag_weapon.origin, tag_weapon.axis,
			weaponInfo->tag_projectionsource.origin, weaponInfo->tag_projectionsource.axis );
		return;
	}

	// fall back: copy gun origin and move it front by 16 units and 8 up
	VectorCopy( tag_weapon.origin, tag_result->origin );
	Matrix3_Copy( tag_weapon.axis, tag_result->axis );
	VectorMA( tag_result->origin, 16, &tag_result->axis[AXIS_FORWARD], tag_result->origin );
	VectorMA( tag_result->origin, 8, &tag_result->axis[AXIS_UP], tag_result->origin );
}
Exemple #2
0
/*
* CG_AddWeaponOnTag
*
* Add weapon model(s) positioned at the tag
*/
void CG_AddWeaponOnTag( entity_t *ent, orientation_t *tag, int weaponid, int effects, orientation_t *projectionSource, unsigned int flash_time, unsigned int barrel_time )
{
	entity_t weapon;
	weaponinfo_t *weaponInfo;
	float intensity;

	//don't try without base model
	if( !ent->model )
		return;

	//don't try without a tag
	if( !tag )
		return;

	weaponInfo = CG_GetWeaponInfo( weaponid );
	if( !weaponInfo )
		return;

	//if( ent->renderfx & RF_WEAPONMODEL )
	//	effects &= ~EF_RACEGHOST;

	//weapon
	memset( &weapon, 0, sizeof( weapon ) );
	Vector4Set( weapon.shaderRGBA, 255, 255, 255, 255 );
	weapon.scale = ent->scale;
	weapon.renderfx = ent->renderfx;
	weapon.frame = 0;
	weapon.oldframe = 0;
	weapon.model = weaponInfo->model[WEAPON];

	CG_PlaceModelOnTag( &weapon, ent, tag );

	CG_AddColoredOutLineEffect( &weapon, effects, 0, 0, 0, 255 );

	if( !( effects & EF_RACEGHOST ) )
		CG_AddEntityToScene( &weapon );

	if( !weapon.model )
		return;

	CG_AddShellEffects( &weapon, effects );

	// update projection source
	if( projectionSource != NULL )
	{
		VectorCopy( vec3_origin, projectionSource->origin );
		Matrix3_Copy( axis_identity, projectionSource->axis );
		CG_MoveToTag( projectionSource->origin, projectionSource->axis,
			weapon.origin, weapon.axis,
			weaponInfo->tag_projectionsource.origin,
			weaponInfo->tag_projectionsource.axis );
	}

	//expansion
	if( ( effects & EF_STRONG_WEAPON ) && weaponInfo->model[EXPANSION] )
	{
		if( CG_GrabTag( tag, &weapon, "tag_expansion" ) )
		{
			entity_t expansion;
			memset( &expansion, 0, sizeof( expansion ) );
			Vector4Set( expansion.shaderRGBA, 255, 255, 255, 255 );
			expansion.model = weaponInfo->model[EXPANSION];
			expansion.scale = ent->scale;
			expansion.renderfx = ent->renderfx;
			expansion.frame = 0;
			expansion.oldframe = 0;

			CG_PlaceModelOnTag( &expansion, &weapon, tag );

			CG_AddColoredOutLineEffect( &expansion, effects, 0, 0, 0, 255 );

			if( !( effects & EF_RACEGHOST ) )
				CG_AddEntityToScene( &expansion ); // skelmod

			CG_AddShellEffects( &expansion, effects );
		}
	}

	// barrel
	if( weaponInfo->model[BARREL] )
	{
		if( CG_GrabTag( tag, &weapon, "tag_barrel" ) )
		{
			orientation_t barrel_recoiled;
			vec3_t rotangles = { 0, 0, 0 };

			entity_t barrel;
			memset( &barrel, 0, sizeof( barrel ) );
			Vector4Set( barrel.shaderRGBA, 255, 255, 255, 255 );
			barrel.model = weaponInfo->model[BARREL];
			barrel.scale = ent->scale;
			barrel.renderfx = ent->renderfx;
			barrel.frame = 0;
			barrel.oldframe = 0;

			// rotation
			if( barrel_time > cg.time )
			{
				intensity =  (float)( barrel_time - cg.time ) / (float)weaponInfo->barrelTime;
				rotangles[2] = ( 360.0f * weaponInfo->barrelSpeed * intensity * intensity );
				while( rotangles[2] > 360 ) rotangles[2] -= 360;

				// Check for tag_recoil
				if( CG_GrabTag( &barrel_recoiled, &weapon, "tag_recoil" ) )
					VectorLerp( tag->origin, intensity, barrel_recoiled.origin, tag->origin );
			}

			AnglesToAxis( rotangles, barrel.axis );

			// barrel requires special tagging
			CG_PlaceRotatedModelOnTag( &barrel, &weapon, tag );

			CG_AddColoredOutLineEffect( &barrel, effects, 0, 0, 0, 255 );

			if( !( effects & EF_RACEGHOST ) )
				CG_AddEntityToScene( &barrel ); // skelmod

			CG_AddShellEffects( &barrel, effects );
		}
	}

	if( flash_time < cg.time )
		return;

	// flash
	if( !CG_GrabTag( tag, &weapon, "tag_flash" ) )
		return;

	if( weaponInfo->model[FLASH] )
	{
		entity_t flash;
		qbyte c;

		if( weaponInfo->flashFade )
		{
			intensity = (float)( flash_time - cg.time )/(float)weaponInfo->flashTime;
			c = ( qbyte )( 255 * intensity );
		}
		else
		{
			intensity = 1.0f;
			c = 255;
		}

		memset( &flash, 0, sizeof( flash ) );
		Vector4Set( flash.shaderRGBA, c, c, c, c );
		flash.model = weaponInfo->model[FLASH];
		flash.scale = ent->scale;
		flash.renderfx = ent->renderfx | RF_NOSHADOW;
		flash.frame = 0;
		flash.oldframe = 0;

		CG_PlaceModelOnTag( &flash, &weapon, tag );

		if( !( effects & EF_RACEGHOST ) )
			CG_AddEntityToScene( &flash );

		CG_AddLightToScene( flash.origin, weaponInfo->flashRadius * intensity,
			weaponInfo->flashColor[0], weaponInfo->flashColor[1], weaponInfo->flashColor[2] );
	}
}
Exemple #3
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 );
}
Exemple #4
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;
}
Exemple #5
0
/*
* CG_CalcViewWeapon
*/
void CG_CalcViewWeapon( cg_viewweapon_t *viewweapon )
{
	orientation_t tag;
	weaponinfo_t *weaponInfo;
	vec3_t gunAngles;
	vec3_t gunOffset;
	float fallfrac, fallkick;

	CG_ViewWeapon_RefreshAnimation( viewweapon );

	//if( cg.view.thirdperson )
	//	return;

	weaponInfo = CG_GetWeaponInfo( viewweapon->weapon );
	viewweapon->ent.model = weaponInfo->model[HAND];
	viewweapon->ent.renderfx = RF_MINLIGHT|RF_WEAPONMODEL|RF_FORCENOLOD|(cg_shadows->integer < 2 ? RF_NOSHADOW : 0);
	viewweapon->ent.scale = 1.0f;
	viewweapon->ent.customShader = NULL;
	viewweapon->ent.customSkin = NULL;
	viewweapon->ent.rtype = RT_MODEL;
	Vector4Set( viewweapon->ent.shaderRGBA, 255, 255, 255, 255 );

	// calculate the entity position
#if 1
	VectorCopy( cg.view.origin, viewweapon->ent.origin );
#else
	VectorCopy( cg.predictedPlayerState.pmove.origin, viewweapon->ent.origin );
	viewweapon->ent.origin[2] += cg.predictedPlayerState.viewheight;
#endif
	// weapon config offsets
	VectorAdd( weaponInfo->handpositionAngles, cg.predictedPlayerState.viewangles, gunAngles );
	gunOffset[FORWARD] = cg_gunz->value + weaponInfo->handpositionOrigin[FORWARD];
	gunOffset[RIGHT] = cg_gunx->value + weaponInfo->handpositionOrigin[RIGHT];
	gunOffset[UP] = cg_guny->value + weaponInfo->handpositionOrigin[UP];

	// hand cvar offset
	if( cgs.demoPlaying )
	{
		if( hand->integer == 0 )
			gunOffset[RIGHT] += cg_handOffset->value;
		else if( hand->integer == 1 )
			gunOffset[RIGHT] -= cg_handOffset->value;
	}
	else
	{
		if( cgs.clientInfo[cg.view.POVent-1].hand == 0 )
			gunOffset[RIGHT] += cg_handOffset->value;
		else if( cgs.clientInfo[cg.view.POVent-1].hand == 1 )
			gunOffset[RIGHT] -= cg_handOffset->value;
	}

	// fallkick offset
	if( cg.weapon.fallEff_Time > cg.time )
	{
		fallfrac = (float)( cg.time - cg.weapon.fallEff_rebTime ) / (float)( cg.weapon.fallEff_Time - cg.weapon.fallEff_rebTime );
		fallkick = sin( DEG2RAD( fallfrac*180 ) ) * ( ( cg.weapon.fallEff_Time - cg.weapon.fallEff_rebTime ) * 0.01f );
	}
	else
	{
		cg.weapon.fallEff_Time = cg.weapon.fallEff_rebTime = 0;
		fallkick = fallfrac = 0;
	}

	gunOffset[UP] -= fallkick;

	// apply the offsets
#if 1
	VectorMA( viewweapon->ent.origin, gunOffset[FORWARD], &cg.view.axis[AXIS_FORWARD], viewweapon->ent.origin );
	VectorMA( viewweapon->ent.origin, gunOffset[RIGHT], &cg.view.axis[AXIS_RIGHT], viewweapon->ent.origin );
	VectorMA( viewweapon->ent.origin, gunOffset[UP], &cg.view.axis[AXIS_UP], viewweapon->ent.origin );
#else
	Matrix3_FromAngles( cg.predictedPlayerState.viewangles, offsetAxis );
	VectorMA( viewweapon->ent.origin, gunOffset[FORWARD], &offsetAxis[AXIS_FORWARD], viewweapon->ent.origin );
	VectorMA( viewweapon->ent.origin, gunOffset[RIGHT], &offsetAxis[AXIS_RIGHT], viewweapon->ent.origin );
	VectorMA( viewweapon->ent.origin, gunOffset[UP], &offsetAxis[AXIS_UP], viewweapon->ent.origin );
#endif
	// add angles effects
	CG_ViewWeapon_AddAngleEffects( gunAngles );

	// finish
	AnglesToAxis( gunAngles, viewweapon->ent.axis );

	if( cg_gun_fov->integer && !cg.predictedPlayerState.pmove.stats[PM_STAT_ZOOMTIME] )
	{
		float gun_fov = bound( 20, cg_gun_fov->value, 160 );
		float fracWeapFOV = ( 1.0f / cg.view.fracDistFOV ) * tan( gun_fov * ( M_PI/180 ) * 0.5f );
		VectorScale( &viewweapon->ent.axis[AXIS_FORWARD], fracWeapFOV, &viewweapon->ent.axis[AXIS_FORWARD] );
	}

	// if the player doesn't want to view the weapon we still have to build the projection source
	if( CG_GrabTag( &tag, &viewweapon->ent, "tag_weapon" ) )
		CG_ViewWeapon_UpdateProjectionSource( viewweapon->ent.origin, viewweapon->ent.axis, tag.origin, tag.axis );
	else
		CG_ViewWeapon_UpdateProjectionSource( viewweapon->ent.origin, viewweapon->ent.axis, vec3_origin, axis_identity );
}
Exemple #6
0
/*
* CG_ViewWeapon_RefreshAnimation
*/
void CG_ViewWeapon_RefreshAnimation( cg_viewweapon_t *viewweapon )
{
	int baseAnim;
	weaponinfo_t *weaponInfo;
	int curframe = 0;
	float framefrac;
	bool nolerp = false;

	// if the pov changed, or weapon changed, force restart
	if( viewweapon->POVnum != cg.predictedPlayerState.POVnum ||
		viewweapon->weapon != cg.predictedPlayerState.stats[STAT_WEAPON] )
	{
		nolerp = true;
		viewweapon->eventAnim = 0;
		viewweapon->eventAnimStartTime = 0;
		viewweapon->baseAnim = 0;
		viewweapon->baseAnimStartTime = 0;
	}

	viewweapon->POVnum = cg.predictedPlayerState.POVnum;
	viewweapon->weapon = cg.predictedPlayerState.stats[STAT_WEAPON];

	// hack cause of missing animation config
	if( viewweapon->weapon == WEAP_NONE )
	{
		viewweapon->ent.frame = viewweapon->ent.oldframe = 0;
		viewweapon->ent.backlerp = 0.0f;
		viewweapon->eventAnim = 0;
		viewweapon->eventAnimStartTime = 0;
		return;
	}

	baseAnim = CG_ViewWeapon_baseanimFromWeaponState( cg.predictedPlayerState.weaponState );
	weaponInfo = CG_GetWeaponInfo( viewweapon->weapon );

	// Full restart
	if( !viewweapon->baseAnim || !viewweapon->baseAnimStartTime )
	{
		viewweapon->baseAnim = baseAnim;
		viewweapon->baseAnimStartTime = cg.time;
		nolerp = true;
	}

	// base animation changed?
	if( baseAnim != viewweapon->baseAnim )
	{
		viewweapon->baseAnim = baseAnim;
		viewweapon->baseAnimStartTime = cg.time;
	}

	// if a eventual animation is running override the baseAnim
	if( viewweapon->eventAnim )
	{
		if( !viewweapon->eventAnimStartTime )
			viewweapon->eventAnimStartTime = cg.time;

		framefrac = GS_FrameForTime( &curframe, cg.time, viewweapon->eventAnimStartTime, weaponInfo->frametime[viewweapon->eventAnim],
			weaponInfo->firstframe[viewweapon->eventAnim], weaponInfo->lastframe[viewweapon->eventAnim],
			weaponInfo->loopingframes[viewweapon->eventAnim], qfalse );

		if( curframe >= 0 )
			goto setupframe;

		// disable event anim and fall through
		viewweapon->eventAnim = 0;
		viewweapon->eventAnimStartTime = 0;
	}

	// find new frame for the current animation
	framefrac = GS_FrameForTime( &curframe, cg.time, viewweapon->baseAnimStartTime, weaponInfo->frametime[viewweapon->baseAnim],
		weaponInfo->firstframe[viewweapon->baseAnim], weaponInfo->lastframe[viewweapon->baseAnim],
		weaponInfo->loopingframes[viewweapon->baseAnim], qtrue );

	if( curframe < 0 )
		CG_Error( "CG_ViewWeapon_UpdateAnimation(2): Base Animation without a defined loop.\n" );

setupframe:
	if( nolerp )
	{
		framefrac = 0;
		viewweapon->ent.oldframe = curframe;
	}
	else
	{
		clamp( framefrac, 0, 1 );
		if( curframe != viewweapon->ent.frame )
			viewweapon->ent.oldframe = viewweapon->ent.frame;
	}

	viewweapon->ent.frame = curframe;
	viewweapon->ent.backlerp = 1.0f - framefrac;
}