Esempio n. 1
0
void FX_CreateLight(const FXSegment_t *segment, vec3_t origin)
{
	FXLightSegment_t *light;
	fxLight_t *effect;

	if(!segment)
	{	// NULL segment pointer?
		return;
	}
	if(!segment->SegmentData.FXLightSegment)
	{	// No particle segment data?
		return;
	}
	if(segment->segmentType != EFXS_LIGHT)
	{	// Not a particle?
		return;
	}
	light = segment->SegmentData.FXLightSegment;
	effect = (fxLight_t *)malloc(sizeof(fxLight_t));
	FX_LightInit((fxPrimitive_t *)effect);
	effect->culldist = flrand(light->cullrange[0], light->cullrange[1]);
	effect->culldist *= effect->culldist; // allows for VLSquared
	effect->startTime = fx_time + Q_irand(light->delay[0], light->delay[1]);
	effect->endTime = effect->startTime + Q_irand(light->life[0], light->life[1]);
	VectorCopy(origin, effect->origin);

	if((segment->spawnflags & FXSFLAG_CHEAPORIGINCALC))
	{
		vec3_t offset;
		vecrandom(light->origin[0], light->origin[1], offset);
		VectorAdd(effect->origin, offset, effect->origin);
	}
	vecrandom(light->rgb.start.sv[0], light->rgb.start.sv[1], effect->startRGB);

	if(light->rgb.flags != 0 || !(light->rgb.flags & FXTLF_CONSTANT))
	{
		vecrandom(light->rgb.end.ev[0], light->rgb.end.ev[1], effect->endRGB);
	}
	else
	{
		VectorCopy(effect->startRGB, effect->endRGB);
	}
	//effect->RGBflags = light->rgb.flags;
	VectorCopy(effect->startRGB, effect->RGB);

	effect->startsize = effect->size = flrand(light->size.start.sf[0], light->size.start.sf[1]);

	if(light->size.flags != 0 || !(light->size.flags & FXTLF_CONSTANT))
	{
		// TODO: make the distinction between wave, clamp, nonlinear, etc
		effect->endsize = flrand(light->size.end.ef[0], light->size.end.ef[1]);
	}
	else
	{
		effect->endsize = effect->startsize;
	}
	//effect->sizeFlags = light->size.flags;

	FX_AddPrimitive((fxPrimitive_t *)effect, effect->startTime, effect->endTime);
}
Esempio n. 2
0
qboolean NPC_FacePosition( vec3_t position, qboolean doPitch )
{
	vec3_t		muzzle;
	vec3_t		angles;
	float		yawDelta;
	qboolean	facing = qtrue;

	//Get the positions
	if ( NPC->client && (NPC->client->NPC_class == CLASS_RANCOR || NPC->client->NPC_class == CLASS_WAMPA) )// || NPC->client->NPC_class == CLASS_SAND_CREATURE) )
	{
		CalcEntitySpot( NPC, SPOT_ORIGIN, muzzle );
		muzzle[2] += NPC->r.maxs[2] * 0.75f;
	}
	else if ( NPC->client && NPC->client->NPC_class == CLASS_GALAKMECH )
	{
		CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
	}
	else
	{
		CalcEntitySpot( NPC, SPOT_HEAD_LEAN, muzzle );//SPOT_HEAD
	}

	//Find the desired angles
	GetAnglesForDirection( muzzle, position, angles );

	NPCInfo->desiredYaw		= AngleNormalize360( angles[YAW] );
	NPCInfo->desiredPitch	= AngleNormalize360( angles[PITCH] );

	if ( NPC->enemy && NPC->enemy->client && NPC->enemy->client->NPC_class == CLASS_ATST )
	{
		// FIXME: this is kind of dumb, but it was the easiest way to get it to look sort of ok
		NPCInfo->desiredYaw	+= flrand( -5, 5 ) + sin( level.time * 0.004f ) * 7;
		NPCInfo->desiredPitch += flrand( -2, 2 );
	}
	//Face that yaw
	NPC_UpdateAngles( qtrue, qtrue );

	//Find the delta between our goal and our current facing
	yawDelta = AngleNormalize360( NPCInfo->desiredYaw - ( SHORT2ANGLE( ucmd.angles[YAW] + client->ps.delta_angles[YAW] ) ) );
	
	//See if we are facing properly
	if ( fabs( yawDelta ) > VALID_ATTACK_CONE )
		facing = qfalse;

	if ( doPitch )
	{
		//Find the delta between our goal and our current facing
		float currentAngles = ( SHORT2ANGLE( ucmd.angles[PITCH] + client->ps.delta_angles[PITCH] ) );
		float pitchDelta = NPCInfo->desiredPitch - currentAngles;
		
		//See if we are facing properly
		if ( fabs( pitchDelta ) > VALID_ATTACK_CONE )
			facing = qfalse;
	}

	return facing;
}
Esempio n. 3
0
void NPC_AimWiggle( vec3_t enemy_org )
{
	//shoot for somewhere between the head and torso
	//NOTE: yes, I know this looks weird, but it works
	if ( NPCInfo->aimErrorDebounceTime < level.time )
	{
		NPCInfo->aimOfs[0] = 0.3*flrand(NPC->enemy->r.mins[0], NPC->enemy->r.maxs[0]);
		NPCInfo->aimOfs[1] = 0.3*flrand(NPC->enemy->r.mins[1], NPC->enemy->r.maxs[1]);
		if ( NPC->enemy->r.maxs[2] > 0 )
		{
			NPCInfo->aimOfs[2] = NPC->enemy->r.maxs[2]*flrand(0.0f, -1.0f);
		}
	}
	VectorAdd( enemy_org, NPCInfo->aimOfs, enemy_org );
}
Esempio n. 4
0
//lightning strike trigger lightning strike event
void Do_Strike(gentity_t *ent)
{
	trace_t localTrace;
	vec3_t strikeFrom;
	vec3_t strikePoint;
	vec3_t fxAng;
	
	//maybe allow custom fx direction at some point?
	VectorSet(fxAng, 90.0f, 0.0f, 0.0f);

	//choose a random point to strike within the bounds of the trigger
	strikePoint[0] = flrand(ent->r.absmin[0], ent->r.absmax[0]);
	strikePoint[1] = flrand(ent->r.absmin[1], ent->r.absmax[1]);

	//consider the bottom mins the ground level
	strikePoint[2] = ent->r.absmin[2];

	//set the from point
	strikeFrom[0] = strikePoint[0];
	strikeFrom[1] = strikePoint[1];
	strikeFrom[2] = ent->r.absmax[2]-4.0f;

	//now trace for damaging stuff, and do the effect
	trap->Trace(&localTrace, strikeFrom, NULL, NULL, strikePoint, ent->s.number, MASK_PLAYERSOLID, 0, 0, 0);
	VectorCopy(localTrace.endpos, strikePoint);

	if (localTrace.startsolid || localTrace.allsolid)
	{ //got a bad spot, think again next frame to try another strike
		ent->nextthink = level.time;
		return;
	}

	if (ent->radius)
	{ //do a radius damage at the end pos
		G_RadiusDamage(strikePoint, ent, ent->damage, ent->radius, ent, NULL, MOD_SUICIDE);
	}
	else
	{ //only damage individuals
		gentity_t *trHit = &g_entities[localTrace.entityNum];

		if (trHit->inuse && trHit->takedamage)
		{ //damage it then
			G_Damage(trHit, ent, ent, NULL, trHit->r.currentOrigin, ent->damage, 0, MOD_SUICIDE);
		}
	}

	G_PlayEffectID(ent->genericValue2, strikeFrom, fxAng);
}
Esempio n. 5
0
/*
===============
BG_CalculateBulletEndpoint

Calculates the end point of a bullet based on the given inaccuracy and range
===============
*/
void BG_CalculateBulletEndpoint ( vec3_t muzzlePoint, vec3_t fireAngs, float inaccuracy, float range, vec3_t end, int *seed )
{
	float	fGaussianX = 0;
	float	fGaussianY = 0;
	vec3_t	dir;
	vec3_t  fwd;
	vec3_t	up;
	vec3_t	right;

	AngleVectors ( fireAngs, fwd, right, up );

	// No inaccuracy so just extend it forward by the range
	if ( inaccuracy <= 0.0f )
	{
		VectorMA (muzzlePoint, range, fwd, end);
		return;
	}

	// Gaussian spread should keep it a bit less random looking
	while ( 1 )
	{ 	
		float fGaussian;
		float f1;
		float f2;

		f1 = (float)flrand(0, 15000) / 15000.0f;
		f2 = (float)flrand(0, 15000) / 15000.0f;
		fGaussianX = (f1-0.5f) + (f2-0.5f); 

		f1 = (float)flrand(0, 15000) / 15000.0f;
		f2 = (float)flrand(0, 15000) / 15000.0f;
		fGaussianY = (f1-0.5f) + (f2-0.5f); 

		fGaussian = fGaussianX * fGaussianX + fGaussianY * fGaussianY;

		if ( fGaussian < 1 )
		{
			break;
		}
	} 

	VectorMA ( fwd, 0.05f * inaccuracy * fGaussianX, right, dir );
	VectorMA ( dir, 0.05f * inaccuracy * fGaussianY, up, dir );

	VectorMA (muzzlePoint, range, dir, end);
}
Esempio n. 6
0
void LayerNet::an1 ( TrainingSet *tptr , struct LearnParams *lptr )
{
   int itry, user_quit ;
   long seed ;
   double best_err ;
   char msg[80] ;
   LayerNet *worknet, *bestnet ;

/*
   Allocate scratch memory
*/

   MEMTEXT ( "AN1::learn new worknet, bestnet" ) ;
   worknet = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                            nout , 0 , 0 ) ;
   bestnet = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                            nout , 0 , 1 ) ;

   if ((worknet == NULL)  ||  (! worknet->ok)
    || (bestnet == NULL)  ||  (! bestnet->ok)) {
      memory_message ( "to learn" ) ;
      if (worknet != NULL)
         delete worknet ;
      if (bestnet != NULL)
         delete bestnet ;
      errtype = 0 ;
      return ;
      }

   best_err = 1.e30 ;
   for (itry=1 ; itry<=lptr->retries+1 ; itry++) {

      user_quit = anneal1 ( tptr , lptr , worknet , 1 , itry ) ;
      if (neterr < best_err) {
         best_err = neterr ;
         copy_weights ( bestnet , this ) ;
         }

      sprintf ( msg , "Try %d  err=%lf  best=%lf", itry, neterr, best_err ) ;
      normal_message ( msg ) ;

      if (user_quit  ||  (neterr < lptr->quit_err))
         break ;

      seed = flrand() - (long) (itry * 97) ;   // Insure new seed for anneal
      sflrand ( seed ) ;
      zero_weights () ;  // Retry random
      }

   copy_weights ( this , bestnet ) ;
   neterr = best_err ;
   MEMTEXT ( "AN1::learn delete worknet, bestnet" ) ;
   delete worknet ;
   delete bestnet ;
   return ;
}
Esempio n. 7
0
/*
-------------------------
FX_BlasterWeaponHitPlayer
-------------------------
*/
void FX_BlasterWeaponHitPlayer( gentity_t *hit, vec3_t origin, vec3_t normal, qboolean humanoid )
{
	//temporary? just testing out the damage skin stuff -rww
	if ( hit && hit->client && hit->ghoul2.size() )
	{
		CG_AddGhoul2Mark(cgs.media.bdecal_burnmark1, flrand(3.5, 4.0), origin, normal, hit->s.number,
			hit->client->ps.origin, hit->client->renderInfo.legsYaw, hit->ghoul2, hit->s.modelScale, Q_irand(10000, 13000));
	}
        
	theFxScheduler.PlayEffect( cgs.effects.blasterFleshImpactEffect, origin, normal );
}
Esempio n. 8
0
static void vecrandom(const vec3_t v1, const vec3_t v2, vec3_t result)
{
	int i;
	if(!result)
	{
		return;
	}
	for(i = 0; i < 3; i++)
	{
		result[i] = flrand(v1[i], v2[i]);
	}
}
Esempio n. 9
0
void Sniper_UpdateEnemyPos( void ) {
	int index;
	int i;

	for ( i = MAX_ENEMY_POS_LAG - ENEMY_POS_LAG_INTERVAL; i >= 0; i -= ENEMY_POS_LAG_INTERVAL ) {
		index = i / ENEMY_POS_LAG_INTERVAL;
		if ( !index ) {
			CalcEntitySpot( NPC->enemy, SPOT_HEAD_LEAN, &NPCInfo->enemyLaggedPos[index] );
			NPCInfo->enemyLaggedPos[index].z -= flrand( 2, 16 );
		}
		else {
			VectorCopy( &NPCInfo->enemyLaggedPos[index - 1], &NPCInfo->enemyLaggedPos[index] );
		}
	}
}
Esempio n. 10
0
void NPC_GetFlyToLeader( vec3_t moveDir )
{
	vec3_t	dir, target, t_angs, t_dir;
	float	dist, groundDist = G_GroundDistance( NPC );
	const float	minyaw = 35 /*sina(96/176)*/, maxyaw = 75 /*90-15*/;
	float	speed, maxSpeed;
	const float	speedD = 8;

	VectorSubtract( NPC->client->leader->r.currentOrigin, NPC->r.currentOrigin, dir );
	dist = VectorLength( dir );

	if ( dist > 96 && dist < 256 && groundDist > 96 )
	{
		return;
	}

	GetAnglesForDirection( NPC->client->leader->r.currentOrigin, NPC->r.currentOrigin, t_angs );
	t_angs[PITCH] = flrand( minyaw, maxyaw );	//FIXME?

	AngleVectors( t_angs, t_dir, NULL, NULL );

	VectorMA( NPC->client->leader->r.currentOrigin, 176, t_dir, target );

	VectorSubtract( target, NPC->r.currentOrigin, moveDir );
	dist = VectorLength( moveDir );
	VectorNormalize( moveDir );

	maxSpeed = (dist>384)?NPCInfo->stats.runSpeed:NPCInfo->stats.walkSpeed;

	speed = NPCInfo->flySpeed + NPCInfo->stats.acceleration;
	speed *= sqrt(dist) / speedD;

	if ( speed > maxSpeed )
		speed = maxSpeed;
	else if ( speed < 0 )
		speed = 0;

	NPCInfo->flySpeed = DotProduct( moveDir, NPCInfo->lastFlyDir ) * speed;
	if ( NPCInfo->flySpeed < 0 )
		NPCInfo->flySpeed = 0;

	if ( DotProduct( NPC->client->ps.velocity, dir ) > dist )
		speed = -speed;

	VectorCopy( moveDir, NPCInfo->lastFlyDir );
	VectorScale( moveDir, speed, moveDir );

}
Esempio n. 11
0
/*
-------------------------
Remote_Attack
-------------------------
*/
void Remote_Attack( void )
{
	float		distance;
	qboolean	visible;
	float		idealDist;
	qboolean	advance;
	qboolean	retreat;

	if ( TIMER_Done(NPC,"spin") )
	{
		TIMER_Set( NPC, "spin", Q_irand( 250, 1500 ) );
		NPCInfo->desiredYaw += Q_irand( -200, 200 ); 
	}
	// Always keep a good height off the ground
	Remote_MaintainHeight();

	// If we don't have an enemy, just idle
	if ( NPC_CheckEnemyExt(qfalse) == qfalse )
	{
		Remote_Idle();
		return;
	}

	// Rate our distance to the target, and our visibilty
	distance	= (int) DistanceHorizontalSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin );	
	visible		= NPC_ClearLOS4( NPC->enemy );
	idealDist	= MIN_DISTANCE_SQR+(MIN_DISTANCE_SQR*flrand( 0, 1 ));
	advance		= (qboolean)(distance > idealDist*1.25);
	retreat		= (qboolean)(distance < idealDist*0.75);

	// If we cannot see our target, move to see it
	if ( visible == qfalse )
	{
		if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES )
		{
			Remote_Hunt( visible, advance, retreat );
			return;
		}
	}

	Remote_Ranged( visible, advance, retreat );

}
Esempio n. 12
0
void NPC_GetFlyToGoal( vec3_t moveDir ) 
{
#if 0
	vec3_t	dir, a, b;
	float	dot, dist;
	float	acceleration = NPCInfo->stats.acceleration, speed, maxSpeed = ((NPCInfo->scriptFlags&SCF_WALKING)?NPCInfo->stats.walkSpeed:NPCInfo->stats.runSpeed);

	if ( !NPCInfo->goalEntity )
		return;

	VectorSubtract( NPCInfo->goalEntity->r.currentOrigin, NPC->r.currentOrigin, dir );

	dist = VectorLengthSquared( dir );
	if ( VectorLengthSquared( dir ) < 4096 )
	{
		VectorClear( moveDir );
		return;
	}

	VectorNormalize( dir );

	acceleration *= 5.0f;
	maxSpeed *= 5.0f;
	dot = DotProduct( NPC->client->ps.velocity, dir );
	speed = maxSpeed - dot;
	if ( speed > acceleration )
		speed = acceleration;
	else if ( speed < -acceleration )
		speed = -acceleration;

	VectorMA( NPC->r.currentOrigin, dist * 2.0f, dir, a );
	VectorMA( NPC->r.currentOrigin, 0.5f, NPC->client->ps.velocity, b );	//FIXME?
	VectorSubtract( a, b, moveDir );
	
	VectorNormalize( moveDir );
	VectorScale( moveDir, acceleration, moveDir );
#else
	vec3_t	vel, dir;
	float	dist;
	float	lMin, lMax;
	const float	lMinD = -(0.015625f*0.015625f), lMaxD = 0.0234375f*0.0234375f;
	/*const */float	speedD = 16;
	float	speed, maxSpeed = ((ucmd.buttons&BUTTON_WALKING)?NPCInfo->stats.walkSpeed:NPCInfo->stats.runSpeed);

	if ( !NPCInfo->goalEntity )
	{
		if ( VectorCompare( NPC->client->ps.velocity, vec3_origin ) )
		{
			VectorClear( moveDir );
		}
		else
		{
			//on décélère
			speed = VectorLength( NPC->client->ps.velocity );
			if ( speed > maxSpeed )
				speed = maxSpeed;
			VectorNormalize2( NPC->client->ps.velocity, moveDir );
			VectorScale( moveDir, -speed, moveDir );
		}
		return;
	}

	VectorSubtract( NPCInfo->goalEntity->r.currentOrigin, NPC->r.currentOrigin, moveDir );
	VectorNormalize2( moveDir, dir );

	dist = VectorLength( moveDir );

	lMax = sqrt(dist);
	lMin = lMax * lMinD;	//-0.015625f
	lMax *= lMaxD;	//0.0234375f

	if ( VectorLengthSquared( NPC->client->ps.velocity ) <= 1 )
	{
		vel[0] = flrand(-1.0f,1.0f);
		vel[1] = flrand(-1.0f,1.0f);
		vel[2] = flrand(-1.0f,1.0f);
	}
	else
	{
		VectorCopy( NPC->client->ps.velocity, vel );
	}

#if 1	//du gro hack ki pu
	if ( (NPC->r.currentOrigin[2] - NPCInfo->goalEntity->r.currentOrigin[2]) > 0 && NPCInfo->goalEntity == NPC->client->leader )
	{
		lMin = lMax = VectorLength( NPC->client->ps.velocity );
	}
	if ( NPCInfo->behaviorState == BS_FOLLOW_LEADER )
	{
		speedD = 8;
	}
#endif

	VectorNormalize( vel );
	VectorScale( vel, flrand( lMin, lMax ), vel );

	VectorSubtract( moveDir, vel, moveDir );

	VectorNormalize( moveDir );

	speed = NPCInfo->flySpeed + NPCInfo->stats.acceleration;
	speed *= sqrt(dist) / speedD;

	if ( speed > maxSpeed )
		speed = maxSpeed;
	else if ( speed < -maxSpeed )
		speed = -maxSpeed;

	NPCInfo->flySpeed = DotProduct( moveDir, NPCInfo->lastFlyDir ) * speed;
	if ( NPCInfo->flySpeed < 0 )
		NPCInfo->flySpeed = 0;

	if ( DotProduct( NPC->client->ps.velocity, dir ) > dist )
		speed = -speed;

	VectorCopy( moveDir, NPCInfo->lastFlyDir );
	VectorScale( moveDir, speed, moveDir );

#endif
}
Esempio n. 13
0
/*
qboolean NPC_UpdateFiringAngles ( qboolean doPitch, qboolean doYaw ) 

  Includes aim when determining angles - so they don't always hit...
  */
