void misc_model_use (gentity_t *self, gentity_t *other, gentity_t *activator)
{
	if ( self->health <= 0 && self->max_health > 0)
	{//used while broken fired target3
		G_UseTargets2( self, activator, self->target3 );
		return;
	}

	G_ActivateBehavior( self, BSET_USE );
	//Don't explode if they've requested it to not
	if ( self->spawnflags & 64 )
	{//Usemodels toggling
		if ( self->spawnflags & 32 )
		{
			if( self->s.modelindex == self->sound1to2 )
			{
				self->s.modelindex = self->sound2to1;
			}
			else
			{
				self->s.modelindex = self->sound1to2;
			}
		}

		return;
	}

	misc_model_breakable_die( self, other, activator, self->health, MOD_UNKNOWN );
}
Exemple #2
0
/*
==============================
G_UseTargets

"activator" should be set to the entity that initiated the firing.

Search for (string)targetname in all entities that
match (string)self.target and call their .use function

==============================
*/
void G_UseTargets (gentity_t *ent, gentity_t *activator)
{
//
// fire targets
//
	G_UseTargets2 (ent, activator, ent->target);
}
Exemple #3
0
//----------------------------------------------------------
void fx_runner_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	if ( self->spawnflags & 2 ) // ONESHOT
	{
		// call the effect with the desired position and orientation, as a safety thing,
		//	make sure we aren't thinking at all.
		fx_runner_think( self );
		self->nextthink = -1;

		if ( self->target2 )
		{
			// let our target know that we have spawned an effect
			G_UseTargets2( self, self, self->target2 );
		}

		if ( VALIDSTRING( self->soundSet ) == true )
		{
			G_AddEvent( self, EV_BMODEL_SOUND, CAS_GetBModelSound( self->soundSet, BMS_START ));
		}
	}
	else
	{
		// ensure we are working with the right think function
		self->e_ThinkFunc = thinkF_fx_runner_think;

		// toggle our state
		if ( self->nextthink == -1 )
		{
			// NOTE: we fire the effect immediately on use, the fx_runner_think func will set
			//	up the nextthink time.
			fx_runner_think( self );

			if ( VALIDSTRING( self->soundSet ) == true )
			{
				G_AddEvent( self, EV_BMODEL_SOUND, CAS_GetBModelSound( self->soundSet, BMS_START ));
				self->s.loopSound = CAS_GetBModelSound( self->soundSet, BMS_MID );

				if ( self->s.loopSound < 0 )
				{
					self->s.loopSound = 0;
				}
			}
		}
		else
		{
			// turn off for now
			self->nextthink = -1;

			if ( VALIDSTRING( self->soundSet ) == true )
			{
				G_AddEvent( self, EV_BMODEL_SOUND, CAS_GetBModelSound( self->soundSet, BMS_END ));
				self->s.loopSound = 0;
			}
		}
	}
}
Exemple #4
0
void trigger_cleared_fire (gentity_t *self)
{
	G_UseTargets2( self, self->activator, self->target2 );
	self->e_ThinkFunc = thinkF_NULL;
	// should start the wait timer now, because the trigger's just been cleared, so we must "wait" from this point
	if ( self->wait > 0 ) 
	{
		self->nextthink = level.time + ( self->wait + self->random * crandom() ) * 1000;
	}
}
Exemple #5
0
void func_usable_pain(gentity_t *self, gentity_t *inflictor, gentity_t *attacker, const vec3_t point, int damage, int mod,int hitLoc)
{
	if ( self->paintarget )
	{
		G_UseTargets2 (self, self->activator, self->paintarget);
	}
	else
	{
		GEntity_UseFunc( self, attacker, attacker );
	}
}
void misc_model_breakable_pain ( gentity_t *self, gentity_t *inflictor, gentity_t *other, vec3_t point, int damage, int mod,int hitLoc )
{
	if ( self->health > 0 )
	{
		// still alive, react to the pain
		if ( self->paintarget )
		{
			G_UseTargets2 (self, self->activator, self->paintarget);
		}

		// Don't do script if dead
		G_ActivateBehavior( self, BSET_PAIN );
	}
}
Exemple #7
0
//pain function for model_breakables
void misc_model_breakable_pain (gentity_t *self, gentity_t *attacker, int damage)
{
	if ( self->health > 0 )
	{
		// still alive, react to the pain
		if ( self->paintarget )
		{
			G_UseTargets2 (self, self->activator, self->paintarget);
		}

		// Don't do script if dead
		G_ActivateBehavior( self, BSET_PAIN );
	}
}
Exemple #8
0
void target_counter_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	if ( self->count == 0 )
	{
		return;
	}
	
	//gi.Printf("target_counter %s used by %s, entnum %d\n", self->targetname, activator->targetname, activator->s.number );
	self->count--;

	if ( activator )
	{
		Quake3Game()->DebugPrint( IGameInterface::WL_VERBOSE, "target_counter %s used by %s (%d/%d)\n", self->targetname, activator->targetname, (self->max_health-self->count), self->max_health );
	}

	if ( self->count )
	{
		if ( self->target2 )
		{
			//gi.Printf("target_counter %s firing target2 from %s, entnum %d\n", self->targetname, activator->targetname, activator->s.number );
			G_UseTargets2( self, activator, self->target2 );
		}
		return;
	}
	
	G_ActivateBehavior( self,BSET_USE );

	if ( self->spawnflags & 128 )
	{
		self->svFlags |= SVF_INACTIVE;
	}

	self->activator = activator;
	G_UseTargets( self, activator );

	if ( self->count == 0 )
	{
		if ( self->bounceCount == 0 )
		{
			return;
		}
		self->count = self->max_health;
		if ( self->bounceCount > 0 )
		{//-1 means bounce back forever
			self->bounceCount--; 
		}
	}
}
void target_counter_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	if ( self->count == 0 )
	{
		return;
	}
	
	//gi.Printf("target_counter %s used by %s, entnum %d\n", self->targetname, activator->targetname, activator->s.number );
	self->count--;

	if ( activator )
	{
		G_DebugPrint( WL_VERBOSE, "target_counter %s used by %s (%d/%d)\n", self->targetname, activator->targetname, (self->genericValue1-self->count), self->genericValue1 );
	}

	if ( self->count )
	{
		if ( self->target2 )
		{
			//gi.Printf("target_counter %s firing target2 from %s, entnum %d\n", self->targetname, activator->targetname, activator->s.number );
			G_UseTargets2( self, activator, self->target2 );
		}
		return;
	}
	
	G_ActivateBehavior( self,BSET_USE );

	if ( self->spawnflags & 128 )
	{
		self->flags |= FL_INACTIVE;
	}

	self->activator = activator;
	G_UseTargets( self, activator );

	if ( self->count == 0 )
	{
		if ( self->bounceCount == 0 )
		{
			return;
		}
		self->count = self->genericValue1;
		if ( self->bounceCount > 0 )
		{//-1 means bounce back forever
			self->bounceCount--; 
		}
	}
}
void funcBBrushPain(gentity_t *self, gentity_t *inflictor, gentity_t *attacker, vec3_t point, int damage, int mod,int hitLoc)
{
	if ( self->painDebounceTime > level.time )
	{
		return;
	}

	if ( self->paintarget )
	{
		G_UseTargets2 (self, self->activator, self->paintarget);
	}

	G_ActivateBehavior( self, BSET_PAIN );

	if ( self->material == MAT_DRK_STONE
		|| self->material == MAT_LT_STONE
		|| self->material == MAT_GREY_STONE )
	{
		vec3_t	org, dir;
		float	scale;
		VectorSubtract( self->absmax, self->absmin, org );// size
		// This formula really has no logical basis other than the fact that it seemed to be the closest to yielding the results that I wanted.
		// Volume is length * width * height...then break that volume down based on how many chunks we have
		scale = VectorLength( org ) / 100.0f;
		VectorMA( self->absmin, 0.5, org, org );
		VectorAdd( self->absmin,self->absmax, org );
		VectorScale( org, 0.5f, org );
		if ( attacker != NULL && attacker->client )
		{
			VectorSubtract( attacker->currentOrigin, org, dir );
			VectorNormalize( dir );
		}
		else
		{
			VectorSet( dir, 0, 0, 1 );
		} 
		CG_Chunks( self->s.number, org, dir, self->mins, self->maxs, 300, Q_irand( 1, 3 ), self->material, 0, scale );
	}

	if ( self->wait == -1 )
	{
		self->e_PainFunc = painF_NULL;
		return;
	}

	self->painDebounceTime = level.time + self->wait;
}
Exemple #11
0
//----------------------------------------------------------
void emplaced_gun_pain( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, const vec3_t point, int damage, int mod,int hitLoc )
{
	if ( self->health <= 0 )
	{
		// play pain effect?
	}
	else
	{
		if ( self->paintarget )
		{
			G_UseTargets2( self, self->activator, self->paintarget );
		}

		// Don't do script if dead
		G_ActivateBehavior( self, BSET_PAIN );
	}
}
Exemple #12
0
void Svcmd_Use_f( void )
{
	char	*cmd1 = gi.argv(1);

	if ( !cmd1 || !cmd1[0] )
	{
		//FIXME: warning message
		gi.Printf( "'use' takes targetname of ent or 'list' (lists all usable ents)\n" );
		return;
	}
	else if ( !Q_stricmp("list", cmd1) )
	{
		gentity_t	*ent;

		gi.Printf("Listing all usable entities:\n");

		for ( int i = 1; i < ENTITYNUM_WORLD; i++ )
		{
			 ent = &g_entities[i];
			 if ( ent )
			 {
				 if ( ent->targetname && ent->targetname[0] )
				 {
					 if ( ent->e_UseFunc != useF_NULL )
					 {
						 if ( ent->NPC )
						 {
							gi.Printf( "%s (NPC)\n", ent->targetname );
						 }
						 else
						 {
							gi.Printf( "%s\n", ent->targetname );
						 }
					 }
				 }
			 }
		}

		gi.Printf("End of list.\n");
	}
	else
	{
		G_UseTargets2( &g_entities[0], &g_entities[0], cmd1 );
	}
}
Exemple #13
0
void misc_model_use (gentity_t *self, gentity_t *other, gentity_t *activator)
{
	if ( self->target4 )
	{//throw me at my target!
		misc_model_throw_at_target4( self, activator );
		return;
	}

	if ( self->health <= 0 && self->max_health > 0)
	{//used while broken fired target3
		G_UseTargets2( self, activator, self->target3 );
		return;
	}

	// Become solid again.
	if ( !self->count )
	{
		self->count = 1;
		self->activator = activator;
		self->svFlags &= ~SVF_NOCLIENT;
		self->s.eFlags &= ~EF_NODRAW;
	}

	G_ActivateBehavior( self, BSET_USE );
	//Don't explode if they've requested it to not
	if ( self->spawnflags & 64 )
	{//Usemodels toggling
		if ( self->spawnflags & 32 )
		{
			if( self->s.modelindex == self->sound1to2 )
			{
				self->s.modelindex = self->sound2to1;
			}
			else
			{
				self->s.modelindex = self->sound1to2;
			}
		}

		return;
	}

	self->e_DieFunc  = dieF_misc_model_breakable_die;
	misc_model_breakable_die( self, other, activator, self->health, MOD_UNKNOWN );
}
Exemple #14
0
void TurretG2Pain( gentity_t *self, gentity_t *attacker, int damage ) {
	if ( self->paintarget && self->paintarget[0] ) {
		if ( self->genericValue8 < level.time ) {
			G_UseTargets2( self, self, self->paintarget );
			self->genericValue8 = level.time + self->genericValue4;
		}
	}

	if ( attacker->client && attacker->client->ps.weapon == WP_DEMP2 ) {
		self->attackDebounceTime = level.time + 2000 + random() * 500;
		self->painDebounceTime = self->attackDebounceTime;
	}
	if ( !self->enemy ) {//react to being hit
		G_SetEnemy( self, attacker );
	}
	//self->s.health = self->health;
	//mmm..yes..bad.
}
Exemple #15
0
void NPC_BSRemove (void)
{
	NPC_UpdateAngles ( qtrue, qtrue );
	if( !gi.inPVS( NPC->currentOrigin, g_entities[0].currentOrigin ) )//FIXME: use cg.vieworg?
	{
		G_UseTargets2( NPC, NPC, NPC->target3 );
		NPC->s.eFlags |= EF_NODRAW;
		NPC->s.eFlags &= ~EF_NPC;
		NPC->svFlags &= ~SVF_NPC;
		NPC->s.eType = ET_INVISIBLE;
		NPC->contents = 0;
		NPC->health = 0;
		NPC->targetname = NULL;

		//Disappear in half a second
		NPC->e_ThinkFunc = thinkF_G_FreeEntity;
		NPC->nextthink = level.time + FRAMETIME;
	}//FIXME: else allow for out of FOV???
}
Exemple #16
0
//----------------------------------------------------------
void fx_runner_think( gentity_t *ent )
{
	vec3_t temp;

	EvaluateTrajectory( &ent->s.pos, level.time, ent->currentOrigin );
	EvaluateTrajectory( &ent->s.apos, level.time, ent->currentAngles );

	// call the effect with the desired position and orientation
	G_AddEvent( ent, EV_PLAY_EFFECT, ent->fxID );

	// Assume angles, we'll do a cross product on the other end to finish up
	AngleVectors( ent->currentAngles, ent->pos3, NULL, NULL );
	MakeNormalVectors( ent->pos3, ent->pos4, temp ); // there IS a reason this is done...it's so that it doesn't break every effect in the game...

	ent->nextthink = level.time + ent->delay + random() * ent->random;

	if ( ent->spawnflags & 4 ) // damage
	{
		G_RadiusDamage( ent->currentOrigin, ent, ent->splashDamage, ent->splashRadius, ent, MOD_UNKNOWN );
	}

	if ( ent->target2 )
	{
		// let our target know that we have spawned an effect
		G_UseTargets2( ent, ent, ent->target2 );
	}

	if ( !(ent->spawnflags & 2 ) && !ent->s.loopSound ) // NOT ONESHOT...this is an assy thing to do
	{
		if ( VALIDSTRING( ent->soundSet ) == true )
		{
			ent->s.loopSound = CAS_GetBModelSound( ent->soundSet, BMS_MID );

			if ( ent->s.loopSound < 0 )
			{
				ent->s.loopSound = 0;
			}
		}
	}

}
Exemple #17
0
void func_wait_return_solid( gentity_t *self )
{
	//once a frame, see if it's clear.
	self->clipmask = CONTENTS_BODY;//|CONTENTS_MONSTERCLIP|CONTENTS_BOTCLIP;
	if ( !(self->spawnflags&16) || G_TestEntityPosition( self ) == NULL )
	{
		gi.SetBrushModel( self, self->model );
		VectorCopy( self->currentOrigin, self->pos1 );
		InitMover( self );
		/*
		VectorCopy( self->s.origin, self->s.pos.trBase );
		VectorCopy( self->s.origin, self->currentOrigin );
		*/
		//if we moved, we want the *current* origin, not our start origin!
		VectorCopy( self->currentOrigin, self->s.pos.trBase );
		gi.linkentity( self );
		self->svFlags &= ~SVF_NOCLIENT;
		self->s.eFlags &= ~EF_NODRAW;
		self->e_UseFunc = useF_func_usable_use;
		self->clipmask = 0;
		if ( self->target2 && self->target2[0] )
		{
			G_UseTargets2( self, self->activator, self->target2 );
		}
		if ( self->s.eFlags & EF_ANIM_ONCE )
		{//Start our anim
			self->s.frame = 0;
		}
		//NOTE: be sure to reset the brushmodel before doing this or else CONTENTS_OPAQUE may not be on when you call this
		if ( !(self->spawnflags&1) )
		{//START_OFF doesn't effect area portals
			gi.AdjustAreaPortalState( self, qfalse );
		}
	}
	else
	{
		self->clipmask = 0;
		self->e_ThinkFunc = thinkF_func_wait_return_solid;
		self->nextthink = level.time + FRAMETIME;
	}
}
Exemple #18
0
int G_FindLocalInterestPoint( gentity_t *self )
{
	int		i, bestPoint = ENTITYNUM_NONE;
	float	dist, bestDist = Q3_INFINITE;
	vec3_t	diffVec, eyes;

	CalcEntitySpot( self, SPOT_HEAD_LEAN, eyes );
	for ( i = 0; i < level.numInterestPoints; i++ )
	{
		//Don't ignore portals?  If through a portal, need to look at portal!
		if ( gi.inPVS( level.interestPoints[i].origin, eyes ) )
		{
			VectorSubtract( level.interestPoints[i].origin, eyes, diffVec );
			if ( (fabs(diffVec[0]) + fabs(diffVec[1])) / 2 < 48 &&
				fabs(diffVec[2]) > (fabs(diffVec[0]) + fabs(diffVec[1])) / 2 )
			{//Too close to look so far up or down
				continue;
			}
			dist = VectorLengthSquared( diffVec );
			//Some priority to more interesting points
			//dist -= ((int)level.interestPoints[i].lookMode * 5) * ((int)level.interestPoints[i].lookMode * 5);
			if ( dist < MAX_INTEREST_DIST && dist < bestDist )
			{
				if ( G_ClearLineOfSight( eyes, level.interestPoints[i].origin, self->s.number, MASK_OPAQUE ) )
				{
					bestDist = dist;
					bestPoint = i;
				}
			}
		}
	}
	if ( bestPoint != ENTITYNUM_NONE && level.interestPoints[bestPoint].target )
	{
		G_UseTargets2( self, self, level.interestPoints[bestPoint].target );
	}
	return bestPoint;
}
Exemple #19
0
// the trigger was just activated
// ent->activator should be set to the activator so it can be held through a delay
// so wait for the delay time before firing
void multi_trigger_run( gentity_t *ent ) 
{
	ent->think = 0;

	G_ActivateBehavior( ent, BSET_USE );

	if ( ent->soundSet && ent->soundSet[0] )
	{
		trap->SetConfigstring( CS_GLOBAL_AMBIENT_SET, ent->soundSet );
	}

	if (ent->genericValue4)
	{ //we want to activate target3 for team1 or target4 for team2
		if (ent->genericValue4 == SIEGETEAM_TEAM1 &&
			ent->target3 && ent->target3[0])
		{
			G_UseTargets2(ent, ent->activator, ent->target3);
		}
		else if (ent->genericValue4 == SIEGETEAM_TEAM2 &&
			ent->target4 && ent->target4[0])
		{
			G_UseTargets2(ent, ent->activator, ent->target4);
		}

		ent->genericValue4 = 0;
	}

	G_UseTargets (ent, ent->activator);
	if ( ent->noise_index ) 
	{
		G_Sound( ent->activator, CHAN_AUTO, ent->noise_index );
	}

	if ( ent->target2 && ent->target2[0] && ent->wait >= 0 )
	{
		ent->think = trigger_cleared_fire;
		ent->nextthink = level.time + ent->speed;
	}
	else if ( ent->wait > 0 ) 
	{
		if ( ent->painDebounceTime != level.time )
		{//first ent to touch it this frame
			//ent->e_ThinkFunc = thinkF_multi_wait;
			ent->nextthink = level.time + ( ent->wait + ent->random * crandom() ) * 1000;
			ent->painDebounceTime = level.time;
		}
	} 
	else if ( ent->wait < 0 )
	{
		// we can't just remove (self) here, because this is a touch function
		// called while looping through area links...
		ent->r.contents &= ~CONTENTS_TRIGGER;//so the EntityContact trace doesn't have to be done against me
		ent->think = 0;
		ent->use = 0;
		//Don't remove, Icarus may barf?
		//ent->nextthink = level.time + FRAMETIME;
		//ent->think = G_FreeEntity;
	}
	if( ent->activator && ent->activator->client )
	{	// mark the trigger as being touched by the player
		ent->aimDebounceTime = level.time;
	}
}
//-----------------------------------------------------
static qboolean turretG2_find_enemies( gentity_t *self )
//-----------------------------------------------------
{
    qboolean	found = qfalse;
    int			i, count;
    float		bestDist = self->radius * self->radius;
    float		enemyDist;
    vec3_t		enemyDir, org, org2;
    qboolean	foundClient = qfalse;
    gentity_t	*entity_list[MAX_GENTITIES], *target, *bestTarget = NULL;

    if ( self->aimDebounceTime > level.time ) // time since we've been shut off
    {
        // We were active and alert, i.e. had an enemy in the last 3 secs
        if ( self->painDebounceTime < level.time )
        {
            if ( !(self->spawnflags&SPF_TURRETG2_TURBO) )
            {
                G_Sound(self, CHAN_BODY, G_SoundIndex( "sound/chars/turret/ping.wav" ));
            }
            self->painDebounceTime = level.time + 1000;
        }
    }

    VectorCopy( self->r.currentOrigin, org2 );
    if ( self->spawnflags & 2 )
    {
        org2[2] += 20;
    }
    else
    {
        org2[2] -= 20;
    }

    count = G_RadiusList( org2, self->radius, self, qtrue, entity_list );

    for ( i = 0; i < count; i++ )
    {
        trace_t	tr;
        target = entity_list[i];

        if ( !target->client )
        {
            // only attack clients
            if ( !(target->flags&FL_BBRUSH)//not a breakable brush
                    || !target->takedamage//is a bbrush, but invincible
                    || (target->NPC_targetname&&self->targetname&&Q_stricmp(target->NPC_targetname,self->targetname)!=0) )//not in invicible bbrush, but can only be broken by an NPC that is not me
            {
                continue;
            }
            //else: we will shoot at bbrushes!
        }
        if ( target == self || !target->takedamage || target->health <= 0 || ( target->flags & FL_NOTARGET ))
        {
            continue;
        }
        if ( target->client && target->client->sess.sessionTeam == TEAM_SPECTATOR )
        {
            continue;
        }
        if ( self->alliedTeam )
        {
            if ( target->client )
            {
                if ( target->client->sess.sessionTeam == self->alliedTeam )
                {
                    // A bot/client/NPC we don't want to shoot
                    continue;
                }
            }
            else if ( target->teamnodmg == self->alliedTeam )
            {
                // An ent we don't want to shoot
                continue;
            }
        }
        if ( !trap_InPVS( org2, target->r.currentOrigin ))
        {
            continue;
        }

        if ( target->client )
        {
            VectorCopy( target->client->renderInfo.eyePoint, org );
        }
        else
        {
            VectorCopy( target->r.currentOrigin, org );
        }

        if ( self->spawnflags & 2 )
        {
            org[2] -= 15;
        }
        else
        {
            org[2] += 5;
        }

        trap_Trace( &tr, org2, NULL, NULL, org, self->s.number, MASK_SHOT );

        if ( !tr.allsolid && !tr.startsolid && ( tr.fraction == 1.0 || tr.entityNum == target->s.number ))
        {
            // Only acquire if have a clear shot, Is it in range and closer than our best?
            VectorSubtract( target->r.currentOrigin, self->r.currentOrigin, enemyDir );
            enemyDist = VectorLengthSquared( enemyDir );

            if ( enemyDist < bestDist || (target->client && !foundClient))// all things equal, keep current
            {
                if ( self->attackDebounceTime < level.time )
                {
                    // We haven't fired or acquired an enemy in the last 2 seconds-start-up sound
                    if ( !(self->spawnflags&SPF_TURRETG2_TURBO) )
                    {
                        G_Sound( self, CHAN_BODY, G_SoundIndex( "sound/chars/turret/startup.wav" ));
                    }

                    // Wind up turrets for a bit
                    self->attackDebounceTime = level.time + 1400;
                }

                bestTarget = target;
                bestDist = enemyDist;
                found = qtrue;
                if ( target->client )
                {   //prefer clients over non-clients
                    foundClient = qtrue;
                }
            }
        }
    }

    if ( found )
    {
        /*
        if ( !self->enemy )
        {//just aquired one
        	AddSoundEvent( bestTarget, self->r.currentOrigin, 256, AEL_DISCOVERED );
        	AddSightEvent( bestTarget, self->r.currentOrigin, 512, AEL_DISCOVERED, 20 );
        }
        */
        G_SetEnemy( self, bestTarget );
        if ( VALIDSTRING( self->target2 ))
        {
            G_UseTargets2( self, self, self->target2 );
        }
    }

    return found;
}
Exemple #21
0
void trigger_entdist_use( gentity_t *self, gentity_t *other, gentity_t *activator )
{
	vec3_t		diff;
	gentity_t	*found = NULL;
	gentity_t	*owner = NULL;
	qboolean	useflag;
	const char	*token, *holdString;

	if ( self->svFlags & SVF_INACTIVE )	// Don't use INACTIVE
		return;

	G_ActivateBehavior(self,BSET_USE);

	if(self->ownername && self->ownername[0])
	{
		owner = G_Find(NULL, FOFS(targetname), self->ownername);
	}

	if(owner == NULL)
	{
		owner = self;
	}

	self->activator = activator;

	useflag = qfalse;

	self->svFlags |= SVF_INACTIVE;	// Make it inactive after one use

	if (self->spawnflags & ENTDIST_PLAYER)	// Look for player???
	{
		found = &g_entities[0];

		if (found)
		{	
			VectorSubtract(owner->currentOrigin, found->currentOrigin, diff);
			if(VectorLength(diff) < self->count)
			{
				useflag = qtrue;
			}
		}
	}

	if ((self->spawnflags & ENTDIST_NPC) && (!useflag))
	{
		holdString = self->NPC_target;

		while (holdString)
		{
			token = COM_Parse( &holdString);
			if ( !token ) // Nothing left to look at
			{
				break;
			}

			found = G_Find(found, FOFS(targetname), token);	// Look for the specified NPC
			if (found)	//Found???
			{	
				VectorSubtract(owner->currentOrigin, found->currentOrigin, diff);
				if(VectorLength(diff) < self->count)	// Within distance
				{
					useflag = qtrue;
					break;
				}
			}
		}
	}

	if (useflag)
	{
		G_UseTargets2 (self, self->activator, self->target);
	}
	else if (self->target2)
	{
		// This is the negative target
		G_UseTargets2 (self, self->activator, self->target2);
	}	


}
Exemple #22
0
/*
===============
NPC_Pain
===============
*/
void NPC_Pain( gentity_t *self, gentity_t *inflictor, gentity_t *other, const vec3_t point, int damage, int mod, int hitLoc )
{
	team_t otherTeam = TEAM_FREE;
	int		voiceEvent = -1;

	if ( self->NPC == NULL )
		return;

	if ( other == NULL )
		return;

	//or just remove ->pain in player_die?
	if ( self->client->ps.pm_type == PM_DEAD )
		return;

	if ( other == self )
		return;

	other = G_CheckControlledTurretEnemy(self, other, qfalse);
	if (!other)
	{
		return;
	}

	//MCG: Ignore damage from your own team for now
	if ( other->client )
	{
		otherTeam = other->client->playerTeam;
	//	if ( otherTeam == TEAM_DISGUISE )
	//	{
	//		otherTeam = TEAM_PLAYER;
	//	}
	}

	if ( self->client->playerTeam
		&& other->client
		&& otherTeam == self->client->playerTeam
		&& (!player->client->ps.viewEntity || other->s.number != player->client->ps.viewEntity))
	{//hit by a teammate
		if ( other != self->enemy && self != other->enemy )
		{//we weren't already enemies
			if ( self->enemy || other->enemy
				|| (other->s.number&&other->s.number!=player->client->ps.viewEntity)
				/*|| (!other->s.number&&Q_irand( 0, 3 ))*/ )
			{//if one of us actually has an enemy already, it's okay, just an accident OR wasn't hit by player or someone controlled by player OR player hit ally and didn't get 25% chance of getting mad (FIXME:accumulate anger+base on diff?)
				//FIXME: player should have to do a certain amount of damage to ally or hit them several times to make them mad
				//Still run pain and flee scripts
				if ( self->client && self->NPC )
				{//Run any pain instructions
					if ( self->health <= (self->max_health/3) && G_ActivateBehavior(self, BSET_FLEE) )
					{

					}
					else// if( VALIDSTRING( self->behaviorSet[BSET_PAIN] ) )
					{
						G_ActivateBehavior(self, BSET_PAIN);
					}
				}
				if ( damage != -1 )
				{//-1 == don't play pain anim
					//Set our proper pain animation
					if ( Q_irand( 0, 1 ) )
					{
						NPC_ChoosePainAnimation( self, other, point, damage, mod, hitLoc, EV_FFWARN );
					}
					else
					{
						NPC_ChoosePainAnimation( self, other, point, damage, mod, hitLoc );
					}
				}
				return;
			}
			else if ( self->NPC && !other->s.number )//should be assumed, but...
			{//dammit, stop that!
				if ( self->NPC->charmedTime > level.time )
				{//mindtricked
					return;
				}
				else if ( self->NPC->ffireCount < 3+((2-g_spskill->integer)*2) )
				{//not mad enough yet
					//Com_Printf( "chck: %d < %d\n", self->NPC->ffireCount, 3+((2-g_spskill->integer)*2) );
					if ( damage != -1 )
					{//-1 == don't play pain anim
						//Set our proper pain animation
						if ( Q_irand( 0, 1 ) )
						{
							NPC_ChoosePainAnimation( self, other, point, damage, mod, hitLoc, EV_FFWARN );
						}
						else
						{
							NPC_ChoosePainAnimation( self, other, point, damage, mod, hitLoc );
						}
					}
					return;
				}
				else if ( G_ActivateBehavior( self, BSET_FFIRE ) )
				{//we have a specific script to run, so do that instead
					return;
				}
				else
				{//okay, we're going to turn on our ally, we need to set and lock our enemy and put ourselves in a bstate that lets us attack him (and clear any flags that would stop us)
					self->NPC->blockedSpeechDebounceTime = 0;
					voiceEvent = EV_FFTURN;
					self->NPC->behaviorState = self->NPC->tempBehavior = self->NPC->defaultBehavior = BS_DEFAULT;
					other->flags &= ~FL_NOTARGET;
					self->svFlags &= ~(SVF_IGNORE_ENEMIES|SVF_ICARUS_FREEZE|SVF_NO_COMBAT_SOUNDS);
					G_SetEnemy( self, other );
					self->svFlags |= SVF_LOCKEDENEMY;
					self->NPC->scriptFlags &= ~(SCF_DONT_FIRE|SCF_CROUCHED|SCF_WALKING|SCF_NO_COMBAT_TALK|SCF_FORCED_MARCH);
					self->NPC->scriptFlags |= (SCF_CHASE_ENEMIES|SCF_NO_MIND_TRICK);
					//NOTE: we also stop ICARUS altogether
					stop_icarus = qtrue;
					if ( !killPlayerTimer )
					{
						killPlayerTimer = level.time + 10000;
					}
				}
			}
		}
	}

	SaveNPCGlobals();
	SetNPCGlobals( self );

	//Do extra bits
	if ( NPCInfo->ignorePain == qfalse )
	{
		NPCInfo->confusionTime = 0;//clear any charm or confusion, regardless
		if ( NPC->ghoul2.size() && NPC->headBolt != -1 )
		{
			G_StopEffect("force/confusion", NPC->playerModel, NPC->headBolt, NPC->s.number );
		}
		if ( damage != -1 )
		{//-1 == don't play pain anim
			//Set our proper pain animation
			NPC_ChoosePainAnimation( self, other, point, damage, mod, hitLoc, voiceEvent );
		}
		//Check to take a new enemy
		if ( NPC->enemy != other && NPC != other )
		{//not already mad at them
			//if it's an eweb or emplaced gun, get mad at the owner, not the gun
			NPC_CheckAttacker( other, mod );
		}
	}

	//Attempt to run any pain instructions
	if ( self->client && self->NPC )
	{
		//FIXME: This needs better heuristics perhaps
		if(self->health <= (self->max_health/3) && G_ActivateBehavior(self, BSET_FLEE) )
		{
		}
		else //if( VALIDSTRING( self->behaviorSet[BSET_PAIN] ) )
		{
			G_ActivateBehavior(self, BSET_PAIN);
		}
	}

	//Attempt to fire any paintargets we might have
	if( self->paintarget && self->paintarget[0] )
	{
		G_UseTargets2(self, other, self->paintarget);
	}

	if (self->client && self->client->NPC_class==CLASS_BOBAFETT)
	{
		Boba_Pain( self, inflictor, damage, mod);
	}


	RestoreNPCGlobals();
}
Exemple #23
0
//-----------------------------------------------------
static qboolean turret_find_enemies( gentity_t *self )
//-----------------------------------------------------
{
	qboolean	found = qfalse;
	int			i, count;
	float		bestDist = self->radius * self->radius;
	float		enemyDist;
	vec3_t		enemyDir, org, org2;
	gentity_t	*entity_list[MAX_GENTITIES], *target, *bestTarget = NULL;
	trace_t		tr;
	gentity_t *top = &g_entities[self->r.ownerNum];
	if ( !top )
	{
		return qfalse;
	}

	if ( self->aimDebounceTime > level.time ) // time since we've been shut off
	{
		// We were active and alert, i.e. had an enemy in the last 3 secs
		if ( self->timestamp < level.time )
		{
			//G_Sound(self, CHAN_BODY, G_SoundIndex( "sound/chars/turret/ping.wav" ));
			self->timestamp = level.time + 1000;
		}
	}

	VectorCopy( top->r.currentOrigin, org2 );

	count = G_RadiusList( org2, self->radius, self, qtrue, entity_list );

	for ( i = 0; i < count; i++ )
	{
		target = entity_list[i];

		if ( !target->client )
		{
			// only attack clients
			continue;
		}
		if ( target == self || !target->takedamage || target->health <= 0 || ( target->flags & FL_NOTARGET ))
		{
			continue;
		}
		if ( target->client->sess.sessionTeam == TEAM_SPECTATOR )
		{
			continue;
		}
		if ( self->alliedTeam )
		{
			if ( target->client )
			{
				if ( target->client->sess.sessionTeam == self->alliedTeam )
				{ 
					// A bot/client/NPC we don't want to shoot
					continue;
				}
			}
			else if ( target->teamnodmg == self->alliedTeam )
			{ 
				// An ent we don't want to shoot
				continue;
			}
		}
		if ( !trap_InPVS( org2, target->r.currentOrigin ))
		{
			continue;
		}

		VectorCopy( target->r.currentOrigin, org );
		org[2] += target->r.maxs[2]*0.5f;

		trap_Trace( &tr, org2, NULL, NULL, org, self->s.number, MASK_SHOT );

		if ( !tr.allsolid && !tr.startsolid && ( tr.fraction == 1.0 || tr.entityNum == target->s.number ))
		{
			// Only acquire if have a clear shot, Is it in range and closer than our best?
			VectorSubtract( target->r.currentOrigin, top->r.currentOrigin, enemyDir );
			enemyDist = VectorLengthSquared( enemyDir );

			if ( enemyDist < bestDist // all things equal, keep current
				|| (!Q_stricmp( "atst_vehicle", target->NPC_type ) && bestTarget && Q_stricmp( "atst_vehicle", bestTarget->NPC_type ) ) )//target AT-STs over non-AT-STs... FIXME: must be a better, easier way to tell this, no?
			{
				if ( self->attackDebounceTime < level.time )
				{
					// We haven't fired or acquired an enemy in the last 2 seconds-start-up sound
					//G_Sound( self, CHAN_BODY, G_SoundIndex( "sound/chars/turret/startup.wav" ));

					// Wind up turrets for a bit
					self->attackDebounceTime = level.time + 1400;
				}

				bestTarget = target;
				bestDist = enemyDist;
				found = qtrue;
			}
		}
	}

	if ( found )
	{
		G_SetEnemy( self, bestTarget );
		if ( VALIDSTRING( self->target2 ))
		{
			G_UseTargets2( self, self, self->target2 );
		}
	}

	return found;
}
/*
===============
NPC_Pain
===============
*/
void NPC_Pain( gentity_t *self, gentity_t *other, int damage ) 
{
	team_t otherTeam = TEAM_FREE;

	if ( self->NPC == NULL ) 
		return;

	if ( other == NULL ) 
		return;

	//or just remove ->pain in player_die?
	if ( self->client->ps.pm_type == PM_DEAD )
		return;

	if ( other == self ) 
		return;

	//MCG: Ignore damage from your own team for now
	if ( other->client )
	{
		otherTeam = other->client->playerTeam;
		if ( otherTeam == TEAM_DISGUISE )
		{
			otherTeam = TEAM_STARFLEET;
		}
	}

	if ( other != self->enemy && self->client->playerTeam && other->client && otherTeam == self->client->playerTeam ) 
	{//Still run pain and flee scripts
		if ( self->client && self->NPC )
		{//Run any pain instructions
			if ( self->health <= (self->max_health/3) && ( VALIDSTRING( self->behaviorSet[BSET_FLEE] ) ) )
			{
				G_ActivateBehavior(self, BSET_FLEE);
			}
			else if( VALIDSTRING( self->behaviorSet[BSET_PAIN] ) )
			{
				G_ActivateBehavior(self, BSET_PAIN);
			}
		}
		return;
	}

	//Hirogen boss with shield
	if ( ( self->client->playerTeam == TEAM_HIROGEN ) ) 
	{
		if ( ( Q_stricmp( self->NPC_type, "hirogenalpha" ) == 0 ) && ( self->s.powerups & ( 1 << PW_HIROGEN_SHIELD ) ) )
			return;
	}

	SaveNPCGlobals();
	SetNPCGlobals( self );

	//Do extra bits
	if ( NPCInfo->ignorePain == qfalse )
	{
		//Check to take a new enemy
		NPC_CheckAttacker( other );

		if ( damage != -1 )
		{//don't play pain anim
			//Set our proper pain animation
			NPC_ChoosePainAnimation( self, damage );
		}
	}

	//Attempt to run any pain instructions
	if(self->client && self->NPC)
	{
		//FIXME: This needs better heuristics perhaps
		if(self->health <= (self->max_health/3) && ( VALIDSTRING( self->behaviorSet[BSET_FLEE] ) ) )
		{
			G_ActivateBehavior(self, BSET_FLEE);
		}
		else if( VALIDSTRING( self->behaviorSet[BSET_PAIN] ) )
		{
			G_ActivateBehavior(self, BSET_PAIN);
		}
	}

	//Attempt to fire any paintargets we might have
	if( self->paintarget && self->paintarget[0] )
	{
		G_UseTargets2(self, other, self->paintarget);
	}

	RestoreNPCGlobals();
}