Ejemplo n.º 1
0
/*
================
CG_Trace
================
*/
void	CG_Trace( trace_t *result, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, 
					 int skipNumber, int mask ) {
	trace_t	t;

	trap_CM_BoxTrace ( &t, start, end, mins, maxs, 0, mask);
	t.entityNum = t.fraction != 1.0 ? ENTITYNUM_WORLD : ENTITYNUM_NONE;
	// check all other solid models
	CG_ClipMoveToEntities( start, mins, maxs, end, skipNumber, mask, &t, TT_AABB );

	*result = t;
}
Ejemplo n.º 2
0
/*
================
CG_AddClientCritter
================
*/
void CG_AddClientCritter( localEntity_t *le ) {
	vec3_t	newOrigin;
	trace_t	trace;
	int		time, step = 25, i;
	vec3_t	v, ang, v2, oDelta;
	localEntity_t backup;
	float	oldSpeed, enemyDist, of;
	vec3_t	enemyPos;
	float alpha;

	if (cg_entities[le->ownerNum].currentState.otherEntityNum2 == cg.snap->ps.clientNum) {
		VectorCopy( cg.snap->ps.origin, enemyPos );
		enemyPos[2] += cg.snap->ps.viewheight;
	} else {
		VectorCopy( cg_entities[le->ownerNum].currentState.origin2, enemyPos );
	}

	VectorCopy( le->pos.trDelta, oDelta );

	// vary the enemyPos to create a psuedo-randomness
	of = (float)cg.time + le->startTime;
	enemyPos[0] += 12 * (sin(of/100) * cos(of/78));
	enemyPos[1] += 12 * (sin(of/70) * cos(of/82));
	enemyPos[2] += 12 * (sin(of/67) * cos(of/98));

	time = le->lastTrailTime+step;

	while (time <= cg.time) {
		if (time > le->refEntity.fadeStartTime) {
			alpha = (float)(time - le->refEntity.fadeStartTime)/(float)(le->refEntity.fadeEndTime - le->refEntity.fadeStartTime);
			if (alpha < 0) alpha = 0;
			else if (alpha > 1) alpha = 1;
		} else {
			alpha = 1.0;
		}

		// calculate new position
		BG_EvaluateTrajectory( &le->pos, time, newOrigin );

		VectorSubtract( enemyPos, le->refEntity.origin, v );
		enemyDist = VectorNormalize( v );

		// trace a line from previous position to new position
		CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, le->ownerNum, MASK_SHOT );

		// if stuck, kill it
		if (trace.startsolid || (trace.fraction < 1.0)) {
			// kill it
			CG_FreeLocalEntity( le );
			return;
		}

		// moved some distance
		VectorCopy( trace.endpos, le->refEntity.origin );

		if (le->leType == LE_ZOMBIE_SPIRIT) {
			le->headJuncIndex = CG_AddTrailJunc( le->headJuncIndex,
												cgs.media.zombieSpiritTrailShader,
												time,
												STYPE_STRETCH,
												le->refEntity.origin,
												(int)le->effectWidth,	// trail life
												0.3 * alpha,
												0.0,
												le->radius,
												0,
												0,//TJFL_FIXDISTORT,
												colorWhite,
												colorWhite,
												1.0, 1 );
		}

		// tracking factor
		if (le->leType == LE_ZOMBIE_BAT)
			le->bounceFactor = 3.0*(float)step/1000.0;
		else
			le->bounceFactor = 5.0*(float)step/1000.0;
		oldSpeed = VectorLength( le->pos.trDelta );

		// track the enemy
		backup = *le;
		VectorSubtract( enemyPos, le->refEntity.origin, v );
		enemyDist = VectorNormalize( v );

		if (alpha > 0.5 && (le->lastSpiritDmgTime < time - 100) && enemyDist < 24) {
			// inflict the damage!
			CG_ClientDamage( cg_entities[le->ownerNum].currentState.otherEntityNum2, le->ownerNum, CLDMG_SPIRIT );
			le->lastSpiritDmgTime = time;
		}

		VectorMA( le->pos.trDelta, le->bounceFactor*oldSpeed, v, le->pos.trDelta );
		//VectorCopy( v, le->pos.trDelta );
		if (VectorLength(le->pos.trDelta) < 1) {
			CG_FreeLocalEntity( le );
			return;
		}

		le->bounceFactor = 5.0*(float)step/1000.0;	// avoidance factor

		// the intersection is a fraction of the frametime
		le->pos.trTime = time;
		VectorCopy( le->refEntity.origin, le->pos.trBase );
		VectorNormalize( le->pos.trDelta );
		VectorScale( le->pos.trDelta, oldSpeed, le->pos.trDelta );

		// now trace ahead of time, if we're going to hit something, then avoid it
		// only avoid dangers if we don't have direct sight to the enemy
		trap_CM_BoxTrace( &trace, le->refEntity.origin, enemyPos, NULL, NULL, 0, MASK_SOLID );
		if (trace.fraction < 1.0) {
			BG_EvaluateTrajectory( &le->pos, time+1000, newOrigin );

			// if we would go passed the enemy, don't bother
			if (VectorDistance( le->refEntity.origin, enemyPos) > VectorDistance( le->refEntity.origin, newOrigin )) {

				trap_CM_BoxTrace( &trace, le->refEntity.origin, newOrigin, NULL, NULL, 0, MASK_SOLID );

				if (trace.fraction < 1.0) {
					// make sure we are not heading away from the enemy too much
					VectorNormalize2( le->pos.trDelta, v2 );
					if (DotProduct( v, v2 ) > 0.7) {
						// avoid world geometry
						backup = *le;
						le->bounceFactor = (1.0 - trace.fraction)*10.0*(float)step/1000.0;	// tracking and avoidance factor
						// reflect the velocity on the trace plane
						VectorMA( le->pos.trDelta, le->bounceFactor*oldSpeed, trace.plane.normal, le->pos.trDelta );
						if (VectorLength(le->pos.trDelta) < 1) {
							CG_FreeLocalEntity( le );
							return;
						}
						// the intersection is a fraction of the frametime
						le->pos.trTime = time;
						VectorCopy( le->refEntity.origin, le->pos.trBase );
						VectorNormalize( le->pos.trDelta );
						VectorScale( le->pos.trDelta, oldSpeed, le->pos.trDelta );
						//
						// double check end velocity
						VectorNormalize2( le->pos.trDelta, v2 );
						if (DotProduct( v, v2 ) <= 0.2) {
							// restore
							*le = backup;
						}
					}
				}
			}
		}

		// set the angles
		VectorNormalize2( le->pos.trDelta, v );
		// HACK!!! skull model is back-to-front, need to fix
		if (le->leType == LE_ZOMBIE_SPIRIT)
			VectorInverse( v );
		vectoangles( v, ang );
		AnglesToAxis( ang, le->refEntity.axis );
		// lean when turning
		if (le->leType == LE_ZOMBIE_BAT) {
			VectorSubtract( le->pos.trDelta, oDelta, v2 );
			ang[ROLL] = -5.0 * DotProduct( le->refEntity.axis[1], v2 );
			if (fabs(ang[ROLL]) > 80) {
				if (ang[ROLL] > 80) ang[ROLL] = 80;
				else ang[ROLL] = -80;
			}
		}
		AnglesToAxis( ang, le->refEntity.axis );

		// HACK: the skull is slightly higher than the origin
		if (le->leType == LE_ZOMBIE_SPIRIT) {
			// set the size scale
			for (i=0; i<3; i++)
				VectorScale( le->refEntity.axis[i], 0.35, le->refEntity.axis[i] );
			VectorMA( le->refEntity.origin, -10, le->refEntity.axis[2], le->refEntity.origin );
		}

		le->lastTrailTime = time;
		time += step;
	}

	// Bats, set the frame
	if (le->leType == LE_ZOMBIE_BAT) {
		#define	BAT_ANIM_FRAMETIME	30
		le->refEntity.frame = (cg.time/BAT_ANIM_FRAMETIME+1)%19;
		le->refEntity.oldframe = (cg.time/BAT_ANIM_FRAMETIME)%19;
		le->refEntity.backlerp = 1.0 - ((float)(cg.time%BAT_ANIM_FRAMETIME)/(float)BAT_ANIM_FRAMETIME);
	}

	// add the sound
	if (le->loopingSound) {
		if (cg.time > le->refEntity.fadeStartTime)
			trap_S_AddLoopingSound( 0, le->refEntity.origin, vec3_origin, le->loopingSound, 255 - (int)(255.0 * (float)(cg.time - le->refEntity.fadeStartTime) / (float)(le->refEntity.fadeEndTime - le->refEntity.fadeStartTime)) );
		else if (le->startTime + 1000 > cg.time)
			trap_S_AddLoopingSound( 0, le->refEntity.origin, vec3_origin, le->loopingSound, (int)(255.0 * (float)(cg.time - le->startTime) / 1000.0) );
		else
			trap_S_AddLoopingSound( 0, le->refEntity.origin, vec3_origin, le->loopingSound, 255);
	}

	trap_R_AddRefEntityToScene( &le->refEntity );