qboolean NPC_UpdateFiringAngles ( qboolean doPitch, qboolean doYaw ) 
{

	float		error, diff;
	float		decay;
	float		targetPitch = 0;
	float		targetYaw = 0;
	qboolean	exact = qtrue;

	// if angle changes are locked; just keep the current angles
	if ( level.time < NPCInfo->aimTime ) 
	{
		if(doPitch)
			targetPitch = NPCInfo->lockedDesiredPitch;
		if(doYaw)
			targetYaw = NPCInfo->lockedDesiredYaw;
	}
	else 
	{
		if(doPitch)
			targetPitch = NPCInfo->desiredPitch;
		if(doYaw)
			targetYaw = NPCInfo->desiredYaw;

//		NPCInfo->aimTime = level.time + 250;
		if(doPitch)
			NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch;
		if(doYaw)
			NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw;
	}

	if ( NPCInfo->aimErrorDebounceTime < level.time )
	{
		if ( Q_irand(0, 1 ) )
		{
			NPCInfo->lastAimErrorYaw = ((float)(6 - NPCInfo->stats.aim)) * flrand(-1, 1);
		}
		if ( Q_irand(0, 1 ) )
		{
			NPCInfo->lastAimErrorPitch = ((float)(6 - NPCInfo->stats.aim)) * flrand(-1, 1);
		}
		NPCInfo->aimErrorDebounceTime = level.time + Q_irand(250, 2000);
	}

	if(doYaw)
	{
		// decay yaw diff
		diff = AngleDelta ( NPC->client->ps.viewangles[YAW], targetYaw );
		
		if ( diff) 
		{
			exact = qfalse;

			decay = 60.0 + 80.0;
			decay *= 50.0f / 1000.0f;//msec
			if ( diff < 0.0 ) 
			{
				diff += decay;
				if ( diff > 0.0 ) 
				{
					diff = 0.0;
				}
			}
			else 
			{
				diff -= decay;
				if ( diff < 0.0 ) 
				{
					diff = 0.0;
				}
			}
		}
				
		// add yaw error based on NPCInfo->aim value
		error = NPCInfo->lastAimErrorYaw;

		/*
		if(Q_irand(0, 1))
		{
			error *= -1;
		}
		*/

		ucmd.angles[YAW] = ANGLE2SHORT( targetYaw + diff + error ) - client->ps.delta_angles[YAW];
	}

	if(doPitch)
	{
		// decay pitch diff
		diff = AngleDelta ( NPC->client->ps.viewangles[PITCH], targetPitch );
		if ( diff) 
		{
			exact = qfalse;

			decay = 60.0 + 80.0;
			decay *= 50.0f / 1000.0f;//msec
			if ( diff < 0.0 ) 
			{
				diff += decay;
				if ( diff > 0.0 ) 
				{
					diff = 0.0;
				}
			}
			else 
			{
				diff -= decay;
				if ( diff < 0.0 ) 
				{
					diff = 0.0;
				}
			}
		}
		
		error = NPCInfo->lastAimErrorPitch;

		ucmd.angles[PITCH] = ANGLE2SHORT( targetPitch + diff + error ) - client->ps.delta_angles[PITCH];
	}

	ucmd.angles[ROLL] = ANGLE2SHORT ( NPC->client->ps.viewangles[ROLL] ) - client->ps.delta_angles[ROLL];

	return exact;
}
void asteroid_field_think(gentity_t *self)
{
	int numAsteroids = asteroid_count_num_asteroids( self );

	self->nextthink = level.time + 500;

	if ( numAsteroids < self->count )
	{
		//need to spawn a new asteroid
		gentity_t *newAsteroid = G_Spawn();
		if ( newAsteroid )
		{
			vec3_t startSpot, endSpot, startAngles;
			float dist, speed = flrand( self->speed * 0.25f, self->speed * 2.0f );
			int	capAxis, axis, time = 0;
			gentity_t *copyAsteroid = asteroid_pick_random_asteroid( self );
			if ( copyAsteroid )
			{
				newAsteroid->model = copyAsteroid->model;
				newAsteroid->model2 = copyAsteroid->model2;
				newAsteroid->health = copyAsteroid->health;
				newAsteroid->spawnflags = copyAsteroid->spawnflags;
				newAsteroid->mass = copyAsteroid->mass;
				newAsteroid->damage = copyAsteroid->damage;
				newAsteroid->speed = copyAsteroid->speed;

				G_SetOrigin( newAsteroid, copyAsteroid->s.origin );
				G_SetAngles( newAsteroid, copyAsteroid->s.angles );
				newAsteroid->classname = "func_rotating";

				SP_func_rotating( newAsteroid );

				newAsteroid->genericValue15 = copyAsteroid->genericValue15;
				newAsteroid->s.iModelScale = copyAsteroid->s.iModelScale;
				newAsteroid->maxHealth = newAsteroid->health;
				G_ScaleNetHealth(newAsteroid);
				newAsteroid->radius = copyAsteroid->radius;
				newAsteroid->material = copyAsteroid->material;
				//CacheChunkEffects( self->material );

				//keep track of it
				newAsteroid->r.ownerNum = self->s.number;

				//move it
				capAxis = Q_irand( 0, 2 );
				for ( axis = 0; axis < 3; axis++ )
				{
					if ( axis == capAxis )
					{
						if ( Q_irand( 0, 1 ) )
						{
							startSpot[axis] = self->r.mins[axis];
							endSpot[axis] = self->r.maxs[axis];
						}
						else
						{
							startSpot[axis] = self->r.maxs[axis];
							endSpot[axis] = self->r.mins[axis];
						}
					}
					else
					{
						startSpot[axis] = self->r.mins[axis]+(flrand(0,1.0f)*(self->r.maxs[axis]-self->r.mins[axis]));
						endSpot[axis] = self->r.mins[axis]+(flrand(0,1.0f)*(self->r.maxs[axis]-self->r.mins[axis]));
					}
				}
				//FIXME: maybe trace from start to end to make sure nothing is in the way?  How big of a trace?

				G_SetOrigin( newAsteroid, startSpot );
				dist = Distance( endSpot, startSpot );
				time = ceil(dist/speed)*1000;
				Q3_Lerp2Origin( -1, newAsteroid->s.number, endSpot, time );

				//spin it
				startAngles[0] = flrand( -360, 360 );
				startAngles[1] = flrand( -360, 360 );
				startAngles[2] = flrand( -360, 360 );
				G_SetAngles( newAsteroid, startAngles );
				newAsteroid->s.apos.trDelta[0] = flrand( -100, 100 );
				newAsteroid->s.apos.trDelta[1] = flrand( -100, 100 );
				newAsteroid->s.apos.trDelta[2] = flrand( -100, 100 );
				newAsteroid->s.apos.trTime = level.time;
				newAsteroid->s.apos.trType = TR_LINEAR;

				//remove itself when done
				newAsteroid->think = G_FreeEntity;
				newAsteroid->nextthink = level.time+time;

				//think again sooner if need even more
				if ( numAsteroids+1 < self->count )
				{//still need at least one more
					//spawn it in 100ms
					self->nextthink = level.time + 100;
				}
			}
		}
	}
}
Esempio n. 15
0
void LayerNet::ssg (
   TrainingSet *tptr ,        // Training set to use
   struct LearnParams *lptr , // User's general learning parameters
   int use_grad               // SS if zero, else SSG
   )
{
   int itry, user_quit, n, n_grad ;
   long seed ;
   double best_err, *work1, *work2, *grad, *avg_grad ;
   char msg[80] ;
   LayerNet *worknet1, *worknet2, *bestnet ;
                             
/*
   Allocate network scratch memory
*/

   MEMTEXT ( "SSG::new 2 worknets, bestnet" ) ;
   worknet1 = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                             nout , 0 , 0 ) ;
   worknet2 = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                             nout , 0 , 0 ) ;
   bestnet = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                            nout , 0 , 1 ) ;

   if ((worknet1 == NULL)  ||  (! worknet1->ok)
    || (worknet2 == NULL)  ||  (! worknet2->ok)
    || (bestnet == NULL)  ||  (! bestnet->ok)) {
      memory_message ( "to learn" ) ;
      if (worknet1 != NULL)
         delete worknet1 ;
      if (worknet2 != NULL)
         delete worknet2 ;
      if (bestnet != NULL)
         delete bestnet ;
      errtype = 0 ;
      return ;
      }

/*
   Allocate gradient work memory.
   Work1 is used for hidden layer 2 deltas in REAL model, and output
   activation partial derivatives and deltas in all COMPLEX models.
   Work2 is output deltas in REAL model, error difference in COMPLEX models.
*/

   if (use_grad) {
      if (nhid2)       // Must be REAL model if this is true
         n = nhid2 ;
      else if (model == NETMOD_COMPLEX_INPUT)
         n = nhid1  ?  nout * 2 + nhid1 * 2  :  nout * 2 ;
      else if (model == NETMOD_COMPLEX_HIDDEN)
         n = nout * 4  +  nhid1 * 4 ;
      else if (model == NETMOD_COMPLEX)
         n = nhid1  ?  nout * 6  +  nhid1 * 4  :  nout * 4 ;
      else
         n = 0 ;

      if (n) {
         MEMTEXT ( "SSG::work1" ) ;
         work1 = (double *) MALLOC ( n * sizeof(double) ) ;
         if (work1 == NULL) {
            memory_message ( "to learn" ) ;
            delete worknet1 ;
            delete worknet2 ;
            delete bestnet ;
            errtype = 0 ;
            return ;
            }
         }
      else
         work1 = NULL ;

      if (nhid1 == 0)               // No hidden layer
         n_grad = nout * nin_n ;
      else if (nhid2 == 0)          // One hidden layer
         n_grad = nhid1 * nin_n + nout * nhid1_n ;
      else                          // Two hidden layers
         n_grad = nhid1 * nin_n + nhid2 * nhid1_n + nout * nhid2_n ;

      MEMTEXT ( "SSG::3 work vectors" ) ;
      work2 = (double *) MALLOC ( nout_n * sizeof(double) ) ;
      grad = (double *) MALLOC ( n_grad * sizeof(double) ) ;
      avg_grad = (double *) MALLOC ( n_grad * sizeof(double) ) ;

      if ((work2 == NULL)  ||  (grad == NULL)  ||  (avg_grad == NULL)) {
         if (work1 != NULL)
            FREE ( work1 ) ;
         if (work2 != NULL)
            FREE ( work2 ) ;
         if (grad != NULL)
            FREE ( grad ) ;
         if (avg_grad != NULL)
            FREE ( avg_grad ) ;
         memory_message ( "to learn" ) ;
         delete worknet1 ;
         delete worknet2 ;
         delete bestnet ;
         errtype = 0 ;
         return ;
         }
      }
   else
      work1 = work2 = grad = avg_grad = NULL ;

   best_err = 1.e30 ;
   for (itry=1 ; itry<=lptr->retries+1 ; itry++) {

      user_quit = ssg_core ( tptr , lptr , worknet1 , worknet2 ,
                             work1 , work2 , grad , avg_grad , n_grad ) ;

      if (neterr < best_err) {
         best_err = neterr ;
         copy_weights ( bestnet , this ) ;
         }

      sprintf ( msg , "Try %d  err=%lf  best=%lf", itry, neterr, best_err ) ;
      normal_message ( msg ) ;

      if (user_quit  ||  (neterr < lptr->quit_err))
         break ;

      seed = flrand() - (long) (itry * 97) ;   // Insure new seed for anneal
      sflrand ( seed ) ;
      zero_weights () ;  // Retry random
      }

   copy_weights ( this , bestnet ) ;
   neterr = best_err ;

   MEMTEXT ( "AN1::learn delete 2 worknets, bestnet" ) ;
   delete worknet1 ;
   delete worknet2 ;
   delete bestnet ;

   if (use_grad) {
      if (work1 != NULL) {
         MEMTEXT ( "SSG::work1" ) ;
         FREE ( work1 ) ;
         }
      MEMTEXT ( "SSG::3 work vectors" ) ;
      FREE ( work2 ) ;
      FREE ( grad ) ;
      FREE ( avg_grad) ;
      }

   return ;

}
Esempio n. 16
0
void Sniper_FaceEnemy( void )
{
	//FIXME: the ones behind kill holes are facing some arbitrary direction and not firing
	//FIXME: If actually trying to hit enemy, don't fire unless enemy is at least in front of me?
	//FIXME: need to give designers option to make them not miss first few shots
	if ( NPC->enemy )
	{
		vec3_t	muzzle, target, angles, forward, right, up;
		//Get the positions
		AngleVectors( NPC->client->ps.viewangles, forward, right, up );
		CalcMuzzlePoint( NPC, forward, right, up, muzzle );
		//CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
		CalcEntitySpot( NPC->enemy, SPOT_ORIGIN, target );

		if ( enemyDist2 > 65536 && NPCInfo->stats.aim < 5 )//is 256 squared, was 16384 (128*128)
		{
			if ( NPC->count < (5-NPCInfo->stats.aim) )
			{//miss a few times first
				if ( shoot2 && TIMER_Done( NPC, "attackDelay" ) && level.time >= NPCInfo->shotTime )
				{//ready to fire again
					qboolean	aimError = qfalse;
					qboolean	hit = qtrue;
					int			tryMissCount = 0;
					trace_t		trace;

					GetAnglesForDirection( muzzle, target, angles );
					AngleVectors( angles, forward, right, up );

					while ( hit && tryMissCount < 10 )
					{
						tryMissCount++;
						if ( !Q_irand( 0, 1 ) )
						{
							aimError = qtrue;
							if ( !Q_irand( 0, 1 ) )
							{
								VectorMA( target, NPC->enemy->r.maxs[2]*flrand(1.5, 4), right, target );
							}
							else
							{
								VectorMA( target, NPC->enemy->r.mins[2]*flrand(1.5, 4), right, target );
							}
						}
						if ( !aimError || !Q_irand( 0, 1 ) )
						{
							if ( !Q_irand( 0, 1 ) )
							{
								VectorMA( target, NPC->enemy->r.maxs[2]*flrand(1.5, 4), up, target );
							}
							else
							{
								VectorMA( target, NPC->enemy->r.mins[2]*flrand(1.5, 4), up, target );
							}
						}
						trap_Trace( &trace, muzzle, vec3_origin, vec3_origin, target, NPC->s.number, MASK_SHOT );
						hit = Sniper_EvaluateShot( trace.entityNum );
					}
					NPC->count++;
				}
				else
				{
					if ( !enemyLOS2 )
					{
						NPC_UpdateAngles( qtrue, qtrue );
						return;
					}
				}
			}
			else
			{//based on distance, aim value, difficulty and enemy movement, miss
				//FIXME: incorporate distance as a factor?
				int missFactor = 8-(NPCInfo->stats.aim+g_spskill.integer) * 3;
				if ( missFactor > ENEMY_POS_LAG_STEPS )
				{
					missFactor = ENEMY_POS_LAG_STEPS;
				}
				else if ( missFactor < 0 )
				{//???
					missFactor = 0 ;
				}
				VectorCopy( NPCInfo->enemyLaggedPos[missFactor], target );
			}
			GetAnglesForDirection( muzzle, target, angles );
		}
		else
		{
			target[2] += flrand( 0, NPC->enemy->r.maxs[2] );
			//CalcEntitySpot( NPC->enemy, SPOT_HEAD_LEAN, target );
			GetAnglesForDirection( muzzle, target, angles );
		}

		NPCInfo->desiredYaw		= AngleNormalize360( angles[YAW] );
		NPCInfo->desiredPitch	= AngleNormalize360( angles[PITCH] );
	}
	NPC_UpdateAngles( qtrue, qtrue );
}
void Wampa_Slash( int boltIndex, qboolean backhand )
{
	int			radiusEntNums[128];
	int			numEnts;
	const float	radius = 88;
	const float	radiusSquared = (radius*radius);
	int			i;
	vec3_t		boltOrg;
	int			damage = (backhand)?Q_irand(10,15):Q_irand(20,30);

	numEnts = NPC_GetEntsNearBolt( radiusEntNums, radius, boltIndex, boltOrg );

	for ( i = 0; i < numEnts; i++ )
	{
		gentity_t *radiusEnt = &g_entities[radiusEntNums[i]];
		if ( !radiusEnt->inuse )
		{
			continue;
		}
		
		if ( radiusEnt == NPC )
		{//Skip the wampa ent
			continue;
		}
		
		if ( radiusEnt->client == NULL )
		{//must be a client
			continue;
		}

		if ( DistanceSquared( radiusEnt->r.currentOrigin, boltOrg ) <= radiusSquared )
		{
			//smack
			G_Damage( radiusEnt, NPC, NPC, vec3_origin, radiusEnt->r.currentOrigin, damage, ((backhand)?DAMAGE_NO_ARMOR:(DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK)), MOD_MELEE );
			if ( backhand )
			{
				//actually push the enemy
				vec3_t pushDir;
				vec3_t angs;
				VectorCopy( NPC->client->ps.viewangles, angs );
				angs[YAW] += flrand( 25, 50 );
				angs[PITCH] = flrand( -25, -15 );
				AngleVectors( angs, pushDir, NULL, NULL );
				if ( radiusEnt->client->NPC_class != CLASS_WAMPA
					&& radiusEnt->client->NPC_class != CLASS_RANCOR
					&& radiusEnt->client->NPC_class != CLASS_ATST )
				{
					G_Throw( radiusEnt, pushDir, 65 );
					if ( BG_KnockDownable(&radiusEnt->client->ps) &&
						radiusEnt->health > 0 && Q_irand( 0, 1 ) )
					{//do pain on enemy
						radiusEnt->client->ps.forceHandExtend = HANDEXTEND_KNOCKDOWN;
						radiusEnt->client->ps.forceDodgeAnim = 0;
						radiusEnt->client->ps.forceHandExtendTime = level.time + 1100;
						radiusEnt->client->ps.quickerGetup = qfalse;
					}
				}
			}
			else if ( radiusEnt->health <= 0 && radiusEnt->client )
			{//killed them, chance of dismembering
				if ( !Q_irand( 0, 1 ) )
				{//bite something off
					int hitLoc = Q_irand( G2_MODELPART_HEAD, G2_MODELPART_RLEG );
					if ( hitLoc == G2_MODELPART_HEAD )
					{
						NPC_SetAnim( radiusEnt, SETANIM_BOTH, BOTH_DEATH17, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
					}
					else if ( hitLoc == G2_MODELPART_WAIST )
					{
						NPC_SetAnim( radiusEnt, SETANIM_BOTH, BOTH_DEATHBACKWARD2, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
					}
					G_Dismember( radiusEnt, NPC, radiusEnt->r.currentOrigin, hitLoc, 90, 0, radiusEnt->client->ps.torsoAnim, qtrue);
				}
			}
			else if ( !Q_irand( 0, 3 ) && radiusEnt->health > 0 )
			{//one out of every 4 normal hits does a knockdown, too
				vec3_t pushDir;
				vec3_t angs;
				VectorCopy( NPC->client->ps.viewangles, angs );
				angs[YAW] += flrand( 25, 50 );
				angs[PITCH] = flrand( -25, -15 );
				AngleVectors( angs, pushDir, NULL, NULL );
				//[KnockdownSys]
				//ported multi-direction knockdowns from SP.
				G_Knockdown( radiusEnt, NPC, pushDir, 35, qtrue );
				//G_Knockdown( radiusEnt );
				//[/KnockdownSys]
			}
			G_Sound( radiusEnt, CHAN_WEAPON, G_SoundIndex( "sound/chars/rancor/swipehit.wav" ) );
		}
	}
}
Esempio n. 18
0
void NPC_BSGM_Attack( void )
{
	//Don't do anything if we're hurt
	if ( NPCS.NPC->painDebounceTime > level.time )
	{
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}

#if 0
	//FIXME: if killed enemy, use victory anim
	if ( NPC->enemy && NPC->enemy->health <= 0
		&& !NPC->enemy->s.number )
	{//my enemy is dead
		if ( NPC->client->ps.torsoAnim == BOTH_STAND2TO1 )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				G_AddVoiceEvent( NPC, Q_irand( EV_VICTORY1, EV_VICTORY3 ), 3000 );
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_TRIUMPHANT1START, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer += 500;
				NPC->client->ps.torsoTimer += 500;
			}
		}
		else if ( NPC->client->ps.torsoAnim == BOTH_TRIUMPHANT1START )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_TRIUMPHANT1STARTGESTURE, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer += 500;
				NPC->client->ps.torsoTimer += 500;
			}
		}
		else if ( NPC->client->ps.torsoAnim == BOTH_TRIUMPHANT1STARTGESTURE )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_TRIUMPHANT1STOP, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer += 500;
				NPC->client->ps.torsoTimer += 500;
			}
		}
		else if ( NPC->client->ps.torsoAnim == BOTH_TRIUMPHANT1STOP )
		{
			if ( NPC->client->ps.torsoTimer <= 500 )
			{
				NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_STAND1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				NPC->client->ps.legsTimer = -1;
				NPC->client->ps.torsoTimer = -1;
			}
		}
		else if ( NPC->wait )
		{
			if ( TIMER_Done( NPC, "gloatTime" ) )
			{
				GM_StartGloat();
			}
			else if ( DistanceHorizontalSquared( NPC->client->renderInfo.eyePoint, NPC->enemy->r.currentOrigin ) > 4096 && (NPCInfo->scriptFlags&SCF_CHASE_ENEMIES) )//64 squared
			{
				NPCInfo->goalEntity = NPC->enemy;
				GM_Move();
			}
			else
			{//got there
				GM_StartGloat();
			}
		}
		NPC_FaceEnemy( qtrue );
		NPC_UpdateAngles( qtrue, qtrue );
		return;
	}