/*
	// HACK: the skull is slightly higher than the origin
	if (le->leType == LE_ZOMBIE_SPIRIT) {
		// set the size scale
		for (i=0; i<3; i++)
			VectorScale( le->refEntity.axis[i], 1.0/0.35, le->refEntity.axis[i] );
		VectorMA( le->refEntity.origin,  10, le->refEntity.axis[2], le->refEntity.origin );
	}
*/
	// Bats, add the flame
	if (le->leType == LE_ZOMBIE_BAT) {
//		float lightSize, alpha;
		//
		le->refEntity.shaderRGBA[3] = 255;
		VectorNormalize2( le->pos.trDelta, v );
		VectorInverse( v );
		v[2] += 1;
		VectorNormalize2( v, le->refEntity.fireRiseDir );

		le->refEntity.customShader = cgs.media.onFireShader2;
		trap_R_AddRefEntityToScene( &le->refEntity );
		le->refEntity.shaderTime = 1434;
		trap_R_AddRefEntityToScene( &le->refEntity );
//		le->refEntity.customShader = cgs.media.onFireShader;
//		le->refEntity.shaderTime = 0;
//		trap_R_AddRefEntityToScene( &le->refEntity );

		le->refEntity.customShader = 0;
		le->refEntity.shaderTime = 0;
/*
		// drop a dlight
		lightSize = 1.0 + 0.2*(sin(1.0*cg.time/50.0) * cos(1.0*cg.time/43.0));
		alpha = 0.2 * (lightSize / 1.2);
		trap_R_AddLightToScene( le->refEntity.origin, 150.0 + 80.0*lightSize, 1.000000*alpha, 0.603922*alpha, 0.207843*alpha, 0 );
		// add some sound
		trap_S_AddLoopingSound( -1, le->refEntity.origin, vec3_origin, cgs.media.flameSound, 100 );
		trap_S_AddLoopingSound( -1, le->refEntity.origin, vec3_origin, cgs.media.flameBlowSound, 100 );
*/
	}
}
Ejemplo n.º 3
0
void CGSyscall_CM_Trace( trace_t *results, const vec3_t start, const vec3_t end, const vec3_t mins, const vec3_t maxs, clipHandle_t model, int brushmask, int capsule ) { if ( capsule ) trap_CM_CapsuleTrace( results, start, end, mins, maxs, model, brushmask ); else trap_CM_BoxTrace( results, start, end, mins, maxs, model, brushmask ); }
Ejemplo n.º 4
0
/*
=========================
CG_TouchTriggerPrediction

Predict push triggers and items
=========================
*/
static void CG_TouchTriggerPrediction( void ) {
	int			i;
	trace_t		trace;
	entityState_t	*ent;
	clipHandle_t cmodel;
	centity_t	*cent;
	qboolean	spectator;

	// dead players don't activate triggers
	if ( cg.cur_lc->predictedPlayerState.stats[STAT_HEALTH] <= 0 ) {
		return;
	}

	spectator = ( cg.cur_lc->predictedPlayerState.pm_type == PM_SPECTATOR );

	if ( cg.cur_lc->predictedPlayerState.pm_type != PM_NORMAL && !spectator ) {
		return;
	}

	for ( i = 0 ; i < cg_numTriggerEntities ; i++ ) {
		cent = cg_triggerEntities[ i ];
		ent = &cent->currentState;

		if ( ent->eType == ET_ITEM && !spectator ) {
			CG_TouchItem( cent );
			continue;
		}

		if ( ent->collisionType != CT_SUBMODEL ) {
			continue;
		}

		cmodel = trap_CM_InlineModel( ent->modelindex );
		if ( !cmodel ) {
			continue;
		}

		if ( cg.cur_lc->predictedPlayerState.collisionType == CT_CAPSULE ) {
			trap_CM_CapsuleTrace( &trace, cg.cur_lc->predictedPlayerState.origin, cg.cur_lc->predictedPlayerState.origin,
					cg.cur_lc->predictedPlayerState.mins, cg.cur_lc->predictedPlayerState.maxs, cmodel, -1 );
		} else {
			trap_CM_BoxTrace( &trace, cg.cur_lc->predictedPlayerState.origin, cg.cur_lc->predictedPlayerState.origin,
					cg.cur_lc->predictedPlayerState.mins, cg.cur_lc->predictedPlayerState.maxs, cmodel, -1 );
		}

		if ( !trace.startsolid ) {
			continue;
		}

		if ( ent->eType == ET_TELEPORT_TRIGGER ) {
			cg.cur_lc->hyperspace = qtrue;
		} else if ( ent->eType == ET_PUSH_TRIGGER ) {
			BG_TouchJumpPad( &cg.cur_lc->predictedPlayerState, ent );
		}
	}

	// if we didn't touch a jump pad this pmove frame
	if ( cg.cur_lc->predictedPlayerState.jumppad_frame != cg.cur_lc->predictedPlayerState.pmove_framecount ) {
		cg.cur_lc->predictedPlayerState.jumppad_frame = 0;
		cg.cur_lc->predictedPlayerState.jumppad_ent = 0;
	}
}