#endif

	//If we don't have an enemy, just idle
	if ( NPC_CheckEnemyExt(qfalse) == qfalse || !NPCS.NPC->enemy )
	{
		NPCS.NPC->enemy = NULL;
		NPC_BSGM_Patrol();
		return;
	}

	enemyLOS4 = enemyCS4 = qfalse;
	move4 = qtrue;
	faceEnemy4 = qfalse;
	shoot4 = qfalse;
	hitAlly4 = qfalse;
	VectorClear( impactPos4 );
	enemyDist4 = DistanceSquared( NPCS.NPC->r.currentOrigin, NPCS.NPC->enemy->r.currentOrigin );

	//if ( NPC->client->ps.torsoAnim == BOTH_ATTACK4 ||
	//	NPC->client->ps.torsoAnim == BOTH_ATTACK5 )
	if (0)
	{
		shoot4 = qfalse;
		if ( TIMER_Done( NPCS.NPC, "smackTime" ) && !NPCS.NPCInfo->blockedDebounceTime )
		{//time to smack
			//recheck enemyDist4 and InFront
			if ( enemyDist4 < MELEE_DIST_SQUARED && InFront( NPCS.NPC->enemy->r.currentOrigin, NPCS.NPC->r.currentOrigin, NPCS.NPC->client->ps.viewangles, 0.3f ) )
			{
				vec3_t	smackDir;
				VectorSubtract( NPCS.NPC->enemy->r.currentOrigin, NPCS.NPC->r.currentOrigin, smackDir );
				smackDir[2] += 30;
				VectorNormalize( smackDir );
				//hurt them
				G_Sound( NPCS.NPC->enemy, CHAN_AUTO, G_SoundIndex( "sound/weapons/galak/skewerhit.wav" ) );
				G_Damage( NPCS.NPC->enemy, NPCS.NPC, NPCS.NPC, smackDir, NPCS.NPC->r.currentOrigin, (g_npcspskill.integer+1)*Q_irand( 5, 10), DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK, MOD_CRUSH );
				if ( NPCS.NPC->client->ps.torsoAnim == BOTH_ATTACK4 )
				{//smackdown
					int knockAnim = BOTH_KNOCKDOWN1;
					if ( BG_CrouchAnim( NPCS.NPC->enemy->client->ps.legsAnim ) )
					{//knockdown from crouch
						knockAnim = BOTH_KNOCKDOWN4;
					}
					//throw them
					smackDir[2] = 1;
					VectorNormalize( smackDir );
					G_Throw( NPCS.NPC->enemy, smackDir, 50 );
					NPC_SetAnim( NPCS.NPC->enemy, SETANIM_BOTH, knockAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				}
				else
				{//uppercut
					//throw them
					G_Throw( NPCS.NPC->enemy, smackDir, 100 );
					//make them backflip
					NPC_SetAnim( NPCS.NPC->enemy, SETANIM_BOTH, BOTH_KNOCKDOWN5, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				}
				//done with the damage
				NPCS.NPCInfo->blockedDebounceTime = 1;
			}
		}
	}
	else if ( NPCS.NPC->lockCount ) //already shooting laser
	{//sometimes use the laser beam attack, but only after he's taken down our generator
		shoot4 = qfalse;
		if ( NPCS.NPC->lockCount == 1 )
		{//charging up
			if ( TIMER_Done( NPCS.NPC, "beamDelay" ) )
			{//time to start the beam
				int laserAnim;
				//if ( Q_irand( 0, 1 ) )
				if (1)
				{
					laserAnim = BOTH_ATTACK2;
				}
				/*
				else
				{
					laserAnim = BOTH_ATTACK7;
				}
				*/
				NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, laserAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				TIMER_Set( NPCS.NPC, "attackDelay", NPCS.NPC->client->ps.torsoTimer + Q_irand( 1000, 3000 ) );
				//turn on beam effect
				NPCS.NPC->lockCount = 2;
				G_PlayEffectID( G_EffectIndex("galak/trace_beam"), NPCS.NPC->r.currentOrigin, vec3_origin );
				NPCS.NPC->s.loopSound = G_SoundIndex( "sound/weapons/galak/lasercutting.wav" );
				if ( !NPCS.NPCInfo->coverTarg )
				{//for moving looping sound at end of trace
					NPCS.NPCInfo->coverTarg = G_Spawn();
					if ( NPCS.NPCInfo->coverTarg )
					{
						G_SetOrigin( NPCS.NPCInfo->coverTarg, NPCS.NPC->client->renderInfo.muzzlePoint );
						NPCS.NPCInfo->coverTarg->r.svFlags |= SVF_BROADCAST;
						NPCS.NPCInfo->coverTarg->s.loopSound = G_SoundIndex( "sound/weapons/galak/lasercutting.wav" );
					}
				}
			}
		}
		else
		{//in the actual attack now
			if ( NPCS.NPC->client->ps.torsoTimer <= 0 )
			{//attack done!
				NPCS.NPC->lockCount = 0;
				G_FreeEntity( NPCS.NPCInfo->coverTarg );
				NPCS.NPC->s.loopSound = 0;
#if 0
				NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_DROPWEAP2, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
#endif
				TIMER_Set( NPCS.NPC, "attackDelay", NPCS.NPC->client->ps.torsoTimer );
			}
			else
			{//attack still going
				//do the trace and damage
				trace_t	trace;
				vec3_t	end, mins={-3,-3,-3}, maxs={3,3,3};
				VectorMA( NPCS.NPC->client->renderInfo.muzzlePoint, 1024, NPCS.NPC->client->renderInfo.muzzleDir, end );
				trap->Trace( &trace, NPCS.NPC->client->renderInfo.muzzlePoint, mins, maxs, end, NPCS.NPC->s.number, MASK_SHOT, qfalse, 0, 0 );
				if ( trace.allsolid || trace.startsolid )
				{//oops, in a wall
					if ( NPCS.NPCInfo->coverTarg )
					{
						G_SetOrigin( NPCS.NPCInfo->coverTarg, NPCS.NPC->client->renderInfo.muzzlePoint );
					}
				}
				else
				{//clear
					if ( trace.fraction < 1.0f )
					{//hit something
						gentity_t *traceEnt = &g_entities[trace.entityNum];
						if ( traceEnt && traceEnt->takedamage )
						{//damage it
							G_SoundAtLoc( trace.endpos, CHAN_AUTO, G_SoundIndex( "sound/weapons/galak/laserdamage.wav" ) );
							G_Damage( traceEnt, NPCS.NPC, NPCS.NPC, NPCS.NPC->client->renderInfo.muzzleDir, trace.endpos, 10, 0, MOD_UNKNOWN );
						}
					}
					if ( NPCS.NPCInfo->coverTarg )
					{
						G_SetOrigin( NPCS.NPCInfo->coverTarg, trace.endpos );
					}
					if ( !Q_irand( 0, 5 ) )
					{
						G_SoundAtLoc( trace.endpos, CHAN_AUTO, G_SoundIndex( "sound/weapons/galak/laserdamage.wav" ) );
					}
				}
			}
		}
	}
	else
	{//Okay, we're not in a special attack, see if we should switch weapons or start a special attack
		/*
		if ( NPC->s.weapon == WP_REPEATER
			&& !(NPCInfo->scriptFlags & SCF_ALT_FIRE)//using rapid-fire
			&& NPC->enemy->s.weapon == WP_SABER //enemy using saber
			&& NPC->client && (NPC->client->ps.saberEventFlags&SEF_DEFLECTED)
			&& !Q_irand( 0, 50 ) )
		{//he's deflecting my shots, switch to the laser or the lob fire for a while
			TIMER_Set( NPC, "noRapid", Q_irand( 2000, 6000 ) );
			NPCInfo->scriptFlags |= SCF_ALT_FIRE;
			NPC->alt_fire = qtrue;
			if ( NPC->locationDamage[HL_GENERIC1] > GENERATOR_HEALTH && (Q_irand( 0, 1 )||enemyDist4 < MAX_LOB_DIST_SQUARED) )
			{//shield down, use laser
				NPC_GM_StartLaser();
			}
		}
		else*/
		if (// !NPC->client->ps.powerups[PW_GALAK_SHIELD]
			1 //rwwFIXMEFIXME: just act like the shield is down til the effects and stuff are done
			&& enemyDist4 < MELEE_DIST_SQUARED
			&& InFront( NPCS.NPC->enemy->r.currentOrigin, NPCS.NPC->r.currentOrigin, NPCS.NPC->client->ps.viewangles, 0.3f )
			&& NPCS.NPC->enemy->localAnimIndex <= 1 )//within 80 and in front
		{//our shield is down, and enemy within 80, if very close, use melee attack to slap away
			if ( TIMER_Done( NPCS.NPC, "attackDelay" ) )
			{
				//animate me
				int swingAnim = BOTH_ATTACK1;
#if 0
				if ( NPC->locationDamage[HL_GENERIC1] > GENERATOR_HEALTH )
				{//generator down, use random melee
					swingAnim = Q_irand( BOTH_ATTACK4, BOTH_ATTACK5 );//smackdown or uppercut
				}
				else
				{//always knock-away
					swingAnim = BOTH_ATTACK5;//uppercut
				}
#endif
				//FIXME: swing sound
				NPC_SetAnim( NPCS.NPC, SETANIM_BOTH, swingAnim, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
				TIMER_Set( NPCS.NPC, "attackDelay", NPCS.NPC->client->ps.torsoTimer + Q_irand( 1000, 3000 ) );
				//delay the hurt until the proper point in the anim
				TIMER_Set( NPCS.NPC, "smackTime", 600 );
				NPCS.NPCInfo->blockedDebounceTime = 0;
				//FIXME: say something?
			}
		}
		else if ( !NPCS.NPC->lockCount && NPCS.NPC->locationDamage[HL_GENERIC1] > GENERATOR_HEALTH
			&& TIMER_Done( NPCS.NPC, "attackDelay" )
			&& InFront( NPCS.NPC->enemy->r.currentOrigin, NPCS.NPC->r.currentOrigin, NPCS.NPC->client->ps.viewangles, 0.3f )
			&& ((!Q_irand( 0, 10*(2-g_npcspskill.integer))&& enemyDist4 > MIN_LOB_DIST_SQUARED&& enemyDist4 < MAX_LOB_DIST_SQUARED)
				||(!TIMER_Done( NPCS.NPC, "noLob" )&&!TIMER_Done( NPCS.NPC, "noRapid" )))
			&& NPCS.NPC->enemy->s.weapon != WP_TURRET )
		{//sometimes use the laser beam attack, but only after he's taken down our generator
			shoot4 = qfalse;
			NPC_GM_StartLaser();
		}
		else if ( enemyDist4 < MIN_LOB_DIST_SQUARED
			&& (NPCS.NPC->enemy->s.weapon != WP_TURRET || Q_stricmp( "PAS", NPCS.NPC->enemy->classname ))
			&& TIMER_Done( NPCS.NPC, "noRapid" ) )//256
		{//enemy within 256
			if ( (NPCS.NPC->client->ps.weapon == WP_REPEATER) && (NPCS.NPCInfo->scriptFlags & SCF_ALT_FIRE) )
			{//shooting an explosive, but enemy too close, switch to primary fire
				NPCS.NPCInfo->scriptFlags &= ~SCF_ALT_FIRE;
				NPCS.NPC->alt_fire = qfalse;
				//FIXME: use weap raise & lower anims
				NPC_ChangeWeapon( WP_REPEATER );
			}
		}
		else if ( (enemyDist4 > MAX_LOB_DIST_SQUARED || (NPCS.NPC->enemy->s.weapon == WP_TURRET && !Q_stricmp( "PAS", NPCS.NPC->enemy->classname )))
			&& TIMER_Done( NPCS.NPC, "noLob" ) )//448
		{//enemy more than 448 away and we are ready to try lob fire again
			if ( (NPCS.NPC->client->ps.weapon == WP_REPEATER) && !(NPCS.NPCInfo->scriptFlags & SCF_ALT_FIRE) )
			{//enemy far enough away to use lobby explosives
				NPCS.NPCInfo->scriptFlags |= SCF_ALT_FIRE;
				NPCS.NPC->alt_fire = qtrue;
				//FIXME: use weap raise & lower anims
				NPC_ChangeWeapon( WP_REPEATER );
			}
		}
	}

	//can we see our target?
	if ( NPC_ClearLOS4( NPCS.NPC->enemy ) )
	{
		NPCS.NPCInfo->enemyLastSeenTime = level.time;//used here for aim debouncing, not always a clear LOS
		enemyLOS4 = qtrue;

		if ( NPCS.NPC->client->ps.weapon == WP_NONE )
		{
			enemyCS4 = qfalse;//not true, but should stop us from firing
			NPC_AimAdjust( -1 );//adjust aim worse longer we have no weapon
		}
		else
		{//can we shoot our target?
			if ( ((NPCS.NPC->client->ps.weapon == WP_REPEATER && (NPCS.NPCInfo->scriptFlags&SCF_ALT_FIRE))) && enemyDist4 < MIN_LOB_DIST_SQUARED )//256
			{
				enemyCS4 = qfalse;//not true, but should stop us from firing
				hitAlly4 = qtrue;//us!
				//FIXME: if too close, run away!
			}
			else
			{
				int hit = NPC_ShotEntity( NPCS.NPC->enemy, impactPos4 );
				gentity_t *hitEnt = &g_entities[hit];
				if ( hit == NPCS.NPC->enemy->s.number
					|| ( hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPCS.NPC->client->enemyTeam )
					|| ( hitEnt && hitEnt->takedamage ) )
				{//can hit enemy or will hit glass or other breakable, so shoot anyway
					enemyCS4 = qtrue;
					NPC_AimAdjust( 2 );//adjust aim better longer we have clear shot at enemy
					VectorCopy( NPCS.NPC->enemy->r.currentOrigin, NPCS.NPCInfo->enemyLastSeenLocation );
				}
				else
				{//Hmm, have to get around this bastard
					NPC_AimAdjust( 1 );//adjust aim better longer we can see enemy
					if ( hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPCS.NPC->client->playerTeam )
					{//would hit an ally, don't fire!!!
						hitAlly4 = qtrue;
					}
					else
					{//Check and see where our shot *would* hit... if it's not close to the enemy (within 256?), then don't fire
					}
				}
			}
		}
	}
	else if ( trap->InPVS( NPCS.NPC->enemy->r.currentOrigin, NPCS.NPC->r.currentOrigin ) )
	{
		int hit;
		gentity_t *hitEnt;

		if ( TIMER_Done( NPCS.NPC, "talkDebounce" ) && !Q_irand( 0, 10 ) )
		{
			if ( NPCS.NPCInfo->enemyCheckDebounceTime < 8 )
			{
				int speech = -1;
				switch( NPCS.NPCInfo->enemyCheckDebounceTime )
				{
				case 0:
				case 1:
				case 2:
					speech = EV_CHASE1 + NPCS.NPCInfo->enemyCheckDebounceTime;
					break;
				case 3:
				case 4:
				case 5:
					speech = EV_COVER1 + NPCS.NPCInfo->enemyCheckDebounceTime-3;
					break;
				case 6:
				case 7:
					speech = EV_ESCAPING1 + NPCS.NPCInfo->enemyCheckDebounceTime-6;
					break;
				}
				NPCS.NPCInfo->enemyCheckDebounceTime++;
				if ( speech != -1 )
				{
					G_AddVoiceEvent( NPCS.NPC, speech, Q_irand( 3000, 5000 ) );
					TIMER_Set( NPCS.NPC, "talkDebounce", Q_irand( 5000, 7000 ) );
				}
			}
		}

		NPCS.NPCInfo->enemyLastSeenTime = level.time;

		hit = NPC_ShotEntity( NPCS.NPC->enemy, impactPos4 );
		hitEnt = &g_entities[hit];
		if ( hit == NPCS.NPC->enemy->s.number
			|| ( hitEnt && hitEnt->client && hitEnt->client->playerTeam == NPCS.NPC->client->enemyTeam )
			|| ( hitEnt && hitEnt->takedamage ) )
		{//can hit enemy or will hit glass or other breakable, so shoot anyway
			enemyCS4 = qtrue;
		}
		else
		{
			faceEnemy4 = qtrue;
			NPC_AimAdjust( -1 );//adjust aim worse longer we cannot see enemy
		}
	}

	if ( enemyLOS4 )
	{
		faceEnemy4 = qtrue;
	}
	else
	{
		if ( !NPCS.NPCInfo->goalEntity )
		{
			NPCS.NPCInfo->goalEntity = NPCS.NPC->enemy;
		}
		if ( NPCS.NPCInfo->goalEntity == NPCS.NPC->enemy )
		{//for now, always chase the enemy
			move4 = qtrue;
		}
	}
	if ( enemyCS4 )
	{
		shoot4 = qtrue;
		//NPCInfo->enemyCheckDebounceTime = level.time;//actually used here as a last actual LOS
	}
	else
	{
		if ( !NPCS.NPCInfo->goalEntity )
		{
			NPCS.NPCInfo->goalEntity = NPCS.NPC->enemy;
		}
		if ( NPCS.NPCInfo->goalEntity == NPCS.NPC->enemy )
		{//for now, always chase the enemy
			move4 = qtrue;
		}
	}

	//Check for movement to take care of
	GM_CheckMoveState();

	//See if we should override shooting decision with any special considerations
	GM_CheckFireState();

	if ( NPCS.NPC->client->ps.weapon == WP_REPEATER && (NPCS.NPCInfo->scriptFlags&SCF_ALT_FIRE) && shoot4 && TIMER_Done( NPCS.NPC, "attackDelay" ) )
	{
		vec3_t	muzzle;
		vec3_t	angles;
		vec3_t	target;
		vec3_t velocity = {0,0,0};
		vec3_t mins = {-REPEATER_ALT_SIZE,-REPEATER_ALT_SIZE,-REPEATER_ALT_SIZE}, maxs = {REPEATER_ALT_SIZE,REPEATER_ALT_SIZE,REPEATER_ALT_SIZE};
		qboolean clearshot;

		CalcEntitySpot( NPCS.NPC, SPOT_WEAPON, muzzle );

		VectorCopy( NPCS.NPC->enemy->r.currentOrigin, target );

		target[0] += flrand( -5, 5 )+(Q_flrand(-1.0f, 1.0f)*(6-NPCS.NPCInfo->currentAim)*2);
		target[1] += flrand( -5, 5 )+(Q_flrand(-1.0f, 1.0f)*(6-NPCS.NPCInfo->currentAim)*2);
		target[2] += flrand( -5, 5 )+(Q_flrand(-1.0f, 1.0f)*(6-NPCS.NPCInfo->currentAim)*2);

		//Find the desired angles
		clearshot = WP_LobFire( NPCS.NPC, muzzle, target, mins, maxs, MASK_SHOT|CONTENTS_LIGHTSABER,
			velocity, qtrue, NPCS.NPC->s.number, NPCS.NPC->enemy->s.number,
			300, 1100, 1500, qtrue );
		if ( VectorCompare( vec3_origin, velocity ) || (!clearshot&&enemyLOS4&&enemyCS4)  )
		{//no clear lob shot and no lob shot that will hit something breakable
			if ( enemyLOS4 && enemyCS4 && TIMER_Done( NPCS.NPC, "noRapid" ) )
			{//have a clear straight shot, so switch to primary
				NPCS.NPCInfo->scriptFlags &= ~SCF_ALT_FIRE;
				NPCS.NPC->alt_fire = qfalse;
				NPC_ChangeWeapon( WP_REPEATER );
				//keep this weap for a bit
				TIMER_Set( NPCS.NPC, "noLob", Q_irand( 500, 1000 ) );
			}
			else
			{
				shoot4 = qfalse;
			}
		}
		else
		{
			vectoangles( velocity, angles );

			NPCS.NPCInfo->desiredYaw		= AngleNormalize360( angles[YAW] );
			NPCS.NPCInfo->desiredPitch	= AngleNormalize360( angles[PITCH] );

			VectorCopy( velocity, NPCS.NPC->client->hiddenDir );
			NPCS.NPC->client->hiddenDist = VectorNormalize ( NPCS.NPC->client->hiddenDir );
		}
	}
	else if ( faceEnemy4 )
	{//face the enemy
		NPC_FaceEnemy( qtrue );
	}

	if ( !TIMER_Done( NPCS.NPC, "standTime" ) )
	{
		move4 = qfalse;
	}
	if ( !(NPCS.NPCInfo->scriptFlags&SCF_CHASE_ENEMIES) )
	{//not supposed to chase my enemies
		if ( NPCS.NPCInfo->goalEntity == NPCS.NPC->enemy )
		{//goal is my entity, so don't move
			move4 = qfalse;
		}
	}

	if ( move4 && !NPCS.NPC->lockCount )
	{//move toward goal
		if ( NPCS.NPCInfo->goalEntity
			/*&& NPC->client->ps.legsAnim != BOTH_ALERT1
			&& NPC->client->ps.legsAnim != BOTH_ATTACK2
			&& NPC->client->ps.legsAnim != BOTH_ATTACK4
			&& NPC->client->ps.legsAnim != BOTH_ATTACK5
			&& NPC->client->ps.legsAnim != BOTH_ATTACK7*/ )
		{
			move4 = GM_Move();
		}
		else
		{
			move4 = qfalse;
		}
	}

	if ( !TIMER_Done( NPCS.NPC, "flee" ) )
	{//running away
		faceEnemy4 = qfalse;
	}

	//FIXME: check scf_face_move_dir here?

	if ( !faceEnemy4 )
	{//we want to face in the dir we're running
		if ( !move4 )
		{//if we haven't moved, we should look in the direction we last looked?
			VectorCopy( NPCS.NPC->client->ps.viewangles, NPCS.NPCInfo->lastPathAngles );
		}
		if ( move4 )
		{//don't run away and shoot
			NPCS.NPCInfo->desiredYaw = NPCS.NPCInfo->lastPathAngles[YAW];
			NPCS.NPCInfo->desiredPitch = 0;
			shoot4 = qfalse;
		}
	}
	NPC_UpdateAngles( qtrue, qtrue );

	if ( NPCS.NPCInfo->scriptFlags & SCF_DONT_FIRE )
	{
		shoot4 = qfalse;
	}

	if ( NPCS.NPC->enemy && NPCS.NPC->enemy->enemy )
	{
		if ( NPCS.NPC->enemy->s.weapon == WP_SABER && NPCS.NPC->enemy->enemy->s.weapon == WP_SABER )
		{//don't shoot at an enemy jedi who is fighting another jedi, for fear of injuring one or causing rogue blaster deflections (a la Obi Wan/Vader duel at end of ANH)
			shoot4 = qfalse;
		}
	}
	//FIXME: don't shoot right away!
	if ( shoot4 )
	{//try to shoot if it's time
		if ( TIMER_Done( NPCS.NPC, "attackDelay" ) )
		{
			if( !(NPCS.NPCInfo->scriptFlags & SCF_FIRE_WEAPON) ) // we've already fired, no need to do it again here
			{
				WeaponThink( qtrue );
			}
		}
	}

	//also:
	if ( NPCS.NPC->enemy->s.weapon == WP_TURRET && !Q_stricmp( "PAS", NPCS.NPC->enemy->classname ) )
	{//crush turrets
		if ( G_BoundsOverlap( NPCS.NPC->r.absmin, NPCS.NPC->r.absmax, NPCS.NPC->enemy->r.absmin, NPCS.NPC->enemy->r.absmax ) )
		{//have to do this test because placed turrets are not solid to NPCs (so they don't obstruct navigation)
			//if ( NPC->client->ps.powerups[PW_GALAK_SHIELD] > 0 )
			if (0)
			{
				#ifdef BASE_COMPAT
					NPCS.NPC->client->ps.powerups[PW_BATTLESUIT] = level.time + ARMOR_EFFECT_TIME;
				#endif
				G_Damage( NPCS.NPC->enemy, NPCS.NPC, NPCS.NPC, NULL, NPCS.NPC->r.currentOrigin, 100, DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN );
			}
			else
			{
				G_Damage( NPCS.NPC->enemy, NPCS.NPC, NPCS.NPC, NULL, NPCS.NPC->r.currentOrigin, 100, DAMAGE_NO_KNOCKBACK, MOD_CRUSH );
			}
		}
	}
	else if ( NPCS.NPCInfo->touchedByPlayer != NULL && NPCS.NPCInfo->touchedByPlayer == NPCS.NPC->enemy )
	{//touched enemy
		//if ( NPC->client->ps.powerups[PW_GALAK_SHIELD] > 0 )
		if (0)
		{//zap him!
			vec3_t	smackDir;

			//animate me
#if 0
			NPC_SetAnim( NPC, SETANIM_BOTH, BOTH_ATTACK6, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD );
#endif
			TIMER_Set( NPCS.NPC, "attackDelay", NPCS.NPC->client->ps.torsoTimer );
			TIMER_Set( NPCS.NPC, "standTime", NPCS.NPC->client->ps.legsTimer );
			//FIXME: debounce this?
			NPCS.NPCInfo->touchedByPlayer = NULL;
			//FIXME: some shield effect?
			#ifdef BASE_COMPAT
				NPCS.NPC->client->ps.powerups[PW_BATTLESUIT] = level.time + ARMOR_EFFECT_TIME;
			#endif

			VectorSubtract( NPCS.NPC->enemy->r.currentOrigin, NPCS.NPC->r.currentOrigin, smackDir );
			smackDir[2] += 30;
			VectorNormalize( smackDir );
			G_Damage( NPCS.NPC->enemy, NPCS.NPC, NPCS.NPC, smackDir, NPCS.NPC->r.currentOrigin, (g_npcspskill.integer+1)*Q_irand( 5, 10), DAMAGE_NO_KNOCKBACK, MOD_UNKNOWN );
			//throw them
			G_Throw( NPCS.NPC->enemy, smackDir, 100 );
			//NPC->enemy->s.powerups |= ( 1 << PW_SHOCKED );
			if ( NPCS.NPC->enemy->client )
			{
			//	NPC->enemy->client->ps.powerups[PW_SHOCKED] = level.time + 1000;
				NPCS.NPC->enemy->client->ps.electrifyTime = level.time + 1000;
			}
			//stop any attacks
			NPCS.ucmd.buttons = 0;
		}
	}

	if ( NPCS.NPCInfo->movementSpeech < 3 && NPCS.NPCInfo->blockedSpeechDebounceTime <= level.time )
	{
		if ( NPCS.NPC->enemy && NPCS.NPC->enemy->health > 0 && NPCS.NPC->enemy->painDebounceTime > level.time )
		{
			if ( NPCS.NPC->enemy->health < 50 && NPCS.NPCInfo->movementSpeech == 2 )
			{
				G_AddVoiceEvent( NPCS.NPC, EV_ANGER2, Q_irand( 2000, 4000 ) );
				NPCS.NPCInfo->movementSpeech = 3;
			}
			else if ( NPCS.NPC->enemy->health < 75 && NPCS.NPCInfo->movementSpeech == 1 )
			{
				G_AddVoiceEvent( NPCS.NPC, EV_ANGER1, Q_irand( 2000, 4000 ) );
				NPCS.NPCInfo->movementSpeech = 2;
			}
			else if ( NPCS.NPC->enemy->health < 100 && NPCS.NPCInfo->movementSpeech == 0 )
			{
				G_AddVoiceEvent( NPCS.NPC, EV_ANGER3, Q_irand( 2000, 4000 ) );
				NPCS.NPCInfo->movementSpeech = 1;
			}
		}
	}
}
Esempio n. 19
0
void LayerNet::anx_dd ( TrainingSet *tptr , struct LearnParams *lptr )
{
   int itry, n_escape, n_retry, bad_count, new_record, refined ;
   long seed ;
   double err, prev_err, best_err, start_of_loop_error, best_inner_error ;
   double initial_accuracy, final_accuracy ;
   char msg[80] ;
   LayerNet *worknet, *worknet2, *bestnet ;

   n_escape = n_retry = 0 ;

/*
   Allocate scratch memory
*/

   MEMTEXT ( "ANX_DD::learn new worknet, bestnet" ) ;
   worknet = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                            nout , 0 , 0 ) ;
   bestnet = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                            nout , 0 , 1 ) ;

   if ((worknet == NULL)  ||  (! worknet->ok)
    || (bestnet == NULL)  ||  (! bestnet->ok)) {
      memory_message ( "to learn" ) ;
      if (worknet != NULL)
         delete worknet ;
      if (bestnet != NULL)
         delete bestnet ;
      errtype = 0 ;
      return ;
      }

   if ((lptr->method == METHOD_AN2_CJ)  ||  (lptr->method == METHOD_AN2_LM)) {
      worknet2 = new LayerNet ( model , outmod , outlin , nin , nhid1 , nhid2 ,
                                nout , 0 , 0 ) ;
      if ((worknet2 == NULL)  ||  (! worknet2->ok)) {
         if (worknet2 != NULL)
            delete worknet2 ;
         delete worknet ;
         delete bestnet ;
         memory_message ( "to learn" ) ;
         errtype = 0 ;
         return ;
         }
      }
   else
      worknet2 = NULL ;

/*
   Start by annealing around the starting weights.  These will be zero if the
   net was just created.  If it was restored or partially trained already,
   they will be meaningful.  Anneal1 guarantees that it will not return all
   zero weights if there is at least one hidden layer, even if that means
   that the error exceeds the amount that could be attained by all zeros.
*/

   best_err = best_inner_error = 1.e30 ;
   if ((lptr->method == METHOD_AN1_CJ)  ||  (lptr->method == METHOD_AN1_LM))
      anneal1 ( tptr , lptr , worknet , 1 , 0 ) ;
   else if ((lptr->method == METHOD_AN2_CJ) || (lptr->method == METHOD_AN2_LM))
      anneal2 ( tptr , lptr , worknet , worknet2 , 1 ) ;

/*
   Do direct descent optimization, finding local minimum.
   Then anneal to break out of it.  If successful, loop back up to
   do direct descent again.  Otherwise restart totally random.
*/

   bad_count = 0 ;         // Handles flat local mins
   refined = 0 ;           // Did we ever refine to high resolution?  Not yet.
   new_record = 0 ;        // Refine every time a new inner error record set
   initial_accuracy = pow ( 10.0 , -lptr->cj_acc ) ;
   final_accuracy = initial_accuracy * pow ( 10.0 , -lptr->cj_refine ) ;

   for (itry=1 ; ; itry++) {

      if (neterr < best_err) {   // Keep track of best
         copy_weights ( bestnet , this ) ;
         best_err = neterr ;
         }

      sprintf ( msg , "Try %d  (best=%lf):", itry, best_err ) ;
      normal_message ( msg ) ;

      if (neterr <= lptr->quit_err)
         break ;

      start_of_loop_error = neterr ;
      if ((lptr->method == METHOD_AN1_CJ)  ||  (lptr->method == METHOD_AN2_CJ))
         err = conjgrad ( tptr , 32767 , initial_accuracy ,
                          lptr->quit_err , lptr->cj_progress ) ;
      else if ((lptr->method==METHOD_AN1_LM) || (lptr->method==METHOD_AN2_LM))
         err = lev_marq ( tptr , 32767 , initial_accuracy ,
                          lptr->quit_err , lptr->cj_progress ) ;
      neterr = fabs ( err ) ; // err<0 if user pressed ESCape

      sprintf ( msg , "  Gradient err=%lf", neterr ) ;
      progress_message ( msg ) ;

      if (neterr < best_err) {   // Keep track of best
         copy_weights ( bestnet , this ) ;
         best_err = neterr ;
         }

      if (err <= lptr->quit_err) { // err<0 if user pressed ESCape
         if (err < -1.e29)         // or insufficient memory
            printf ( "\nInsufficient memory for gradient learning." ) ;
         break ;
         }

      seed = flrand() - (long) (itry * 97) ;   // Insure new seed for anneal
      sflrand ( seed ) ;

      prev_err = neterr ;  // So we can see if anneal helped

      if ((lptr->method == METHOD_AN1_CJ)  ||  (lptr->method == METHOD_AN1_LM))
         anneal1 ( tptr , lptr , worknet , 0 , itry ) ;
      else if ((lptr->method==METHOD_AN2_CJ) || (lptr->method==METHOD_AN2_LM))
         anneal2 ( tptr , lptr , worknet , worknet2 , 0 ) ;

      sprintf ( msg , "  Anneal err=%lf", neterr ) ;
      progress_message ( msg ) ;

      if (neterr < best_err) {  // Keep track of best
         copy_weights ( bestnet , this ) ;
         best_err = neterr ;
         }

      if (best_err <= lptr->quit_err)
         break ;

      if (neterr < best_inner_error) {  // Keep track of best inner for refine
         best_inner_error = neterr ;
         new_record = 1 ;               // Tells us to refine
         }

      if ((prev_err - neterr) > 1.e-7) { // Did we break out of local min?
         if ((start_of_loop_error - neterr) < 1.e-3)
            ++bad_count ;  // Avoid many unprofitable iters
         else
            bad_count = 0 ;
         if (bad_count < 4) {
            ++n_escape ;          // Count escapes from local min
            continue ;            // Escaped, so gradient learn again
            }
         }

/*
   After first few tries, and after each inprovement thereafter, refine
   to high resolution
*/

      if ((itry-n_escape >= lptr->cj_pretries)  &&  (new_record || ! refined)) {
         if (! refined) {   // If refining the best of the pretries
            copy_weights ( this , bestnet ) ;  // Get that net
            neterr = best_err ;
            }
         refined = 1 ;     // Only force refine once
         new_record = 0 ;  // Reset new inner error record flag
         progress_message ( "  REFINING" ) ;
         if ((lptr->method == METHOD_AN1_CJ) || (lptr->method == METHOD_AN2_CJ))
            err = conjgrad ( tptr , 0 , final_accuracy ,
                             lptr->quit_err , lptr->cj_progress ) ;
         else if ((lptr->method==METHOD_AN1_LM)|| (lptr->method==METHOD_AN2_LM))
            err = lev_marq ( tptr , 0 , final_accuracy ,
                             lptr->quit_err , lptr->cj_progress ) ;
         neterr = fabs ( err ) ; // err<0 if user pressed ESCape
         sprintf ( msg , "  Attained err=%lf", neterr ) ;
         progress_message ( msg ) ;
         if (neterr < best_err) {  // Keep track of best
            copy_weights ( bestnet , this ) ;
            best_err = neterr ;
            }
         }

      if (++n_retry > lptr->retries)
         break ;

      progress_message ( "  RESTART" ) ;
      zero_weights () ;  // Failed to break out, so retry random
      seed = flrand() - (long) (itry * 773) ;   // Insure new seed for anneal
      sflrand ( seed ) ;
      if ((lptr->method == METHOD_AN1_CJ)  ||  (lptr->method == METHOD_AN1_LM))
         anneal1 ( tptr , lptr , worknet , 1 , itry ) ;
      else if ((lptr->method==METHOD_AN2_CJ) || (lptr->method==METHOD_AN2_LM))
         anneal2 ( tptr , lptr , worknet , worknet2 , 1 ) ;
      }

FINISH:
   copy_weights ( this , bestnet ) ;
   neterr = best_err ;
   MEMTEXT ( "AN1_DD::learn delete worknet, bestnet" ) ;
   delete worknet ;
   delete bestnet ;
   sprintf ( msg , "%d successful escapes, %d retries", n_escape, n_retry ) ;
   normal_message ( msg ) ;

   return ;
}
Esempio n. 20
0
//------------------------------------
void Seeker_MaintainHeight( void )
{
	float	dif;

	// Update our angles regardless
	NPC_UpdateAngles( qtrue, qtrue );

	// If we have an enemy, we should try to hover at or a little below enemy eye level
	if ( NPCS.NPC->enemy )
	{
		if (TIMER_Done( NPCS.NPC, "heightChange" ))
		{
			float difFactor;

			TIMER_Set( NPCS.NPC,"heightChange",Q_irand( 1000, 3000 ));

			// Find the height difference
			dif = (NPCS.NPC->enemy->r.currentOrigin[2] +  flrand( NPCS.NPC->enemy->r.maxs[2]/2, NPCS.NPC->enemy->r.maxs[2]+8 )) - NPCS.NPC->r.currentOrigin[2];

			difFactor = 1.0f;
			if ( NPCS.NPC->client->NPC_class == CLASS_BOBAFETT )
			{
				if ( TIMER_Done( NPCS.NPC, "flameTime" ) )
				{
					difFactor = 10.0f;
				}
			}

			// cap to prevent dramatic height shifts
			if ( fabs( dif ) > 2*difFactor )
			{
				if ( fabs( dif ) > 24*difFactor )
				{
					dif = ( dif < 0 ? -24*difFactor : 24*difFactor );
				}

				NPCS.NPC->client->ps.velocity[2] = (NPCS.NPC->client->ps.velocity[2]+dif)/2;
			}
			if ( NPCS.NPC->client->NPC_class == CLASS_BOBAFETT )
			{
				NPCS.NPC->client->ps.velocity[2] *= flrand( 0.85f, 3.0f );
			}
		}
	}
	else
	{
		gentity_t *goal = NULL;

		if ( NPCS.NPCInfo->goalEntity )	// Is there a goal?
		{
			goal = NPCS.NPCInfo->goalEntity;
		}
		else
		{
			goal = NPCS.NPCInfo->lastGoalEntity;
		}
		if ( goal )
		{
			dif = goal->r.currentOrigin[2] - NPCS.NPC->r.currentOrigin[2];

			if ( fabs( dif ) > 24 )
			{
				NPCS.ucmd.upmove = ( NPCS.ucmd.upmove < 0 ? -4 : 4 );
			}
			else
			{
				if ( NPCS.NPC->client->ps.velocity[2] )
				{
					NPCS.NPC->client->ps.velocity[2] *= VELOCITY_DECAY;

					if ( fabs( NPCS.NPC->client->ps.velocity[2] ) < 2 )
					{
						NPCS.NPC->client->ps.velocity[2] = 0;
					}
				}
			}
		}
	}

	// Apply friction
	if ( NPCS.NPC->client->ps.velocity[0] )
	{
		NPCS.NPC->client->ps.velocity[0] *= VELOCITY_DECAY;

		if ( fabs( NPCS.NPC->client->ps.velocity[0] ) < 1 )
		{
			NPCS.NPC->client->ps.velocity[0] = 0;
		}
	}

	if ( NPCS.NPC->client->ps.velocity[1] )
	{
		NPCS.NPC->client->ps.velocity[1] *= VELOCITY_DECAY;

		if ( fabs( NPCS.NPC->client->ps.velocity[1] ) < 1 )
		{
			NPCS.NPC->client->ps.velocity[1] = 0;
		}
	}
}
Esempio n. 21
0
void CG_Chunks( int owner, vec3_t origin, const vec3_t normal, const vec3_t mins, const vec3_t maxs, 
						float speed, int numChunks, material_t chunkType, int customChunk, float baseScale )
{
	localEntity_t	*le;
	refEntity_t		*re;
	vec3_t			dir;
	int				i, j, k;
	int				chunkModel = 0;
	leBounceSoundType_t	bounce = LEBS_NONE;
	float			r, speedMod = 1.0f;
	qboolean		chunk = qfalse;

	if ( chunkType == MAT_NONE )
	{
		// Well, we should do nothing
		return;
	}

	// Set up our chunk sound info...breaking sounds are done here so they are done once on breaking..some return instantly because the chunks are done with effects instead of models
	switch( chunkType )
	{
	default:
		break;
	case MAT_GLASS:
		trap->S_StartSound( NULL, owner, CHAN_BODY, cgs.media.glassChunkSound );
		return;
		break;
	case MAT_GRATE1:
		trap->S_StartSound( NULL, owner, CHAN_BODY, cgs.media.grateSound );
		return;
		break;
	case MAT_ELECTRICAL:// (sparks)
		trap->S_StartSound( NULL, owner, CHAN_BODY, trap->S_RegisterSound (va("sound/ambience/spark%d.wav", Q_irand(1, 6))) );
		return;
		break;
	case MAT_DRK_STONE:
	case MAT_LT_STONE:
	case MAT_GREY_STONE:
	case MAT_WHITE_METAL:  // not quite sure what this stuff is supposed to be...it's for Stu
	case MAT_SNOWY_ROCK:
		trap->S_StartSound( NULL, owner, CHAN_BODY, cgs.media.rockBreakSound );
		bounce = LEBS_ROCK;
		speedMod = 0.5f; // rock blows up less
		break;
	case MAT_GLASS_METAL:
		trap->S_StartSound( NULL, owner, CHAN_BODY, cgs.media.glassChunkSound ); // FIXME: should probably have a custom sound
		bounce = LEBS_METAL;
		break;
	case MAT_CRATE1:
	case MAT_CRATE2:
		trap->S_StartSound( NULL, owner, CHAN_BODY, cgs.media.crateBreakSound[Q_irand(0,1)] );
		break;
	case MAT_METAL:
	case MAT_METAL2:
	case MAT_METAL3:
	case MAT_ELEC_METAL:// FIXME: maybe have its own sound?
		trap->S_StartSound( NULL, owner, CHAN_BODY, cgs.media.chunkSound );
		bounce = LEBS_METAL;
		speedMod = 0.8f; // metal blows up a bit more
		break;
	case MAT_ROPE:
//		trap->S_StartSound( NULL, owner, CHAN_BODY, cgi_S_RegisterSound( "" ));  FIXME:  needs a sound
		return;
		break;
	}

	if ( baseScale <= 0.0f )
	{
		baseScale = 1.0f;
	}

	// Chunks
	for( i = 0; i < numChunks; i++ )
	{
		if ( customChunk > 0 )
		{
			// Try to use a custom chunk.
			if ( cgs.gameModels[customChunk] )
			{
				chunk = qtrue;
				chunkModel = cgs.gameModels[customChunk];
			}
		}

		if ( !chunk )
		{
			// No custom chunk.  Pick a random chunk type at run-time so we don't get the same chunks
			switch( chunkType )
			{
			default:
				break;
			case MAT_METAL2: //bluegrey
				chunkModel = cgs.media.chunkModels[CHUNK_METAL2][Q_irand(0, 3)];
				break;
			case MAT_GREY_STONE://gray
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK1][Q_irand(0, 3)];
				break;
			case MAT_LT_STONE: //tan
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK2][Q_irand(0, 3)];
				break;
			case MAT_DRK_STONE://brown
				chunkModel = cgs.media.chunkModels[CHUNK_ROCK3][Q_irand(0, 3)];
				break;
			case MAT_SNOWY_ROCK://gray & brown
				if ( Q_irand( 0, 1 ) )
				{
					chunkModel = cgs.media.chunkModels[CHUNK_ROCK1][Q_irand(0, 3)];
				}
				else
				{
					chunkModel = cgs.media.chunkModels[CHUNK_ROCK3][Q_irand(0, 3)];
				}
				break;
			case MAT_WHITE_METAL:
				chunkModel = cgs.media.chunkModels[CHUNK_WHITE_METAL][Q_irand(0, 3)];
				break;
			case MAT_CRATE1://yellow multi-colored crate chunks
				chunkModel = cgs.media.chunkModels[CHUNK_CRATE1][Q_irand(0, 3)];
				break;
			case MAT_CRATE2://red multi-colored crate chunks
				chunkModel = cgs.media.chunkModels[CHUNK_CRATE2][Q_irand(0, 3)];
				break;
			case MAT_ELEC_METAL:
			case MAT_GLASS_METAL:
			case MAT_METAL://grey
				chunkModel = cgs.media.chunkModels[CHUNK_METAL1][Q_irand(0, 3)];
				break;
			case MAT_METAL3:
				if ( rand() & 1 )
				{
					chunkModel = cgs.media.chunkModels[CHUNK_METAL1][Q_irand(0, 3)];
				}
				else
				{
					chunkModel = cgs.media.chunkModels[CHUNK_METAL2][Q_irand(0, 3)];
				}
				break;
			}
		}

		// It wouldn't look good to throw a bunch of RGB axis models...so make sure we have something to work with.
		if ( chunkModel )
		{
			le = CG_AllocLocalEntity();
			re = &le->refEntity;

			re->hModel = chunkModel;
			le->leType = LE_FRAGMENT;
			le->endTime = cg.time + 1300 + random() * 900;

			// spawn chunk roughly in the bbox of the thing...bias towards center in case thing blowing up doesn't complete fill its bbox.
			for( j = 0; j < 3; j++ )
			{
				r = random() * 0.8f + 0.1f;
				re->origin[j] = ( r * mins[j] + ( 1 - r ) * maxs[j] );
			}
			VectorCopy( re->origin, le->pos.trBase );

			// Move out from center of thing, otherwise you can end up things moving across the brush in an undesirable direction.  Visually looks wrong
			VectorSubtract( re->origin, origin, dir );
			VectorNormalize( dir );
			VectorScale( dir, flrand( speed * 0.5f, speed * 1.25f ) * speedMod, le->pos.trDelta );

			// Angular Velocity
			VectorSet( le->angles.trBase, random() * 360, random() * 360, random() * 360 );

			le->angles.trDelta[0] = crandom();
			le->angles.trDelta[1] = crandom();
			le->angles.trDelta[2] = 0; // don't do roll

			VectorScale( le->angles.trDelta, random() * 600.0f + 200.0f, le->angles.trDelta );

			le->pos.trType = TR_GRAVITY;
			le->angles.trType = TR_LINEAR;
			le->pos.trTime = le->angles.trTime = cg.time;
			le->bounceFactor = 0.2f + random() * 0.2f;
			le->leFlags |= LEF_TUMBLE;
			//le->ownerGentNum = owner;
			le->leBounceSoundType = bounce; 

			// Make sure that we have the desired start size set
			le->radius = flrand( baseScale * 0.75f, baseScale * 1.25f );
			re->nonNormalizedAxes = qtrue;
			AxisCopy( axisDefault, re->axis ); // could do an angles to axis, but this is cheaper and works ok
			for( k = 0; k < 3; k++ )
			{
				re->modelScale[k] = le->radius;
			}
			ScaleModelAxis(re);
			/*
			for( k = 0; k < 3; k++ )
			{
				VectorScale( re->axis[k], le->radius, re->axis[k] );
			}
			*/
		}
	}
}
Esempio n. 22
0
void Rancor_Swing( qboolean tryGrab )
{
	int			radiusEntNums[128];
	int			numEnts;
	const float	radius = 88;
	const float	radiusSquared = (radius*radius);
	int			i;
	vec3_t		boltOrg;

	numEnts = NPC_GetEntsNearBolt( radiusEntNums, radius, NPCS.NPC->client->renderInfo.handRBolt, boltOrg );

	for ( i = 0; i < numEnts; i++ )
	{
		gentity_t *radiusEnt = &g_entities[radiusEntNums[i]];
		if ( !radiusEnt->inuse )
		{
			continue;
		}
		
		if ( radiusEnt == NPCS.NPC )
		{//Skip the rancor ent
			continue;
		}
		
		if ( radiusEnt->client == NULL )
		{//must be a client
			continue;
		}

		if ( (radiusEnt->client->ps.eFlags2&EF2_HELD_BY_MONSTER) )
		{//can't be one already being held
			continue;
		}
		
		if ( DistanceSquared( radiusEnt->r.currentOrigin, boltOrg ) <= radiusSquared )
		{
			if ( tryGrab 
				&& NPCS.NPC->count != 1 //don't have one in hand or in mouth already - FIXME: allow one in hand and any number in mouth!
				&& radiusEnt->client->NPC_class != CLASS_RANCOR
				&& radiusEnt->client->NPC_class != CLASS_GALAKMECH
				&& radiusEnt->client->NPC_class != CLASS_ATST
				&& radiusEnt->client->NPC_class != CLASS_GONK
				&& radiusEnt->client->NPC_class != CLASS_R2D2
				&& radiusEnt->client->NPC_class != CLASS_R5D2
				&& radiusEnt->client->NPC_class != CLASS_MARK1
				&& radiusEnt->client->NPC_class != CLASS_MARK2
				&& radiusEnt->client->NPC_class != CLASS_MOUSE
				&& radiusEnt->client->NPC_class != CLASS_PROBE
				&& radiusEnt->client->NPC_class != CLASS_SEEKER
				&& radiusEnt->client->NPC_class != CLASS_REMOTE
				&& radiusEnt->client->NPC_class != CLASS_SENTRY
				&& radiusEnt->client->NPC_class != CLASS_INTERROGATOR
				&& radiusEnt->client->NPC_class != CLASS_VEHICLE )
			{//grab
				if ( NPCS.NPC->count == 2 )
				{//have one in my mouth, remove him
					TIMER_Remove( NPCS.NPC, "clearGrabbed" );
					Rancor_DropVictim( NPCS.NPC );
				}
				NPCS.NPC->enemy = radiusEnt;//make him my new best friend
				radiusEnt->client->ps.eFlags2 |= EF2_HELD_BY_MONSTER;
				//FIXME: this makes it so that the victim can't hit us with shots!  Just use activator or something
				radiusEnt->client->ps.hasLookTarget = qtrue;
				radiusEnt->client->ps.lookTarget = NPCS.NPC->s.number;
				NPCS.NPC->activator = radiusEnt;//remember him
				NPCS.NPC->count = 1;//in my hand
				//wait to attack
				TIMER_Set( NPCS.NPC, "attacking", NPCS.NPC->client->ps.legsTimer + Q_irand(500, 2500) );
				if ( radiusEnt->health > 0 && radiusEnt->pain )
				{//do pain on enemy
					radiusEnt->pain( radiusEnt, NPCS.NPC, 100 );
					//GEntity_PainFunc( radiusEnt, NPC, NPC, radiusEnt->r.currentOrigin, 0, MOD_CRUSH );
				}
				else if ( radiusEnt->client )
				{
					radiusEnt->client->ps.forceHandExtend = HANDEXTEND_NONE;
					radiusEnt->client->ps.forceHandExtendTime = 0;
					NPC_SetAnim( radiusEnt, SETANIM_BOTH, BOTH_SWIM_IDLE1, SETANIM_FLAG_OVERRIDE | SETANIM_FLAG_HOLD );
				}
			}
			else
			{//smack
				vec3_t pushDir;
				vec3_t angs;

				G_Sound( radiusEnt, CHAN_AUTO, G_SoundIndex( "sound/chars/rancor/swipehit.wav" ) );
				//actually push the enemy
				/*
				//VectorSubtract( radiusEnt->r.currentOrigin, boltOrg, pushDir );
				VectorSubtract( radiusEnt->r.currentOrigin, NPC->r.currentOrigin, pushDir );
				pushDir[2] = Q_flrand( 100, 200 );
				VectorNormalize( pushDir );
				*/
				VectorCopy( NPCS.NPC->client->ps.viewangles, angs );
				angs[YAW] += flrand( 25, 50 );
				angs[PITCH] = flrand( -25, -15 );
				AngleVectors( angs, pushDir, NULL, NULL );
				if ( radiusEnt->client->NPC_class != CLASS_RANCOR
					&& radiusEnt->client->NPC_class != CLASS_ATST )
				{
					G_Damage( radiusEnt, NPCS.NPC, NPCS.NPC, vec3_origin, radiusEnt->r.currentOrigin, Q_irand( 25, 40 ), DAMAGE_NO_ARMOR|DAMAGE_NO_KNOCKBACK, MOD_MELEE );
					G_Throw( radiusEnt, pushDir, 250 );
					if ( radiusEnt->health > 0 )
					{//do pain on enemy
						G_Knockdown( radiusEnt );//, NPC, pushDir, 100, qtrue );
					}
				}
			}
		}
	}
}
Esempio n. 23
0
//-----------------------------------------------------
static void turret_aim( gentity_t *self )
//-----------------------------------------------------
{
	vec3_t	enemyDir, org, org2;
	vec3_t	desiredAngles, setAngle;
	float	diffYaw = 0.0f, diffPitch = 0.0f, turnSpeed;
	const float pitchCap = 40.0f;
	gentity_t *top = &g_entities[self->r.ownerNum];
	if ( !top )
	{
		return;
	}

	// move our gun base yaw to where we should be at this time....
	BG_EvaluateTrajectory( &top->s.apos, level.time, top->r.currentAngles );
	top->r.currentAngles[YAW] = AngleNormalize180( top->r.currentAngles[YAW] );
	top->r.currentAngles[PITCH] = AngleNormalize180( top->r.currentAngles[PITCH] );
	turnSpeed = top->speed;

	if ( self->painDebounceTime > level.time )
	{
		desiredAngles[YAW] = top->r.currentAngles[YAW]+flrand(-45,45);
		desiredAngles[PITCH] = top->r.currentAngles[PITCH]+flrand(-10,10);

		if (desiredAngles[PITCH] < -pitchCap)
		{
			desiredAngles[PITCH] = -pitchCap;
		}
		else if (desiredAngles[PITCH] > pitchCap)
		{
			desiredAngles[PITCH] = pitchCap;
		}

		diffYaw = AngleSubtract( desiredAngles[YAW], top->r.currentAngles[YAW] );
		diffPitch = AngleSubtract( desiredAngles[PITCH], top->r.currentAngles[PITCH] );
		turnSpeed = flrand( -5, 5 );
	}
	else if ( self->enemy )
	{
		// ...then we'll calculate what new aim adjustments we should attempt to make this frame
		// Aim at enemy
		VectorCopy( self->enemy->r.currentOrigin, org );
		org[2]+=self->enemy->r.maxs[2]*0.5f;
		if (self->enemy->s.eType == ET_NPC &&
			self->enemy->s.NPC_class == CLASS_VEHICLE &&
			self->enemy->m_pVehicle &&
			self->enemy->m_pVehicle->m_pVehicleInfo->type == VH_WALKER)
		{ //hack!
			org[2] += 32.0f;
		}
		/*
		mdxaBone_t	boltMatrix;

		// Getting the "eye" here
		gi.G2API_GetBoltMatrix( self->ghoul2, self->playerModel, 
					self->torsoBolt,
					&boltMatrix, self->r.currentAngles, self->s.origin, (cg.time?cg.time:level.time),
					NULL, self->s.modelScale );

		gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, org2 );
		*/
		VectorCopy( top->r.currentOrigin, org2 );

		VectorSubtract( org, org2, enemyDir );
		vectoangles( enemyDir, desiredAngles );
		desiredAngles[PITCH] = AngleNormalize180(desiredAngles[PITCH]);

		if (desiredAngles[PITCH] < -pitchCap)
		{
			desiredAngles[PITCH] = -pitchCap;
		}
		else if (desiredAngles[PITCH] > pitchCap)
		{
			desiredAngles[PITCH] = pitchCap;
		}

		diffYaw = AngleSubtract( desiredAngles[YAW], top->r.currentAngles[YAW] );
		diffPitch = AngleSubtract( desiredAngles[PITCH], top->r.currentAngles[PITCH] );
	}
	else
	{//FIXME: Pan back and forth in original facing
		// no enemy, so make us slowly sweep back and forth as if searching for a new one
		desiredAngles[YAW] = sin( level.time * 0.0001f + top->count );
		desiredAngles[YAW] *=  60.0f;
		desiredAngles[YAW] += self->s.angles[YAW];
		desiredAngles[YAW] = AngleNormalize180( desiredAngles[YAW] );
		diffYaw = AngleSubtract( desiredAngles[YAW], top->r.currentAngles[YAW] );
		diffPitch = AngleSubtract( 0, top->r.currentAngles[PITCH] );
		turnSpeed = 1.0f;
	}

	if ( diffYaw )
	{
		// cap max speed....
		if ( fabs(diffYaw) > turnSpeed )
		{
			diffYaw = ( diffYaw >= 0 ? turnSpeed : -turnSpeed );
		}
	}
	if ( diffPitch )
	{
		if ( fabs(diffPitch) > turnSpeed )
		{
			// cap max speed
			diffPitch = (diffPitch > 0.0f ? turnSpeed : -turnSpeed );
		}
	}
	// ...then set up our desired yaw
	VectorSet( setAngle, diffPitch, diffYaw, 0 );

	VectorCopy( top->r.currentAngles, top->s.apos.trBase );
	VectorScale( setAngle, (1000/FRAMETIME), top->s.apos.trDelta );
	top->s.apos.trTime = level.time;
	top->s.apos.trType = TR_LINEAR_STOP;
	top->s.apos.trDuration = FRAMETIME;

	if ( diffYaw || diffPitch )
	{
		top->s.loopSound = G_SoundIndex( "sound/vehicles/weapons/hoth_turret/turn.wav" );
	}
	else
	{
		top->s.loopSound = 0;
	}
}
Esempio n. 24
0
void G_KickSomeMofos(gentity_t *ent)
{
	vec3_t	kickDir, kickEnd, fwdAngs;
	float animLength = BG_AnimLength( ent->localAnimIndex, (animNumber_t)ent->client->ps.legsAnim );
	float elapsedTime = (float)(animLength-ent->client->ps.legsTimer);
	float remainingTime = (animLength-elapsedTime);
	float kickDist = (ent->r.maxs[0]*1.5f)+STAFF_KICK_RANGE+8.0f;//fudge factor of 8
	int	  kickDamage = Q_irand(10, 15);//Q_irand( 3, 8 ); //since it can only hit a guy once now
	int	  kickPush = flrand( 50.0f, 100.0f );
	qboolean doKick = qfalse;
	renderInfo_t *ri = &ent->client->renderInfo;

	VectorSet(kickDir, 0.0f, 0.0f, 0.0f);
	VectorSet(kickEnd, 0.0f, 0.0f, 0.0f);
	VectorSet(fwdAngs, 0.0f, ent->client->ps.viewangles[YAW], 0.0f);

	//HMM... or maybe trace from origin to footRBolt/footLBolt?  Which one?  G2 trace?  Will do hitLoc, if so...
	if ( ent->client->ps.torsoAnim == BOTH_A7_HILT )
	{
		if ( elapsedTime >= 250 && remainingTime >= 250 )
		{//front
			doKick = qtrue;
			if ( ri->handRBolt != -1 )
			{//actually trace to a bolt
				G_GetBoltPosition( ent, ri->handRBolt, kickEnd, 0 );
				VectorSubtract( kickEnd, ent->client->ps.origin, kickDir );
				kickDir[2] = 0;//ah, flatten it, I guess...
				VectorNormalize( kickDir );
			}
			else
			{//guess
				AngleVectors( fwdAngs, kickDir, NULL, NULL );
			}
		}
	}
	else
	{
		switch ( ent->client->ps.legsAnim )
		{
		case BOTH_GETUP_BROLL_B:
		case BOTH_GETUP_BROLL_F:
		case BOTH_GETUP_FROLL_B:
		case BOTH_GETUP_FROLL_F:
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//front
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->client->ps.origin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_F_AIR:
		case BOTH_A7_KICK_B_AIR:
		case BOTH_A7_KICK_R_AIR:
		case BOTH_A7_KICK_L_AIR:
			if ( elapsedTime >= 100 && remainingTime >= 250 )
			{//air
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_F:
			//FIXME: push forward?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//front
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_B:
			//FIXME: push back?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//back
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_R:
			//FIXME: push right?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//right
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
			}
			break;
		case BOTH_A7_KICK_L:
			//FIXME: push left?
			if ( elapsedTime >= 250 && remainingTime >= 250 )
			{//left
				doKick = qtrue;
				if ( ri->footLBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footLBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_S:
			kickPush = flrand( 75.0f, 125.0f );
			if ( ri->footRBolt != -1 )
			{//actually trace to a bolt
				if ( elapsedTime >= 550 
					&& elapsedTime <= 1050 )
				{
					doKick = qtrue;
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8.0f, kickDir, kickEnd );
				}
			}
			else
			{//guess
				if ( elapsedTime >= 400 && elapsedTime < 500 )
				{//front
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 500 && elapsedTime < 600 )
				{//front-right?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 600 && elapsedTime < 700 )
				{//right
					doKick = qtrue;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
				else if ( elapsedTime >= 700 && elapsedTime < 800 )
				{//back-right?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
				else if ( elapsedTime >= 800 && elapsedTime < 900 )
				{//back
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
				else if ( elapsedTime >= 900 && elapsedTime < 1000 )
				{//back-left?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 1000 && elapsedTime < 1100 )
				{//left
					doKick = qtrue;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
				else if ( elapsedTime >= 1100 && elapsedTime < 1200 )
				{//front-left?
					doKick = qtrue;
					fwdAngs[YAW] += 45;
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_BF:
			kickPush = flrand( 75.0f, 125.0f );
			kickDist += 20.0f;
			if ( elapsedTime < 1500 )
			{//auto-aim!
	//			overridAngles = PM_AdjustAnglesForBFKick( ent, ucmd, fwdAngs, qboolean(elapsedTime<850) )?qtrue:overridAngles;
				//FIXME: if we haven't done the back kick yet and there's no-one there to
				//			kick anymore, go into some anim that returns us to our base stance
			}
			if ( ri->footRBolt != -1 )
			{//actually trace to a bolt
				if ( ( elapsedTime >= 750 && elapsedTime < 850 )
					|| ( elapsedTime >= 1400 && elapsedTime < 1500 ) )
				{//right, though either would do
					doKick = qtrue;
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8, kickDir, kickEnd );
				}
			}
			else
			{//guess
				if ( elapsedTime >= 250 && elapsedTime < 350 )
				{//front
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
				}
				else if ( elapsedTime >= 350 && elapsedTime < 450 )
				{//back
					doKick = qtrue;
					AngleVectors( fwdAngs, kickDir, NULL, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		case BOTH_A7_KICK_RL:
			kickPush = flrand( 75.0f, 125.0f );
			kickDist += 10.0f;

			//ok, I'm tracing constantly on these things, they NEVER hit otherwise (in MP at least)

			//FIXME: auto aim at enemies on the side of us?
			//overridAngles = PM_AdjustAnglesForRLKick( ent, ucmd, fwdAngs, qboolean(elapsedTime<850) )?qtrue:overridAngles;
			//if ( elapsedTime >= 250 && elapsedTime < 350 )
			if (level.framenum&1)
			{//right
				doKick = qtrue;
				if ( ri->footRBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footRBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8, kickDir, kickEnd );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
				}
			}
			//else if ( elapsedTime >= 350 && elapsedTime < 450 )
			else
			{//left
				doKick = qtrue;
				if ( ri->footLBolt != -1 )
				{//actually trace to a bolt
					G_GetBoltPosition( ent, ri->footLBolt, kickEnd, 0 );
					VectorSubtract( kickEnd, ent->r.currentOrigin, kickDir );
					kickDir[2] = 0;//ah, flatten it, I guess...
					VectorNormalize( kickDir );
					//NOTE: have to fudge this a little because it's not getting enough range with the anim as-is
					VectorMA( kickEnd, 8, kickDir, kickEnd );
				}
				else
				{//guess
					AngleVectors( fwdAngs, NULL, kickDir, NULL );
					VectorScale( kickDir, -1, kickDir );
				}
			}
			break;
		}
	}

	if ( doKick )
	{
//		G_KickTrace( ent, kickDir, kickDist, kickEnd, kickDamage, kickPush );
		G_KickTrace( ent, kickDir, kickDist, NULL, kickDamage, kickPush );
	}
}
Esempio n. 25
0
void CG_FragmentBounceMark( localEntity_t *le, trace_t *trace ) {
		 if ( le->leMarkType == LEMT_BLOOD )	CG_ImpactMark( cgs.media.bloodMarkShader, &trace->endpos, &trace->plane.normal, random()*360, 1, 1, 1, 1, qtrue, 16.0f+flrand( 0, 31 ), qfalse );
	else if ( le->leMarkType == LEMT_BURN )		CG_ImpactMark( cgs.media.burnMarkShader, &trace->endpos, &trace->plane.normal, random()*360, 1, 1, 1, 1, qtrue, 8.0f+flrand( 0, 15 ), qfalse );

	le->leMarkType = LEMT_NONE; // don't allow a fragment to make multiple marks, or they pile up while settling
}
Esempio n. 26
0
//----------------------------------------------------------------
static void turretG2_fire ( gentity_t *ent, vec3_t start, vec3_t dir )
//----------------------------------------------------------------
{
    vec3_t		org, ang;
    gentity_t	*bolt;

    if ( (trap_PointContents( start, ent->s.number )&MASK_SHOT) )
    {
        return;
    }

    VectorMA( start, -START_DIS, dir, org ); // dumb....

    if ( ent->random )
    {
        vectoangles( dir, ang );
        ang[PITCH] += flrand( -ent->random, ent->random );
        ang[YAW] += flrand( -ent->random, ent->random );
        AngleVectors( ang, dir, NULL, NULL );
    }

    vectoangles(dir, ang);

    if ( (ent->spawnflags&SPF_TURRETG2_TURBO) )
    {
        //muzzle flash
        G_PlayEffectID( ent->genericValue13, org, ang );
        WP_FireTurboLaserMissile( ent, start, dir );
        if ( ent->alt_fire )
        {
            TurboLaser_SetBoneAnim( ent, 2, 3 );
        }
        else
        {
            TurboLaser_SetBoneAnim( ent, 0, 1 );
        }
    }
    else
    {
        G_PlayEffectID( G_EffectIndex("blaster/muzzle_flash"), org, ang );
        bolt = G_Spawn();

        bolt->classname = "turret_proj";
        bolt->nextthink = level.time + 10000;
        bolt->think = G_FreeEntity;
        bolt->s.eType = ET_MISSILE;
        bolt->s.weapon = WP_BLASTER;
        bolt->r.ownerNum = ent->s.number;
        bolt->damage = ent->damage;
        bolt->alliedTeam = ent->alliedTeam;
        bolt->teamnodmg = ent->teamnodmg;
        bolt->dflags = (DAMAGE_NO_KNOCKBACK|DAMAGE_HEAVY_WEAP_CLASS);		// Don't push them around, or else we are constantly re-aiming
        bolt->splashDamage = ent->splashDamage;
        bolt->splashRadius = ent->splashDamage;
        bolt->methodOfDeath = MOD_TARGET_LASER;//MOD_ENERGY;
        bolt->splashMethodOfDeath = MOD_TARGET_LASER;//MOD_ENERGY;
        bolt->clipmask = MASK_SHOT | CONTENTS_LIGHTSABER;
        //bolt->trigger_formation = qfalse;		// don't draw tail on first frame

        VectorSet( bolt->r.maxs, 1.5, 1.5, 1.5 );
        VectorScale( bolt->r.maxs, -1, bolt->r.mins );
        bolt->s.pos.trType = TR_LINEAR;
        bolt->s.pos.trTime = level.time;
        VectorCopy( start, bolt->s.pos.trBase );
        VectorScale( dir, ent->mass, bolt->s.pos.trDelta );
        SnapVector( bolt->s.pos.trDelta );		// save net bandwidth
        VectorCopy( start, bolt->r.currentOrigin);
    }
}
Esempio n. 27
0
//TODO:  When transition to 0 grav, push away from surface you were resting on
//TODO:  When free-floating in air, apply some friction to your trDelta (based on mass?)
void G_RunObject( gentity_t *ent ) {
	vector3		origin, oldOrg;
	trace_t		tr;
	gentity_t	*traceEnt = NULL;

	//FIXME: floaters need to stop floating up after a while, even if gravity stays negative?
	if ( ent->s.pos.trType == TR_STATIONARY )//g_gravity.value <= 0 &&
	{
		ent->s.pos.trType = TR_GRAVITY;
		VectorCopy( &ent->r.currentOrigin, &ent->s.pos.trBase );
		ent->s.pos.trTime = level.previousTime;//?necc?
		if ( !g_gravity.value ) {
			ent->s.pos.trDelta.z += 100;
		}
	}

	ent->nextthink = level.time + FRAMETIME;

	VectorCopy( &ent->r.currentOrigin, &oldOrg );
	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, &origin );
	//Get current angles?
	BG_EvaluateTrajectory( &ent->s.apos, level.time, &ent->r.currentAngles );

	if ( VectorCompare( &ent->r.currentOrigin, &origin ) ) {//error - didn't move at all!
		return;
	}
	// trace a line from the previous position to the current position,
	// ignoring interactions with the missile owner
	trap->Trace( &tr, &ent->r.currentOrigin, &ent->r.mins, &ent->r.maxs, &origin, ent->parent ? ent->parent->s.number : ent->s.number, ent->clipmask, qfalse, 0, 0 );

	if ( !tr.startsolid && !tr.allsolid && tr.fraction ) {
		VectorCopy( &tr.endpos, &ent->r.currentOrigin );
		trap->LinkEntity( (sharedEntity_t *)ent );
	}
	else
		//if ( tr.startsolid )
	{
		tr.fraction = 0;
	}

	G_MoverTouchPushTriggers( ent, &oldOrg );
	/*
	if ( !(ent->s.eFlags & EF_TELEPORT_BIT) && !(ent->svFlags & SVF_NO_TELEPORT) )
	{
	G_MoverTouchTeleportTriggers( ent, oldOrg );
	if ( ent->s.eFlags & EF_TELEPORT_BIT )
	{//was teleported
	return;
	}
	}
	else
	{
	ent->s.eFlags &= ~EF_TELEPORT_BIT;
	}
	*/

	if ( tr.fraction == 1 ) {
		if ( g_gravity.value <= 0 ) {
			if ( ent->s.apos.trType == TR_STATIONARY ) {
				VectorCopy( &ent->r.currentAngles, &ent->s.apos.trBase );
				ent->s.apos.trType = TR_LINEAR;
				ent->s.apos.trDelta.y = flrand( -300, 300 );
				ent->s.apos.trDelta.x = flrand( -10, 10 );
				ent->s.apos.trDelta.z = flrand( -10, 10 );
				ent->s.apos.trTime = level.time;
			}
		}
		//friction in zero-G
		if ( !g_gravity.value ) {
			float friction = 0.975f;
			//friction -= ent->mass/1000.0f;
			if ( friction < 0.1f ) {
				friction = 0.1f;
			}

			VectorScale( &ent->s.pos.trDelta, friction, &ent->s.pos.trDelta );
			VectorCopy( &ent->r.currentOrigin, &ent->s.pos.trBase );
			ent->s.pos.trTime = level.time;
		}
		return;
	}

	//hit something

	//Do impact damage
	traceEnt = &g_entities[tr.entityNum];
	if ( tr.fraction || (traceEnt && traceEnt->takedamage) ) {
		if ( !VectorCompare( &ent->r.currentOrigin, &oldOrg ) ) {//moved and impacted
			if ( (traceEnt && traceEnt->takedamage) ) {//hurt someone
				//				G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHurt.wav" ) );
			}
			//			G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectHit.wav" ) );
		}

		if ( ent->s.weapon != WP_SABER ) {
			DoImpact( ent, traceEnt, qtrue );
		}
	}

	if ( !ent || (ent->takedamage&&ent->health <= 0) ) {//been destroyed by impact
		//chunks?
		//		G_Sound( ent, G_SoundIndex( "sound/movers/objects/objectBreak.wav" ) );
		return;
	}

	//do impact physics
	if ( ent->s.pos.trType == TR_GRAVITY )//tr.fraction < 1.0f &&
	{//FIXME: only do this if no trDelta
		if ( g_gravity.value <= 0 || tr.plane.normal.z < 0.7f ) {
			if ( ent->flags&(FL_BOUNCE | FL_BOUNCE_HALF) ) {
				if ( tr.fraction <= 0.0f ) {
					VectorCopy( &tr.endpos, &ent->r.currentOrigin );
					VectorCopy( &tr.endpos, &ent->s.pos.trBase );
					VectorClear( &ent->s.pos.trDelta );
					ent->s.pos.trTime = level.time;
				}
				else {
					G_BounceObject( ent, &tr );
				}
			}
			else {//slide down?
				//FIXME: slide off the slope
			}
		}
		else {
			ent->s.apos.trType = TR_STATIONARY;
			pitch_roll_for_slope( ent, &tr.plane.normal );
			//ent->r.currentAngles[0] = 0;//FIXME: match to slope
			//ent->r.currentAngles[2] = 0;//FIXME: match to slope
			VectorCopy( &ent->r.currentAngles, &ent->s.apos.trBase );
			//okay, we hit the floor, might as well stop or prediction will
			//make us go through the floor!
			//FIXME: this means we can't fall if something is pulled out from under us...
			G_StopObjectMoving( ent );
		}
	}
	else if ( ent->s.weapon != WP_SABER ) {
		ent->s.apos.trType = TR_STATIONARY;
		pitch_roll_for_slope( ent, &tr.plane.normal );
		//ent->r.currentAngles[0] = 0;//FIXME: match to slope
		//ent->r.currentAngles[2] = 0;//FIXME: match to slope
		VectorCopy( &ent->r.currentAngles, &ent->s.apos.trBase );
	}

	//call touch func
	ent->touch( ent, &g_entities[tr.entityNum], &tr );
}
Esempio n. 28
0
// Caused by an EV_FIRE_WEAPON event
void CG_FireWeapon( centity_t *cent, qboolean altFire ) {
	entityState_t *ent;
	int c;
	weaponInfo_t *weap;

	ent = &cent->currentState;
	if ( ent->weapon == WP_NONE )
		return;
	if ( ent->weapon >= WP_NUM_WEAPONS ) {
		trap->Error( ERR_DROP, "CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS" );
		return;
	}
	weap = &cg_weapons[ent->weapon];

	// mark the entity as muzzle flashing, so when it is added it will append the flash to the weapon model
	cent->muzzleFlashTime = cg.time;

	if ( cg.predictedPlayerState.clientNum == cent->currentState.number ) {
		if ( (altFire && (ent->weapon == WP_BRYAR_PISTOL || ent->weapon == WP_BRYAR_OLD || ent->weapon == WP_DEMP2)) ||
			(!altFire && ent->weapon == WP_BOWCASTER) ) {
			float val = (cg.time - cent->currentState.constantLight) * 0.001f;

			if ( val > 3 )
				val = 3;
			if ( val < 0.2f )
				val = 0.2f;

			val *= 2;

			CGCam_Shake( val, 250 );
		}
		else if ( ent->weapon == WP_ROCKET_LAUNCHER ||
			(ent->weapon == WP_REPEATER && altFire) ||
			ent->weapon == WP_FLECHETTE ||
			(ent->weapon == WP_CONCUSSION && !altFire) ) {
			if ( ent->weapon == WP_CONCUSSION ) {
				// gives an advantage to being in 3rd person, but would look silly otherwise
				if ( !cg.renderingThirdPerson ) {
					// kick the view back
					cg.kick_angles.pitch = flrand( -10, -15 );
					cg.kick_time = cg.time;
				}
			}
			else if ( ent->weapon == WP_ROCKET_LAUNCHER )
				CGCam_Shake( flrand( 2, 3 ), 350 );
			else if ( ent->weapon == WP_REPEATER )
				CGCam_Shake( flrand( 2, 3 ), 350 );
			else if ( ent->weapon == WP_FLECHETTE ) {
				if ( altFire )
					CGCam_Shake( flrand( 2, 3 ), 350 );
				else
					CGCam_Shake( 1.5f, 250 );
			}
		}
	}

	// play quad sound if needed
	if ( cent->currentState.powerups & (1 << PW_QUAD) ) {
		//	trap->S_StartSound( NULL, cent->currentState.number, CHAN_ITEM, media.snd.quad );
	}

	// play a sound
	if ( altFire ) {
		// play a sound
		for ( c = 0; c<4; c++ ) {
			if ( !weap->altFlashSound[c] )
				break;
		}
		if ( c > 0 ) {
			c = rand() % c;
			if ( weap->altFlashSound[c] )
				trap->S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->altFlashSound[c] );
		}
	}
	else {
		// play a sound
		for ( c = 0; c<4; c++ ) {
			if ( !weap->flashSound[c] )
				break;
		}
		if ( c > 0 ) {
			c = rand() % c;
			if ( weap->flashSound[c] )
				trap->S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->flashSound[c] );
		}
	}
}
Esempio n. 29
0
static void R_SurfaceSpriteFrameUpdate(void)
{
	float dtime, dampfactor;	// Time since last update and damping time for wind changes
	float ratio;
	vec3_t ang, diff, retwindvec;
	float targetspeed;
	vec3_t up={0,0,1};

	if (backEnd.refdef.time == lastSSUpdateTime)
		return;

	if (backEnd.refdef.time < lastSSUpdateTime)
	{	// Time is BEFORE the last update time, so reset everything.
		curWindGust = 5;
		curWindSpeed = r_windSpeed->value;
		nextGustTime = 0;
		gustLeft = 0;
	}

	// Reset the last entity drawn, since this is a new frame.
	ssLastEntityDrawn = NULL;

	// Adjust for an FOV.  If things look twice as wide on the screen, pretend the shaders have twice the range.
	// ASSUMPTION HERE IS THAT "standard" fov is the first one rendered.
	
	if (!standardfovinitialized)
	{	// This isn't initialized yet.
		if (backEnd.refdef.fov_x > 50 && backEnd.refdef.fov_x < 135)		// I don't consider anything below 50 or above 135 to be "normal".
		{
			standardfovx = backEnd.refdef.fov_x;
			standardscalex = tan(standardfovx * 0.5 * (M_PI/180.0f));
			standardfovinitialized = qtrue;
		}
		else
		{
			standardfovx = 90;
			standardscalex = tan(standardfovx * 0.5 * (M_PI/180.0f));
		}
		rangescalefactor = 1.0;		// Don't multiply the shader range by anything.
	}
	else if (standardfovx == backEnd.refdef.fov_x)
	{	// This is the standard FOV (or higher), don't multiply the shader range.
		rangescalefactor = 1.0;
	}
	else
	{	// We are using a non-standard FOV.  We need to multiply the range of the shader by a scale factor.
		if (backEnd.refdef.fov_x > 135)
		{
			rangescalefactor = standardscalex / tan(135.0f * 0.5f * (M_PI/180.0f));
		}
		else
		{
			rangescalefactor = standardscalex / tan(backEnd.refdef.fov_x * 0.5 * (M_PI/180.0f));
		}
	}

	// Create a set of four right vectors so that vertical sprites aren't always facing the same way.
	// First generate a HORIZONTAL forward vector (important).
	CrossProduct(ssViewRight, up, ssfwdvector);
	
	// Right Zero has a nudge forward (10 degrees).
	VectorScale(ssViewRight, 0.985f, ssrightvectors[0]);
	VectorMA(ssrightvectors[0], 0.174f, ssfwdvector, ssrightvectors[0]);

	// Right One has a big nudge back (30 degrees).
	VectorScale(ssViewRight, 0.866f, ssrightvectors[1]);
	VectorMA(ssrightvectors[1], -0.5f, ssfwdvector, ssrightvectors[1]);


	// Right two has a big nudge forward (30 degrees).
	VectorScale(ssViewRight, 0.866f, ssrightvectors[2]);
	VectorMA(ssrightvectors[2], 0.5f, ssfwdvector, ssrightvectors[2]);


	// Right three has a nudge back (10 degrees).
	VectorScale(ssViewRight, 0.985f, ssrightvectors[3]);
	VectorMA(ssrightvectors[3], -0.174f, ssfwdvector, ssrightvectors[3]);


	// Update the wind.
	// If it is raining, get the windspeed from the rain system rather than the cvar
	if (R_IsRaining() || R_IsPuffing())
	{
		curWeatherAmount = 1.0;
	}
	else
	{
		curWeatherAmount = r_surfaceWeather->value;
	}

	if (R_GetWindSpeed(targetspeed))
	{	// We successfully got a speed from the rain system.
		// Set the windgust to 5, since that looks pretty good.
		targetspeed *= 0.3f;
		if (targetspeed >= 1.0)
		{
			curWindGust = 300/targetspeed;
		}
		else
		{
			curWindGust = 0;
		}
	}
	else
	{	// Use the cvar.
		targetspeed = r_windSpeed->value;	// Minimum gust delay, in seconds.
		curWindGust = r_windGust->value;
	}
	
	if (targetspeed > 0 && curWindGust)
	{
		if (gustLeft > 0)
		{	// We are gusting
			// Add an amount to the target wind speed
			targetspeed *= 1.0 + gustLeft;

			gustLeft -= (float)(backEnd.refdef.time - lastSSUpdateTime)*WIND_GUST_DECAY;
			if (gustLeft <= 0)
			{
				nextGustTime = backEnd.refdef.time + (curWindGust*1000)*flrand(1.0f,4.0f);
			}
		}
		else if (backEnd.refdef.time >= nextGustTime)
		{	// See if there is another right now
			// Gust next time, mano
			gustLeft = flrand(0.75f,1.5f);
		}
	}

	// See if there is a weather system that will tell us a windspeed.
	if (R_GetWindVector(retwindvec))
	{
		retwindvec[2]=0;
		VectorScale(retwindvec, -1.0f, retwindvec);
		vectoangles(retwindvec, ang);
	}
	else
	{	// Calculate the target wind vector based off cvars
		ang[YAW] = r_windAngle->value;
	}

	ang[PITCH] = -90.0 + targetspeed;
	if (ang[PITCH]>-45.0)
	{
		ang[PITCH] = -45.0;
	}
	ang[ROLL] = 0;

	if (targetspeed>0)
	{
//		ang[YAW] += cos(tr.refdef.time*0.01+flrand(-1.0,1.0))*targetspeed*0.5;
//		ang[PITCH] += sin(tr.refdef.time*0.01+flrand(-1.0,1.0))*targetspeed*0.5;
	}
	
	// Get the grass wind vector first
	AngleVectors(ang, targetWindGrassDir, NULL, NULL);
	targetWindGrassDir[2]-=1.0;
//		VectorScale(targetWindGrassDir, targetspeed, targetWindGrassDir);

	// Now get the general wind vector (no pitch)
	ang[PITCH]=0;
	AngleVectors(ang, targetWindBlowVect, NULL, NULL);

	// Start calculating a smoothing factor so wind doesn't change abruptly between speeds.
	dampfactor = 1.0-r_windDampFactor->value;	// We must exponent the amount LEFT rather than the amount bled off
	dtime = (float)(backEnd.refdef.time - lastSSUpdateTime) * (1.0/(float)WIND_DAMP_INTERVAL);	// Our dampfactor is geared towards a time interval equal to "1".

	// Note that since there are a finite number of "practical" delta millisecond values possible, 
	// the ratio should be initialized into a chart ultimately.
	ratio = pow(dampfactor, dtime);

	// Apply this ratio to the windspeed...
	curWindSpeed = targetspeed - (ratio * (targetspeed-curWindSpeed));

	// Use the curWindSpeed to calculate the final target wind vector (with speed)
	VectorScale(targetWindBlowVect, curWindSpeed, targetWindBlowVect);
	VectorSubtract(targetWindBlowVect, curWindBlowVect, diff);
	VectorMA(targetWindBlowVect, -ratio, diff, curWindBlowVect);

	// Update the grass vector now
	VectorSubtract(targetWindGrassDir, curWindGrassDir, diff);
	VectorMA(targetWindGrassDir, -ratio, diff, curWindGrassDir);

	lastSSUpdateTime = backEnd.refdef.time;

	curWindPointForce = r_windPointForce->value - (ratio * (r_windPointForce->value - curWindPointForce));
	if (curWindPointForce < 0.01)
	{
		curWindPointActive = qfalse;
	}
	else
	{
		curWindPointActive = qtrue;
		curWindPoint[0] = r_windPointX->value;
		curWindPoint[1] = r_windPointY->value;
		curWindPoint[2] = 0;
	}

	if (r_surfaceSprites->integer >= 2)
	{
		ri->Printf( PRINT_ALL, "Surfacesprites Drawn: %d, on %d surfaces\n", totalsurfsprites, sssurfaces);
	}

	totalsurfsprites=0;
	sssurfaces=0;
}
Esempio n. 30
0
void FX_CreateParticle(const FXSegment_t *segment, vec3_t origin, vec3_t dir)
{
	FXParticleSegment_t *particle;
	fxParticle_t *effect;

	if(!segment)
	{	// NULL segment pointer?
		return;
	}
	if(!segment->SegmentData.FXParticleSegment)
	{	// No particle segment data?
		return;
	}
	if(segment->segmentType != EFXS_PARTICLE)
	{	// Not a particle?
		return;
	}
	particle = segment->SegmentData.FXParticleSegment;
	effect = (fxParticle_t *)malloc(sizeof(fxParticle_t));
	FX_ParticleInit((fxPrimitive_t *)effect);
	effect->culldist = flrand(particle->cullrange[0], particle->cullrange[1]);
	effect->culldist *= effect->culldist; // allows for VLSquared
	effect->startTime = fx_time + Q_irand(particle->delay[0], particle->delay[1]);
	effect->endTime = effect->startTime + Q_irand(particle->life[0], particle->life[1]);
	effect->flags = segment->flags;
	VectorCopy(origin, effect->origin);

	//if((segment->spawnflags & FXSFLAG_CHEAPORIGINCALC))
	{
		vec3_t offset;
		vecrandom(particle->origin[0], particle->origin[1], offset);
		VectorAdd(effect->origin, offset, effect->origin);
	}
	vecrandom(particle->rgb.start.sv[0], particle->rgb.start.sv[1], effect->startRGB);

	if(particle->rgb.flags != 0 || !(particle->rgb.flags & FXTLF_CONSTANT))
	{
		vecrandom(particle->rgb.end.ev[0], particle->rgb.end.ev[1], effect->endRGB);
	}
	else
	{
		VectorCopy(effect->startRGB, effect->endRGB);
	}
	//effect->RGBflags = light->rgb.flags;
	VectorCopy(effect->startRGB, effect->RGB);

	effect->startsize = effect->size = flrand(particle->size.start.sf[0], particle->size.start.sf[1]);

	if(particle->size.flags != 0 || !(particle->size.flags & FXTLF_CONSTANT))
	{
		// TODO: make the distinction between wave, clamp, nonlinear, etc
		effect->endsize = flrand(particle->size.end.ef[0], particle->size.end.ef[1]);
	}
	else
	{
		effect->endsize = effect->startsize;
	}
	//effect->sizeFlags = light->size.flags;

	effect->startalpha = effect->alpha = flrand(particle->alpha.start.sf[0], particle->alpha.start.sf[1]);
	if(particle->alpha.flags != 0 || !(particle->alpha.flags & FXTLF_CONSTANT))
	{
		// TODO: make the distinction between wave, clamp, nonlinear, etc
		effect->endalpha = flrand(particle->alpha.end.ef[0], particle->alpha.end.ef[1]);
	}
	else
	{
		effect->endalpha = effect->startalpha;
	}
	//effect->alphaFlags = particle->alpha.flags;

	effect->startrotation = effect->rotation = flrand(particle->rotation[0], particle->rotation[1]);
	effect->deltarotation = flrand(particle->rotationDelta[0], particle->rotationDelta[1]);

	vecrandom(particle->velocity[0], particle->velocity[1], effect->velocity);
	vecrandom(particle->acceleration[0], particle->acceleration[1], effect->accel);

	effect->shader = particle->shader.fieldHandles[Q_irand(0, particle->shader.numFields-1)];

	FX_AddPrimitive((fxPrimitive_t *)effect, effect->startTime, effect->endTime);
}