コード例 #1
0
ファイル: g_items.c プロジェクト: Garey27/quake3-brainworks
/*
================
G_RunItem

================
*/
void G_RunItem( gentity_t *ent ) {
	vec3_t		origin;
	trace_t		tr;
	int			contents;
	int			mask;

	// if groundentity has been set to -1, it may have been pushed off an edge
	if ( ent->s.groundEntityNum == -1 ) {
		if ( ent->s.pos.trType != TR_GRAVITY ) {
			ent->s.pos.trType = TR_GRAVITY;
			ent->s.pos.trTime = level.time;
		}
	}

	if ( ent->s.pos.trType == TR_STATIONARY ) {
		// check think function
		G_RunThink( ent );
		return;
	}

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

	// trace a line from the previous position to the current position
	if ( ent->clipmask ) {
		mask = ent->clipmask;
	} else {
		mask = MASK_PLAYERSOLID & ~CONTENTS_BODY;//MASK_SOLID;
	}
	trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin,
		ent->r.ownerNum, mask );

	VectorCopy( tr.endpos, ent->r.currentOrigin );

	if ( tr.startsolid ) {
		tr.fraction = 0;
	}

	trap_LinkEntity( ent );	// FIXME: avoid this for stationary?

	// check think function
	G_RunThink( ent );

	if ( tr.fraction == 1 ) {
		return;
	}

	// if it is in a nodrop volume, remove it
	contents = trap_PointContents( ent->r.currentOrigin, -1 );
	if ( contents & CONTENTS_NODROP ) {
		if (ent->item && ent->item->giType == IT_TEAM) {
			Team_FreeEntity(ent);
		} else {
			G_FreeEntity( ent );
		}
		return;
	}

	G_BounceItem( ent, &tr );
}
コード例 #2
0
ファイル: g_missile.c プロジェクト: OpenArena/legacy
/*
================
G_RunMissile
================
*/
void G_RunMissile( gentity_t *ent ) {
	vec3_t		origin;
	trace_t		tr;
	int			passent;

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

	// if this missile bounced off an invulnerability sphere
	if ( ent->target_ent ) {
		passent = ent->target_ent->s.number;
	}
	// prox mines that left the owner bbox will attach to anything, even the owner
	else if (ent->s.weapon == WP_PROX_LAUNCHER && ent->count) {
		passent = ENTITYNUM_NONE;
	}
	else {
		// ignore interactions with the missile owner
		passent = ent->r.ownerNum;
	}
	// trace a line from the previous position to the current position
	trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask );

	if ( tr.startsolid || tr.allsolid ) {
		// make sure the tr.entityNum is set to the entity we're stuck in
		trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask );
		tr.fraction = 0;
	}
	else {
		VectorCopy( tr.endpos, ent->r.currentOrigin );
	}

	trap_LinkEntity( ent );

	if ( tr.fraction != 1 ) {
		// never explode or bounce on sky
		if ( tr.surfaceFlags & SURF_NOIMPACT ) {
			// If grapple, reset owner
			if (ent->parent && ent->parent->client && ent->parent->client->hook == ent) {
				ent->parent->client->hook = NULL;
			}
			G_FreeEntity( ent );
			return;
		}
		G_MissileImpact( ent, &tr );
		if ( ent->s.eType != ET_MISSILE ) {
			return;		// exploded
		}
	}
	// if the prox mine wasn't yet outside the player body
	if (ent->s.weapon == WP_PROX_LAUNCHER && !ent->count) {
		// check if the prox mine is outside the owner bbox
		trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, ENTITYNUM_NONE, ent->clipmask );
		if (!tr.startsolid || tr.entityNum != ent->r.ownerNum) {
			ent->count = 1;
		}
	}
	// check think function after bouncing
	G_RunThink( ent );
}
コード例 #3
0
ファイル: g_physics.c プロジェクト: jayschwa/quake2world
/*
 * @brief A moving object that doesn't obey physics
 */
static void G_Physics_Noclip(g_edict_t *ent) {

	if (!G_RunThink(ent))
		return;

	VectorMA(ent->s.angles, gi.frame_seconds, ent->locals.avelocity, ent->s.angles);
	VectorMA(ent->s.origin, gi.frame_seconds, ent->locals.velocity, ent->s.origin);

	gi.LinkEdict(ent);
}
コード例 #4
0
ファイル: g_missile.c プロジェクト: redrumrobot/ubp-qvm
/*
================
G_RunMissile

================
*/
void G_RunMissile( gentity_t *ent )
{
    vec3_t    origin;
    trace_t   tr;
    int     passent;

    // get current position
    BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

    // ignore interactions with the missile owner
    passent = ent->r.ownerNum;

    // trace a line from the previous position to the current position
    trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask );

    if( tr.startsolid || tr.allsolid )
    {
        // make sure the tr.entityNum is set to the entity we're stuck in
        trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask );
        tr.fraction = 0;
    }
    else
        VectorCopy( tr.endpos, ent->r.currentOrigin );

    ent->r.contents = CONTENTS_SOLID; //trick trap_LinkEntity into...
    trap_LinkEntity( ent );
    ent->r.contents = 0; //...encoding bbox information

    if( tr.fraction != 1 )
    {
        // never explode or bounce on sky
        if( tr.surfaceFlags & SURF_NOIMPACT )
        {
            // If grapple, reset owner
            if( ent->parent && ent->parent->client && ent->parent->client->hook == ent )
                ent->parent->client->hook = NULL;

            G_FreeEntity( ent );
            return;
        }

        G_MissileImpact( ent, &tr );
        if( ent->s.eType != ET_MISSILE )
            return;   // exploded
    }

    // check think function after bouncing
    G_RunThink( ent );
}
コード例 #5
0
ファイル: g_missile.cpp プロジェクト: Arcadiaprime/japp
void G_RunStuckMissile( gentity_t *ent ) {
	if ( ent->takedamage ) {
		if ( ent->s.groundEntityNum >= 0 && ent->s.groundEntityNum < ENTITYNUM_WORLD ) {
			gentity_t *other = &g_entities[ent->s.groundEntityNum];

			if ( (!VectorCompare( &vec3_origin, &other->s.pos.trDelta ) && other->s.pos.trType != TR_STATIONARY) ||
				(!VectorCompare( &vec3_origin, &other->s.apos.trDelta ) && other->s.apos.trType != TR_STATIONARY) ) {//thing I stuck to is moving or rotating now, kill me
				G_Damage( ent, other, other, NULL, NULL, 99999, 0, MOD_CRUSH );
				return;
			}
		}
	}
	// check think function
	G_RunThink( ent );
}
コード例 #6
0
ファイル: g_mover.c プロジェクト: AHPlankton/Quake-III-Arena
/*
================
G_RunMover

================
*/
void G_RunMover( gentity_t *ent ) {
	// if not a team captain, don't do anything, because
	// the captain will handle everything
	if ( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	// if stationary at one of the positions, don't move anything
	if ( ent->s.pos.trType != TR_STATIONARY || ent->s.apos.trType != TR_STATIONARY ) {
		G_MoverTeam( ent );
	}

	// check think function
	G_RunThink( ent );
}
コード例 #7
0
ファイル: g_physics.c プロジェクト: jayschwa/quake2world
/*
 * @brief Bmodel objects don't interact with each other, but push all box objects
 */
static void G_Physics_Pusher(g_edict_t *ent) {
	vec3_t move, amove;
	g_edict_t *part, *mv;

	// if not a team captain, so movement will be handled elsewhere
	if (ent->locals.flags & FL_TEAM_SLAVE)
		return;

	// make sure all team slaves can move before committing
	// any moves or calling any think functions
	// if the move is blocked, all moved objects will be backed out
	// retry:
	g_pushed_p = g_pushed;
	for (part = ent; part; part = part->locals.team_chain) {
		if (!VectorCompare(part->locals.velocity, vec3_origin) || !VectorCompare(
				part->locals.avelocity, vec3_origin)) { // object is moving

			VectorScale(part->locals.velocity, gi.frame_seconds, move);
			VectorScale(part->locals.avelocity, gi.frame_seconds, amove);

			if (!G_Push(part, move, amove))
				break; // move was blocked
		}
	}

	if (g_pushed_p > &g_pushed[MAX_EDICTS])
		gi.Error("MAX_EDICTS exceeded\n");

	if (part) {
		// the move failed, bump all next_think times and back out moves
		for (mv = ent; mv; mv = mv->locals.team_chain) {
			if (mv->locals.next_think > 0)
				mv->locals.next_think += gi.frame_millis;
		}

		// if the pusher has a "blocked" function, call it
		// otherwise, just stay in place until the obstacle is gone
		if (part->locals.Blocked)
			part->locals.Blocked(part, obstacle);

	} else {
		// the move succeeded, so call all think functions
		for (part = ent; part; part = part->locals.team_chain) {
			G_RunThink(part);
		}
	}
}
コード例 #8
0
ファイル: g_mover.c プロジェクト: Razish/QtZ
void G_RunMover( gentity_t *ent ) {
	// if not a team captain, don't do anything, because
	// the captain will handle everything
	if ( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	// if stationary at one of the positions, don't move anything
	if ( ent->s.pos.trType != TR_STATIONARY || ent->s.apos.trType != TR_STATIONARY ) {
		//OSP: pause
		if ( level.pause.state == PAUSE_NONE )
			G_MoverTeam( ent );
		else
			ent->s.pos.trTime += level.time - level.previousTime;
	}

	// check think function
	G_RunThink( ent );
}
コード例 #9
0
ファイル: g_items.cpp プロジェクト: Almightygir/OpenJK
/*
================
G_RunItem

================
*/
void G_RunItem( gentity_t *ent ) {
	vec3_t		origin;
	trace_t		tr;
	int			contents;
	int			mask;

	// if groundentity has been set to -1, it may have been pushed off an edge
	if ( ent->s.groundEntityNum == ENTITYNUM_NONE ) 
	{
		if ( ent->s.pos.trType != TR_GRAVITY ) 
		{
			ent->s.pos.trType = TR_GRAVITY;
			ent->s.pos.trTime = level.time;
		}
	}

	if ( ent->s.pos.trType == TR_STATIONARY ) 
	{
		// check think function
		G_RunThink( ent );
		if ( !g_gravity->value )
		{
			ent->s.pos.trType = TR_GRAVITY;
			ent->s.pos.trTime = level.time;
			ent->s.pos.trDelta[0] += crandom() * 40.0f; // I dunno, just do this??
			ent->s.pos.trDelta[1] += crandom() * 40.0f;
			ent->s.pos.trDelta[2] += random() * 20.0f;
		}
		else if ( (ent->flags&FL_DROPPED_ITEM) 
			&& ent->item
			&& ent->item->giType == IT_WEAPON
			&& ent->item->giTag == WP_SABER )
		{//a dropped saber item, check below, just in case
			int ignore = ENTITYNUM_NONE;
			if ( ent->clipmask ) 
			{
				mask = ent->clipmask;
			} 
			else 
			{
				mask = MASK_SOLID|CONTENTS_PLAYERCLIP;//shouldn't be able to get anywhere player can't
			}
			if ( ent->owner )
			{
				ignore = ent->owner->s.number;
			}
			else if ( ent->activator )
			{
				ignore = ent->activator->s.number;
			}
			VectorSet( origin, ent->currentOrigin[0], ent->currentOrigin[1], ent->currentOrigin[2]-1 ); 
			gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, ignore, mask, (EG2_Collision)0, 0 );
			if ( !tr.allsolid
				&& !tr.startsolid
				&& tr.fraction > 0.001f )
			{//wha?  fall....
				ent->s.pos.trType = TR_GRAVITY;
				ent->s.pos.trTime = level.time;
			}
		}
		return;
	}

	// get current position
	EvaluateTrajectory( &ent->s.pos, level.time, origin );
	if ( ent->s.apos.trType != TR_STATIONARY ) 
	{
		EvaluateTrajectory( &ent->s.apos, level.time, ent->currentAngles );
		G_SetAngles( ent, ent->currentAngles );
	}

	// trace a line from the previous position to the current position
	if ( ent->clipmask ) 
	{
		mask = ent->clipmask;
	} 
	else 
	{
		mask = MASK_SOLID|CONTENTS_PLAYERCLIP;//shouldn't be able to get anywhere player can't
	}

	int ignore = ENTITYNUM_NONE;
	if ( ent->owner )
	{
		ignore = ent->owner->s.number;
	}
	else if ( ent->activator )
	{
		ignore = ent->activator->s.number;
	}
	gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, ignore, mask, (EG2_Collision)0, 0 );

	VectorCopy( tr.endpos, ent->currentOrigin );

	if ( tr.startsolid ) 
	{
		tr.fraction = 0;
	}

	gi.linkentity( ent );	// FIXME: avoid this for stationary?

	// check think function
	G_RunThink( ent );

	if ( tr.fraction == 1 ) 
	{
		if ( g_gravity->value <= 0 )
		{
			if ( ent->s.apos.trType != TR_LINEAR )
			{
				VectorCopy( ent->currentAngles, ent->s.apos.trBase );
				ent->s.apos.trType = TR_LINEAR;
				ent->s.apos.trDelta[1] = Q_flrand( -300, 300 );
				ent->s.apos.trDelta[0] = Q_flrand( -10, 10 );
				ent->s.apos.trDelta[2] = Q_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.1 )
			{
				friction = 0.1f;
			}
			*/
			VectorScale( ent->s.pos.trDelta, friction, ent->s.pos.trDelta );
			VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
			ent->s.pos.trTime = level.time;
		}
		return;
	}

	// if it is in a nodrop volume, remove it
	contents = gi.pointcontents( ent->currentOrigin, -1 );
	if ( contents & CONTENTS_NODROP ) 
	{
		G_FreeEntity( ent );
		return;
	}

	if ( !tr.startsolid )
	{
		G_BounceItem( ent, &tr );
	}
}
コード例 #10
0
ファイル: g_main.c プロジェクト: osfpsproject/MF2
/*
================
G_RunFrame

Advances the non-player objects in the world
================
*/
void G_RunFrame( int levelTime ) 
{
	int i;
	// if we are waiting for the level to restart, do nothing
	if( theLevel.restarted_ )
		return;

	theLevel.framenum_++;
	theLevel.previousTime_ = theLevel.time_;
	theLevel.time_ = levelTime;
	int msec = theLevel.time_ - theLevel.previousTime_;

	// get any cvar changes
	G_UpdateCvars();

	//
	// go through all allocated objects
	//
	int start = Sys_Milliseconds();
	GameEntity* ent = 0;//&g_entities[0];
	for( i=0 ; i<theLevel.num_entities_ ; i++ )
	{
		ent = theLevel.getEntity(i);
		if( !ent || !ent->inuse_ ) 
			continue;

		// clear events that are too old
		if( theLevel.time_ - ent->eventTime_ > EVENT_VALID_MSEC ) 
		{
			if( ent->s.event ) 
			{
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if( ent->client_ ) 
				{
					ent->client_->ps_.externalEvent = 0;
					// predicted events should never be set to zero
					//ent->client->ps.events[0] = 0;
					//ent->client->ps.events[1] = 0;
				}
			}
			if( ent->freeAfterEvent_ ) 
			{
				// tempEntities or dropped items completely go away after their event
				ent->freeUp();// former G_FreeEntity
				continue;
			} 
			else if( ent->unlinkAfterEvent_ ) 
			{
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent_ = false;
				SV_UnlinkEntity( ent );
			}
		}
		// temporary entities don't think
		if( ent->freeAfterEvent_ ) 
			continue;

		if( ent->s.eType == ET_MISSILE ||
			 ent->s.eType == ET_BULLET ) 
		{
			G_RunMissile( ent );
			continue;
		}
		if( ent->s.eType == ET_ITEM || ent->physicsObject_ ) 
		{
			G_RunItem( ent );
			continue;
		}
		if( ent->s.eType == ET_MOVER )
		{
			G_RunMover( ent );
			continue;
		}
		if( ent->client_ )
		{
			G_RunClient( ent );
			continue;
		}
		G_RunThink( ent );
	}
	int end = Sys_Milliseconds();

	start = Sys_Milliseconds();
	// perform final fixups on the players
	//ent = &g_entities[0];
	for( i=1 ; i <= theLevel.maxclients_ ; i++ ) 
	{
		ent = theLevel.getEntity(i);
		if( ent && ent->inuse_ ) 
			ClientEndFrame( ent );
	}
	end = Sys_Milliseconds();

	// see if it is time to do a tournement restart
	CheckTournament();

	// see if it is time to end the level
	CheckExitRules();

	// update to team status?
	CheckTeamStatus();

	// cancel vote if timed out
	CheckVote();

	// check team votes
	CheckTeamVote( ClientBase::TEAM_RED );
	CheckTeamVote( ClientBase::TEAM_BLUE );

	// for tracking changes
	CheckCvars();

	if( g_listEntity.integer ) 
	{
		for( i = 0; i < MAX_GENTITIES; i++ )
		{
			ent = theLevel.getEntity(i);
			Com_Printf("%4i: %s\n", i, ent->classname_);
		}
		Cvar_Set("g_listEntity", "0");
	}
}
コード例 #11
0
ファイル: g_physics.c プロジェクト: Asvarox/Unvanquished
/*
================
G_Physics

================
*/
void G_Physics( gentity_t *ent, int msec )
{
	vec3_t  origin;
	trace_t tr;
	int     contents;

	// if groundentity has been set to ENTITYNUM_NONE, it may have been pushed off an edge
	if ( ent->s.groundEntityNum == ENTITYNUM_NONE )
	{
		if ( ent->s.eType == ET_BUILDABLE )
		{
			if ( ent->s.pos.trType != BG_Buildable( ent->s.modelindex )->traj )
			{
				ent->s.pos.trType = BG_Buildable( ent->s.modelindex )->traj;
				ent->s.pos.trTime = level.time;
			}
		}
		else if ( ent->s.pos.trType != TR_GRAVITY )
		{
			ent->s.pos.trType = TR_GRAVITY;
			ent->s.pos.trTime = level.time;
		}
	}

	if ( ent->s.pos.trType == TR_STATIONARY )
	{
		// check think function
		G_RunThink( ent );

		//check floor infrequently
		if ( ent->nextPhysicsTime < level.time )
		{
			VectorCopy( ent->r.currentOrigin, origin );

			VectorMA( origin, -2.0f, ent->s.origin2, origin );

			trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, ent->s.number, ent->clipmask );

			if ( tr.fraction == 1.0f )
			{
				ent->s.groundEntityNum = ENTITYNUM_NONE;
			}

			ent->nextPhysicsTime = level.time + PHYSICS_TIME;
		}

		return;
	}

	// trace a line from the previous position to the current position

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

	trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, ent->s.number, ent->clipmask );

	VectorCopy( tr.endpos, ent->r.currentOrigin );

	if ( tr.startsolid )
	{
		tr.fraction = 0;
	}

	trap_LinkEntity( ent );  // FIXME: avoid this for stationary?

	// check think function
	G_RunThink( ent );

	if ( tr.fraction == 1.0f )
	{
		return;
	}

	// if it is in a nodrop volume, remove it
	contents = trap_PointContents( ent->r.currentOrigin, -1 );

	if ( contents & CONTENTS_NODROP )
	{
		G_FreeEntity( ent );
		return;
	}

	G_Bounce( ent, &tr );
}
コード例 #12
0
ファイル: g_missile.cpp プロジェクト: BSzili/OpenJK
void G_RunMissile( gentity_t *ent ) 
{
	vec3_t		oldOrg;
	trace_t		tr;
	int			trHitLoc=HL_NONE;

	if ( (ent->s.eFlags&EF_HELD_BY_SAND_CREATURE) )
	{//in a sand creature's mouth
		if ( ent->activator )
		{
			mdxaBone_t	boltMatrix;
			// Getting the bolt here
			//in hand
			vec3_t scAngles = {0};
			scAngles[YAW] = ent->activator->currentAngles[YAW];
			gi.G2API_GetBoltMatrix( ent->activator->ghoul2, ent->activator->playerModel, ent->activator->gutBolt, 
					&boltMatrix, scAngles, ent->activator->currentOrigin, (cg.time?cg.time:level.time),
					NULL, ent->activator->s.modelScale );
			// Storing ent position, bolt position, and bolt axis
			gi.G2API_GiveMeVectorFromMatrix( boltMatrix, ORIGIN, ent->currentOrigin );
			G_SetOrigin( ent, ent->currentOrigin );
		}
		// check think function
		G_RunThink( ent );
		return;
	}

	VectorCopy( ent->currentOrigin, oldOrg );

	// get current position
	if ( ent->s.pos.trType == TR_INTERPOLATE )
	{//rolling missile?
		//FIXME: WTF?!!  Sticks to stick missiles?
		//FIXME: they stick inside the player
		G_RollMissile( ent );
		if ( ent->s.eType != ET_GENERAL )
		{//didn't explode
			VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
			gi.trace( &tr, oldOrg, ent->mins, ent->maxs, ent->currentOrigin, ent->s.number, ent->clipmask, G2_RETURNONHIT, 10 );
			if ( VectorCompare( ent->s.pos.trDelta, vec3_origin ) )
			{
				//VectorCopy( ent->currentAngles, ent->s.apos.trBase );
				VectorClear( ent->s.apos.trDelta );
			}
			else
			{
				vec3_t	ang, fwdDir, rtDir;
				float	speed;
				
				ent->s.apos.trType = TR_INTERPOLATE;
				VectorSet( ang, 0, ent->s.apos.trBase[1], 0 );
				AngleVectors( ang, fwdDir, rtDir, NULL );
				speed = VectorLength( ent->s.pos.trDelta )*4;

				//HMM, this works along an axis-aligned dir, but not along diagonals
				//This is because when roll gets to 90, pitch becomes yaw, and vice-versa
				//Maybe need to just set the angles directly?
				ent->s.apos.trDelta[0] = DotProduct( fwdDir, ent->s.pos.trDelta );
				ent->s.apos.trDelta[1] = 0;//never spin!
				ent->s.apos.trDelta[2] = DotProduct( rtDir, ent->s.pos.trDelta );

				VectorNormalize( ent->s.apos.trDelta );
				VectorScale( ent->s.apos.trDelta, speed, ent->s.apos.trDelta );

				ent->s.apos.trTime = level.previousTime;
			}
		}
	}
	else
	{
		vec3_t		origin; 
		EvaluateTrajectory( &ent->s.pos, level.time, origin );
		// trace a line from the previous position to the current position,
		// ignoring interactions with the missile owner
		gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, 
			ent->owner ? ent->owner->s.number : ent->s.number, ent->clipmask, G2_COLLIDE, 10 );
		
		if ( tr.entityNum != ENTITYNUM_NONE )
		{
			gentity_t *other = &g_entities[tr.entityNum];
			// check for hitting a lightsaber
			if ( other->contents & CONTENTS_LIGHTSABER )
			{//hit a lightsaber bbox
				if ( other->owner 
					&& other->owner->client 
					&& !other->owner->client->ps.saberInFlight 
					&& ( Q_irand( 0, (other->owner->client->ps.forcePowerLevel[FP_SABER_DEFENSE]*other->owner->client->ps.forcePowerLevel[FP_SABER_DEFENSE]) ) == 0 
						|| !InFront( ent->currentOrigin, other->owner->currentOrigin, other->owner->client->ps.viewangles, SABER_REFLECT_MISSILE_CONE ) ) )//other->owner->s.number == 0 &&
				{//Jedi cannot block shots from behind!
					//re-trace from here, ignoring the lightsaber
					gi.trace( &tr, tr.endpos, ent->mins, ent->maxs, origin, tr.entityNum, ent->clipmask, G2_RETURNONHIT, 10 );
				}
			}
		}

		VectorCopy( tr.endpos, ent->currentOrigin );
	}

	// get current angles
	VectorMA( ent->s.apos.trBase, (level.time - ent->s.apos.trTime) * 0.001, ent->s.apos.trDelta, ent->s.apos.trBase );

	//FIXME: Rolling things hitting G2 polys is weird
	///////////////////////////////////////////////////////
//?	if ( tr.fraction != 1 ) 
	{
	// did we hit or go near a Ghoul2 model?
//		qboolean hitModel = qfalse;
		for (int i=0; i < MAX_G2_COLLISIONS; i++)
		{
			if (tr.G2CollisionMap[i].mEntityNum == -1)
			{
				break;
			}

			CCollisionRecord &coll = tr.G2CollisionMap[i];
			gentity_t	*hitEnt = &g_entities[coll.mEntityNum];

			// process collision records here...
			// make sure we only do this once, not for all the entrance wounds we might generate
			if ((coll.mFlags & G2_FRONTFACE)/* && !(hitModel)*/ && hitEnt->health)
			{
				if (trHitLoc==HL_NONE)
				{
					G_GetHitLocFromSurfName( &g_entities[coll.mEntityNum], gi.G2API_GetSurfaceName( &g_entities[coll.mEntityNum].ghoul2[coll.mModelIndex], coll.mSurfaceIndex ), &trHitLoc, coll.mCollisionPosition, NULL, NULL, ent->methodOfDeath );
				}

				break; // NOTE: the way this whole section was working, it would only get inside of this IF once anyway, might as well break out now
			}
		}
	}
/////////////////////////////////////////////////////////

	if ( tr.startsolid ) 
	{
		tr.fraction = 0;
	}

	gi.linkentity( ent );

	if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
	{//stuck missiles should check some special stuff
		G_RunStuckMissile( ent );
		return;
	}

	// check think function
	G_RunThink( ent );

	if ( ent->s.eType != ET_MISSILE ) 
	{
		return;		// exploded
	}

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

	AddSightEvent( ent->owner, ent->currentOrigin, 512, AEL_DISCOVERED, 75 );//wakes them up when see a shot passes in front of them
	if ( !Q_irand( 0, 10 ) )
	{//not so often...
		if ( ent->splashDamage && ent->splashRadius )
		{//I'm an exploder, let people around me know danger is coming
			if ( ent->s.weapon == WP_TRIP_MINE )
			{//???
			}
			else 
			{
				if ( ent->s.weapon == WP_ROCKET_LAUNCHER && ent->e_ThinkFunc == thinkF_rocketThink )
				{//homing rocket- run like hell!
					AddSightEvent( ent->owner, ent->currentOrigin, ent->splashRadius, AEL_DANGER_GREAT, 50 );
				}
				else
				{
					AddSightEvent( ent->owner, ent->currentOrigin, ent->splashRadius, AEL_DANGER, 50 );
				}
				AddSoundEvent( ent->owner, ent->currentOrigin, ent->splashRadius, AEL_DANGER );
			}
		}
		else
		{//makes them run from near misses
			AddSightEvent( ent->owner, ent->currentOrigin, 48, AEL_DANGER, 50 );
		}
	}

	if ( tr.fraction == 1 ) 
	{
		if ( ent->s.weapon == WP_THERMAL && ent->s.pos.trType == TR_INTERPOLATE )
		{//a rolling thermal that didn't hit anything
			G_MissileAddAlerts( ent );
		}
		return;
	}

	// never explode or bounce on sky
	if ( tr.surfaceFlags & SURF_NOIMPACT ) 
	{
		G_FreeEntity( ent );
		return;
	}

	G_MissileImpact( ent, &tr, trHitLoc );
}
コード例 #13
0
/*
================
G_RunFrame

Advances the non-player objects in the world
================
*/
void G_RunFrame( int levelTime ) {
	int			i;
	gentity_t	*ent;

	// if we are waiting for the level to restart, do nothing
	if ( level.restarted ) {
		return;
	}

	level.framenum++;
	level.previousTime = level.time;
	level.time = levelTime;

	// get any cvar changes
	G_UpdateCvars();

	//
	// go through all allocated objects
	//
	ent = &g_entities[0];
	for (i=0 ; i<level.num_entities ; i++, ent++) {
		if ( !ent->inuse ) {
			continue;
		}

		// clear events that are too old
		if ( level.time - ent->eventTime > EVENT_VALID_MSEC ) {
			if ( ent->s.event ) {
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if ( ent->client ) {
					ent->client->ps.externalEvent = 0;
					// predicted events should never be set to zero
					//ent->client->ps.events[0] = 0;
					//ent->client->ps.events[1] = 0;
				}
			}
			if ( ent->freeAfterEvent ) {
				// tempEntities or dropped items completely go away after their event
				G_FreeEntity( ent );
				continue;
			} else if ( ent->unlinkAfterEvent ) {
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent = qfalse;
				trap_UnlinkEntity( ent );
			}
		}

		// temporary entities don't think
		if ( ent->freeAfterEvent ) {
			continue;
		}

		if ( !ent->r.linked && ent->neverFree ) {
			continue;
		}

		if ( ent->s.eType == ET_MISSILE ) {
			G_RunMissile( ent );
			continue;
		}

		if ( ent->s.eType == ET_ITEM || ent->physicsObject ) {
			G_RunItem( ent );
			continue;
		}

		if ( ent->s.eType == ET_MOVER ) {
			G_RunMover( ent );
			continue;
		}

		if ( i < MAX_CLIENTS ) {
			G_RunClient( ent );
			continue;
		}

		G_RunThink( ent );
	}

	// perform final fixups on the players
	ent = &g_entities[0];
	for (i=0 ; i < level.maxclients ; i++, ent++ ) {
		if ( ent->inuse ) {
			ClientEndFrame( ent );
		}
	}

	// see if it is time to do a tournement restart
	CheckTournament();

	// see if it is time to end the level
	CheckExitRules();

	// update to team status?
	CheckTeamStatus();

	// cancel vote if timed out
	CheckVote();

	// check team votes
	CheckTeamVote( TEAM_RED );
	CheckTeamVote( TEAM_BLUE );

	// for tracking changes
	CheckCvars();

	if (g_listEntity.integer) {
		for (i = 0; i < MAX_GENTITIES; i++) {
			G_Printf("%4i: %s\n", i, g_entities[i].classname);
		}
		trap_Cvar_Set("g_listEntity", "0");
	}
}
コード例 #14
0
ファイル: g_physics.c プロジェクト: jayschwa/quake2world
/*
 * @brief Non moving objects can only think
 */
static void G_Physics_None(g_edict_t *ent) {
	// regular thinking
	G_RunThink(ent);
}
コード例 #15
0
ファイル: g_physics.c プロジェクト: jayschwa/quake2world
/*
 * @brief Toss, bounce, and fly movement. When on ground, do nothing.
 */
static void G_Physics_Toss(g_edict_t *ent) {
	vec3_t org, move;

	// regular thinking
	G_RunThink(ent);

	// if not a team captain, movement will be handled elsewhere
	if (ent->locals.flags & FL_TEAM_SLAVE)
		return;

	// check for the ground entity going away
	if (ent->locals.ground_entity) {
		if (!ent->locals.ground_entity->in_use)
			ent->locals.ground_entity = NULL;
		else if (ent->locals.velocity[2] > ent->locals.ground_entity->locals.velocity[2] + 0.1)
			ent->locals.ground_entity = NULL;
		else
			return;
	}

	// if on ground, or intentionally floating, return without moving
	if (ent->locals.ground_entity || (ent->locals.item && (ent->locals.spawn_flags & 4)))
		return;

	// enforce max velocity values
	G_ClampVelocity(ent);

	// move angles
	VectorMA(ent->s.angles, gi.frame_seconds, ent->locals.avelocity, ent->s.angles);

	// move origin
	VectorCopy(ent->s.origin, org);
	VectorScale(ent->locals.velocity, gi.frame_seconds, move);

	// push through the world, interacting with triggers and other ents
	c_trace_t trace = G_PushEntity(ent, move);

	if (!ent->in_use)
		return;

	if (trace.fraction < 1.0) { // move was blocked

		// if it was a floor, we might bounce or come to rest
		vec_t *vel = ent->locals.velocity;
		if (G_ClipVelocity(vel, trace.plane.normal, vel, 1.3) & 1) {

			VectorSubtract(ent->s.origin, org, move);

			// if we're approaching a stop, clear our velocity and set ground
			if (VectorLength(move) < STOP_EPSILON) {

				VectorClear(ent->locals.velocity);

				ent->locals.ground_entity = trace.ent;
				ent->locals.ground_entity_link_count = trace.ent->link_count;
			} else {
				// bounce and slide along the floor
				vec_t bounce, speed = VectorLength(ent->locals.velocity);
				bounce = sqrt(speed);

				if (ent->locals.velocity[2] < bounce)
					ent->locals.velocity[2] = bounce;
			}
		}

		// all impacts reduce velocity and angular velocity
		VectorScale(ent->locals.velocity, 0.9, ent->locals.velocity);
		VectorScale(ent->locals.avelocity, 0.9, ent->locals.avelocity);
	}

	// check for water transition
	const _Bool was_in_water = (ent->locals.water_type & MASK_WATER);
	ent->locals.water_type = gi.PointContents(ent->s.origin);
	const _Bool is_in_water = ent->locals.water_type & MASK_WATER;

	if (is_in_water)
		ent->locals.water_level = 1;
	else
		ent->locals.water_level = 0;

	// add gravity
	if (ent->locals.move_type == MOVE_TYPE_FLY)
		G_AddFlying(ent);
	else
		G_AddGravity(ent);

	if (!was_in_water && is_in_water) {
		gi.PositionedSound(ent->s.origin, g_game.edicts, gi.SoundIndex("world/water_in"), ATTEN_NORM);
		VectorScale(ent->locals.velocity, 0.66, ent->locals.velocity);
	} else if (was_in_water && !is_in_water)
		gi.PositionedSound(ent->s.origin, g_game.edicts, gi.SoundIndex("world/water_out"),
				ATTEN_NORM);

	// move team slaves
	g_edict_t *slave = ent->locals.team_chain;
	while (slave) {
		VectorCopy(ent->s.origin, slave->s.origin);
		gi.LinkEdict(slave);

		slave = slave->locals.team_chain;
	}
}
コード例 #16
0
ファイル: g_missile.c プロジェクト: OADoctor/SmokinGuns
void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
#else
void G_MissileImpact( gentity_t *ent, trace_t *trace, int shaderNum ) {
#endif
	gentity_t		*other;
	qboolean		hitClient = qfalse;
#ifndef SMOKINGUNS
#ifdef MISSIONPACK
	vec3_t			forward, impactpoint, bouncedir;
	int				eFlags;
#endif
#else
	qboolean		hitKnife  = qfalse;
	vec3_t			bottledirs[ALC_COUNT];
#endif
	other = &g_entities[trace->entityNum];

#ifndef SMOKINGUNS
	// check for bounce
	if ( !other->takedamage &&
		( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) ) {
		G_BounceMissile( ent, trace );
		G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
		return;
	}

#ifdef MISSIONPACK
	if ( other->takedamage ) {
		if ( ent->s.weapon != WP_PROX_LAUNCHER ) {
			if ( other->client && other->client->invulnerabilityTime > level.time ) {
				//
				VectorCopy( ent->s.pos.trDelta, forward );
				VectorNormalize( forward );
				if (G_InvulnerabilityEffect( other, forward, ent->s.pos.trBase, impactpoint, bouncedir )) {
					VectorCopy( bouncedir, trace->plane.normal );
					eFlags = ent->s.eFlags & EF_BOUNCE_HALF;
					ent->s.eFlags &= ~EF_BOUNCE_HALF;
					G_BounceMissile( ent, trace );
					ent->s.eFlags |= eFlags;
				}
				ent->target_ent = other;
				return;
			}
		}
	}
#endif
	// impact damage
	if (other->takedamage) {
#else
	if(other->takedamage)
		hitKnife = qtrue;

	// check for bounce
	if ( ( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) ) {
		G_BounceMissile( ent, trace );
		return;
	}

	if (other->takedamage && ent->s.weapon != WP_DYNAMITE) {
#endif
		// FIXME: wrong damage direction?
		if ( ent->damage ) {
			vec3_t	velocity;

			if( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) {
				g_entities[ent->r.ownerNum].client->accuracy_hits++;
				hitClient = qtrue;
			}
			BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity );
			if ( VectorLength( velocity ) == 0 ) {
				velocity[2] = 1;	// stepped on a grenade
			}
#ifndef SMOKINGUNS
			G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
				ent->s.origin, ent->damage,
				0, ent->methodOfDeath);
#else

			// you can't make dynamite exploding by using a knife
			if(!(ent->s.weapon == WP_KNIFE && other->s.weapon == WP_DYNAMITE &&
				other->s.eType == ET_ITEM)){

				// prepare breakable, if not already initialized
				if(!(other->flags & FL_BREAKABLE_INIT))
					G_BreakablePrepare(other, shaderNum);

				G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity,
					ent->s.origin, ent->damage,
					0, ent->methodOfDeath);
			}
#endif
		}
	}

#ifndef SMOKINGUNS
	if( ent->s.weapon == WP_PROX_LAUNCHER ) {
		if( ent->s.pos.trType != TR_GRAVITY ) {
			return;
		}

		// if it's a player, stick it on to them (flag them and remove this entity)
		if( other->s.eType == ET_PLAYER && other->health > 0 ) {
			ProximityMine_Player( ent, other );
			return;
		}

		SnapVectorTowards( trace->endpos, ent->s.pos.trBase );
		G_SetOrigin( ent, trace->endpos );
		ent->s.pos.trType = TR_STATIONARY;
		VectorClear( ent->s.pos.trDelta );

		G_AddEvent( ent, EV_PROXIMITY_MINE_STICK, trace->surfaceFlags );

		ent->think = ProximityMine_Activate;
		ent->nextthink = level.time + 2000;

		vectoangles( trace->plane.normal, ent->s.angles );
		ent->s.angles[0] += 90;

		// link the prox mine to the other entity
		ent->enemy = other;
		ent->die = ProximityMine_Die;
		VectorCopy(trace->plane.normal, ent->movedir);
		VectorSet(ent->r.mins, -4, -4, -4);
		VectorSet(ent->r.maxs, 4, 4, 4);
		trap_LinkEntity(ent);

		return;
	}

	if (!strcmp(ent->classname, "hook")) {
		gentity_t *nent;
		vec3_t v;

		nent = G_Spawn();
		if ( other->takedamage && other->client ) {

			G_AddEvent( nent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
			nent->s.otherEntityNum = other->s.number;

			ent->enemy = other;

			v[0] = other->r.currentOrigin[0] + (other->r.mins[0] + other->r.maxs[0]) * 0.5;
			v[1] = other->r.currentOrigin[1] + (other->r.mins[1] + other->r.maxs[1]) * 0.5;
			v[2] = other->r.currentOrigin[2] + (other->r.mins[2] + other->r.maxs[2]) * 0.5;

			SnapVectorTowards( v, ent->s.pos.trBase );	// save net bandwidth
		} else {
			VectorCopy(trace->endpos, v);
			G_AddEvent( nent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
			ent->enemy = NULL;
		}

		SnapVectorTowards( v, ent->s.pos.trBase );	// save net bandwidth

		nent->freeAfterEvent = qtrue;
		// change over to a normal entity right at the point of impact
		nent->s.eType = ET_GENERAL;
		ent->s.eType = ET_GRAPPLE;

		G_SetOrigin( ent, v );
		G_SetOrigin( nent, v );

		ent->think = Weapon_HookThink;
		ent->nextthink = level.time + FRAMETIME;

		ent->parent->client->ps.pm_flags |= PMF_GRAPPLE_PULL;
		VectorCopy( ent->r.currentOrigin, ent->parent->client->ps.grapplePoint);

		trap_LinkEntity( ent );
		trap_LinkEntity( nent );

		return;
	}
#endif

	// is it cheaper in bandwidth to just remove this ent and create a new
	// one, rather than changing the missile into the explosion?

#ifndef SMOKINGUNS
	if ( other->takedamage && other->client ) {
#else
	// alcoohol impact
	if( !Q_stricmp(ent->classname, "alcohol")){
		// no event
		//G_AddEvent( ent, EV_MISSILE_ALCOHOL, DirToByte( trace->plane.normal));
	} else if( !Q_stricmp(ent->classname, "molotov")){
		// we have to launch the whiskey drops
		int i;

		// set the directions
		for(i = 0; i < ALC_COUNT; i++){
			int temp;

			VectorSet(bottledirs[i], (rand()%10)-5, (rand()%10)-5, (rand()%10)-3);

			// direction has to be exactly the same (client and server)
			temp = DirToByte(bottledirs[i]);
			ByteToDir(temp, bottledirs[i]);
		}

		// dirs
		BG_DirsToEntityState(&ent->s, bottledirs);

		// burning
		if(ent->s.apos.trDelta[0])
			G_AddEvent( ent, EV_MISSILE_FIRE, DirToByte( trace->plane.normal));
		// not burning
		else
			G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( trace->plane.normal));
	} else if ( other->takedamage && other->client ) {
#endif
		G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) );
		ent->s.otherEntityNum = other->s.number;
#ifndef SMOKINGUNS
	} else if( trace->surfaceFlags & SURF_METALSTEPS ) {
#else
	} else if( trace->surfaceFlags & SURF_METAL ) {
#endif
		G_AddEvent( ent, EV_MISSILE_MISS_METAL, DirToByte( trace->plane.normal ) );
	} else {
		G_AddEvent( ent, EV_MISSILE_MISS, DirToByte( trace->plane.normal ) );
	}

#ifndef SMOKINGUNS
	ent->freeAfterEvent = qtrue;

	// change over to a normal entity right at the point of impact
	ent->s.eType = ET_GENERAL;
#else
	if(Q_stricmp(ent->classname, "knife")){
		ent->freeAfterEvent = qtrue;
		// change over to a normal entity right at the point of impact
		ent->s.eType = ET_GENERAL;
	} else {
		vec3_t dir;
		gitem_t			*item;

		item = BG_FindItemForWeapon(WP_KNIFE);

		ent->s.modelindex = item-bg_itemlist;
		ent->s.modelindex2 = 1;

		ent->item = item;

		ent->s.eType = ET_ITEM;
		ent->s.pos.trType = TR_GRAVITY;
		ent->physicsBounce = 0.01f;
		ent->r.contents = CONTENTS_TRIGGER;

		ent->touch = Touch_Item;
		ent->nextthink = level.time + 100;
		ent->think = G_KnifeThink;
		ent->wait = level.time + 30000;
		ent->flags |= FL_THROWN_ITEM;

		vectoangles(ent->s.pos.trDelta, dir);

		VectorCopy(dir, ent->s.apos.trBase);
		VectorCopy(dir, ent->r.currentAngles);
	}
	//modified by Spoon END
#endif

	SnapVectorTowards( trace->endpos, ent->s.pos.trBase );	// save net bandwidth

	G_SetOrigin( ent, trace->endpos );

	// splash damage (doesn't apply to person directly hit)
	if ( ent->splashDamage ) {
		if( G_RadiusDamage( trace->endpos, ent->parent, ent->splashDamage, ent->splashRadius,
			other, ent->splashMethodOfDeath ) ) {
			if( !hitClient ) {
				g_entities[ent->r.ownerNum].client->accuracy_hits++;
			}
		}
	}

	// spawn alcohol missiles
#ifdef SMOKINGUNS
	if(!Q_stricmp(ent->classname, "molotov")){
		BottleBreak( ent, trace->endpos, trace->plane.normal, bottledirs);
	}
#endif

	trap_LinkEntity( ent );
}

/*
================
G_RunMissile
================
*/
void G_RunMissile( gentity_t *ent ) {
	vec3_t		origin;
	trace_t		tr;
	int			passent;
#ifdef SMOKINGUNS
	int			shaderNum;
	gentity_t	*traceEnt;
#endif

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

	// if this missile bounced off an invulnerability sphere
	if ( ent->target_ent ) {
		passent = ent->target_ent->s.number;
	}
#ifndef SMOKINGUNS
	// prox mines that left the owner bbox will attach to anything, even the owner
	else if (ent->s.weapon == WP_PROX_LAUNCHER && ent->count) {
		passent = ENTITYNUM_NONE;
	}
#endif
	else {
		// ignore interactions with the missile owner
		passent = ent->r.ownerNum;
	}
	// trace a line from the previous position to the current position
#ifndef SMOKINGUNS
	trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask );
#else
	shaderNum = trap_Trace_New2( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask );
	traceEnt = &g_entities[tr.entityNum];
#endif

	if ( tr.startsolid || tr.allsolid ) {
		// make sure the tr.entityNum is set to the entity we're stuck in
#ifndef SMOKINGUNS
		trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask );
#else
		trap_Trace_New( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask );
#endif
		tr.fraction = 0;
	}
	else {
		VectorCopy( tr.endpos, ent->r.currentOrigin );
	}

	trap_LinkEntity( ent );

	if ( tr.fraction != 1 ) {

#ifdef SMOKINGUNS
		VectorCopy(origin, ent->s.origin2);
#endif

		// never explode or bounce on sky
		if ( tr.surfaceFlags & SURF_NOIMPACT ) {
			// If grapple, reset owner
			if (ent->parent && ent->parent->client && ent->parent->client->hook == ent) {
				ent->parent->client->hook = NULL;
			}

			// if its a dynamite or molotov let it move 10 seconds before deleting it
#ifdef SMOKINGUNS
			if(ent->s.weapon == WP_DYNAMITE || ent->s.weapon == WP_MOLOTOV
				|| ent->s.weapon == WP_KNIFE){

				if(ent->mappart >= level.time && ent->mappart){
					goto think;
				} else if(ent->mappart){
					ent->mappart = 0;
				} else {
					ent->mappart = level.time + 5000;
					goto think;
				}
			}
#endif
			G_FreeEntity( ent );
			return;
		}
#ifndef SMOKINGUNS
		G_MissileImpact( ent, &tr );
		if ( ent->s.eType != ET_MISSILE ) {
#else
		G_MissileImpact( ent, &tr, shaderNum );
		if ( ent->s.eType != ET_MISSILE && ent->s.eType != ET_ITEM) {
#endif
			return;		// exploded
		}
	}
#ifndef SMOKINGUNS
	// if the prox mine wasn't yet outside the player body
	if (ent->s.weapon == WP_PROX_LAUNCHER && !ent->count) {
		// check if the prox mine is outside the owner bbox
		trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, ENTITYNUM_NONE, ent->clipmask );
		if (!tr.startsolid || tr.entityNum != ent->r.ownerNum) {
			ent->count = 1;
		}
	}
#endif

think:
	// check think function after bouncing
	G_RunThink( ent );
}


//=============================================================================

#ifndef SMOKINGUNS
/*
=================
fire_plasma

=================
*/
gentity_t *fire_plasma (gentity_t *self, vec3_t start, vec3_t dir) {
	gentity_t	*bolt;

	VectorNormalize (dir);

	bolt = G_Spawn();
	bolt->classname = "plasma";
	bolt->nextthink = level.time + 10000;
	bolt->think = G_ExplodeMissile;
	bolt->s.eType = ET_MISSILE;
	bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
	bolt->s.weapon = WP_PLASMAGUN;
	bolt->r.ownerNum = self->s.number;
	bolt->parent = self;
	bolt->damage = 20;
	bolt->splashDamage = 15;
	bolt->splashRadius = 20;
	bolt->methodOfDeath = MOD_PLASMA;
	bolt->splashMethodOfDeath = MOD_PLASMA_SPLASH;
	bolt->clipmask = MASK_SHOT;
	bolt->target_ent = NULL;

	bolt->s.pos.trType = TR_LINEAR;
	bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;		// move a bit on the very first frame
	VectorCopy( start, bolt->s.pos.trBase );
	VectorScale( dir, 2000, bolt->s.pos.trDelta );
	SnapVector( bolt->s.pos.trDelta );			// save net bandwidth

	VectorCopy (start, bolt->r.currentOrigin);

	return bolt;
}

//=============================================================================


/*
=================
fire_grenade
=================
*/
gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
	gentity_t	*bolt;

	VectorNormalize (dir);

	bolt = G_Spawn();
	bolt->classname = "grenade";
	bolt->nextthink = level.time + 2500;
	bolt->think = G_ExplodeMissile;
	bolt->s.eType = ET_MISSILE;
	bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
	bolt->s.weapon = WP_GRENADE_LAUNCHER;
	bolt->s.eFlags = EF_BOUNCE_HALF;
	bolt->r.ownerNum = self->s.number;
	bolt->parent = self;
	bolt->damage = 100;
	bolt->splashDamage = 100;
	bolt->splashRadius = 150;
	bolt->methodOfDeath = MOD_GRENADE;
	bolt->splashMethodOfDeath = MOD_GRENADE_SPLASH;
	bolt->clipmask = MASK_SHOT;
	bolt->target_ent = NULL;

	bolt->s.pos.trType = TR_GRAVITY;
	bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME;		// move a bit on the very first frame
	VectorCopy( start, bolt->s.pos.trBase );
	VectorScale( dir, 700, bolt->s.pos.trDelta );
	SnapVector( bolt->s.pos.trDelta );			// save net bandwidth

	VectorCopy (start, bolt->r.currentOrigin);

	return bolt;
}
コード例 #17
0
void G_RunMissile( gentity_t *ent )
{
	vec3_t   origin;
	trace_t  tr;
	int      passent;
	bool impact = false;

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

	// ignore interactions with the missile owner
	passent = ent->r.ownerNum;

	// general trace to see if we hit anything at all
	trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs,
	            origin, passent, ent->clipmask, 0 );

	if ( tr.startsolid || tr.allsolid )
	{
		tr.fraction = 0.0f;
		VectorCopy( ent->r.currentOrigin, tr.endpos );
	}

	if ( tr.fraction < 1.0f )
	{
		if ( !ent->pointAgainstWorld || (tr.contents & CONTENTS_BODY) )
		{
			// We hit an entity or we don't care
			impact = true;
		}
		else
		{
			trap_Trace( &tr, ent->r.currentOrigin, nullptr, nullptr, origin,
			            passent, ent->clipmask, 0 );

			if ( tr.fraction < 1.0f )
			{
				// Hit the world with point trace
				impact = true;
			}
			else
			{
				if ( tr.contents & CONTENTS_BODY )
				{
					// Hit an entity
					impact = true;
				}
				else
				{
					trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs,
					            origin, passent, CONTENTS_BODY, 0 );

					if ( tr.fraction < 1.0f )
					{
						impact = true;
					}
				}
			}
		}
	}

	VectorCopy( tr.endpos, ent->r.currentOrigin );

	if ( impact )
	{
		// Never explode or bounce when hitting the sky.
		if ( tr.surfaceFlags & SURF_NOIMPACT )
		{
			G_FreeEntity( ent );

			return;
		}

		// Check for impact damage and effects.
		MissileImpact( ent, &tr );

		// Check if the entity was freed during impact.
		if ( !ent->inuse )
		{
			return;
		}

		// HACK: The missile has turned into an explosion and will free itself later.
		//       See MissileImpact for more.
		if ( ent->s.eType != ET_MISSILE )
		{
			return;
		}
	}

	ent->r.contents = CONTENTS_SOLID; //trick trap_LinkEntity into...
	trap_LinkEntity( ent );
	ent->r.contents = 0; //...encoding bbox information

	if ( ent->flightSplashDamage )
	{
		G_RadiusDamage( tr.endpos, ent->parent, ent->flightSplashDamage, ent->flightSplashRadius,
		                ent->parent, 0, ent->splashMethodOfDeath );
	}

	// check think function after bouncing
	G_RunThink( ent );
}
コード例 #18
0
ファイル: g_missile.c プロジェクト: videoP/jaPRO
/*
================
G_RunMissile
================
*/
void G_RunMissile( gentity_t *ent ) {
    vec3_t		origin, groundSpot;
    trace_t		tr;
    int			passent;
    qboolean	isKnockedSaber = qfalse;

    if (ent->neverFree && ent->s.weapon == WP_SABER && (ent->flags & FL_BOUNCE_HALF))
    {
        isKnockedSaber = qtrue;
        ent->s.pos.trType = TR_GRAVITY;
    }

    // get current position
    BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );


    //If its a rocket, and older than 500ms, make it solid to the shooter.
    if ((g_tweakWeapons.integer & WT_SOLID_ROCKET) && (ent->s.weapon == WP_ROCKET_LAUNCHER) && (!ent->raceModeShooter) && (ent->nextthink - level.time < 9500)) {
        ent->r.ownerNum = ENTITYNUM_WORLD;
    }

    // if this missile bounced off an invulnerability sphere
    if ( ent->target_ent ) {
        passent = ent->target_ent->s.number;
    }
    else {
        // ignore interactions with the missile owner
        if ( (ent->r.svFlags&SVF_OWNERNOTSHARED)
                && (ent->s.eFlags&EF_JETPACK_ACTIVE) )
        {   //A vehicle missile that should be solid to its owner
            //I don't care about hitting my owner
            passent = ent->s.number;
        }
        else
        {
            passent = ent->r.ownerNum;
        }
    }
    // trace a line from the previous position to the current position
    if (d_projectileGhoul2Collision.integer == 1) //JAPRO - Serverside - Weapons - New Hitbox Option
    {
        JP_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask, qfalse, G2TRFLAG_DOGHOULTRACE|G2TRFLAG_GETSURFINDEX|G2TRFLAG_THICK|G2TRFLAG_HITCORPSES, g_g2TraceLod.integer );

        if (tr.fraction != 1.0 && tr.entityNum < ENTITYNUM_WORLD)
        {
            gentity_t *g2Hit = &g_entities[tr.entityNum];

            if (g2Hit->inuse && g2Hit->client && g2Hit->ghoul2)
            {   //since we used G2TRFLAG_GETSURFINDEX, tr.surfaceFlags will actually contain the index of the surface on the ghoul2 model we collided with.
                g2Hit->client->g2LastSurfaceHit = tr.surfaceFlags;
                g2Hit->client->g2LastSurfaceTime = level.time;
            }

            if (g2Hit->ghoul2)
            {
                tr.surfaceFlags = 0; //clear the surface flags after, since we actually care about them in here.
            }
        }
    }
    else
    {
        JP_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask, qfalse, 0, 0 );
    }

    if ( tr.startsolid || tr.allsolid ) {
        // make sure the tr.entityNum is set to the entity we're stuck in
        JP_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask, qfalse, 0, 0 );
        tr.fraction = 0;
    }
    else {
        VectorCopy( tr.endpos, ent->r.currentOrigin );
    }

    if (ent->passThroughNum && tr.entityNum == (ent->passThroughNum-1))
    {
        VectorCopy( origin, ent->r.currentOrigin );
        trap->LinkEntity( (sharedEntity_t *)ent );
        goto passthrough;
    }

    trap->LinkEntity( (sharedEntity_t *)ent );

    if (ent->s.weapon == G2_MODEL_PART && !ent->bounceCount)
    {
        vec3_t lowerOrg;
        trace_t trG;

        VectorCopy(ent->r.currentOrigin, lowerOrg);
        lowerOrg[2] -= 1;
        JP_Trace( &trG, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, lowerOrg, passent, ent->clipmask, qfalse, 0, 0 );

        VectorCopy(trG.endpos, groundSpot);

        if (!trG.startsolid && !trG.allsolid && trG.entityNum == ENTITYNUM_WORLD)
        {
            ent->s.groundEntityNum = trG.entityNum;
        }
        else
        {
            ent->s.groundEntityNum = ENTITYNUM_NONE;
        }
    }

    if (tr.fraction != 1) { //Hit something maybe
        qboolean skip = qfalse;

        gentity_t *other = &g_entities[tr.entityNum]; //Check to see if we hit a lightsaber and they are in another dimension, if so dont do the hit code..
        if (other && other->r.contents & CONTENTS_LIGHTSABER)
        {
            gentity_t *otherOwner = &g_entities[other->r.ownerNum];
            gentity_t *owner = &g_entities[ent->r.ownerNum];
            /*
            if (owner->s.bolt1 && !otherOwner->s.bolt1)//We are dueling/racing and they are not
            	skip = qtrue;
            else if (!owner->s.bolt1 && otherOwner->s.bolt1)//They are dueling/racing and we are not
            	skip = qtrue;
            */
            if (owner->s.bolt1 != otherOwner->s.bolt1) //Dont impact if its from another dimension
                skip = qtrue;
        }

        if ( tr.fraction != 1 && !skip) {

            // never explode or bounce on sky
            if ( tr.surfaceFlags & SURF_NOIMPACT ) {
                // If grapple, reset owner
                if (ent->parent && ent->parent->client && ent->parent->client->hook == ent) {
                    ent->parent->client->hook = NULL;
                }

                if ((ent->s.weapon == WP_SABER && ent->isSaberEntity) || isKnockedSaber)
                {
                    G_RunThink( ent );
                    return;
                }
                else if (ent->s.weapon != G2_MODEL_PART)
                {
                    G_FreeEntity( ent );
                    return;
                }
            }

            if (ent->s.weapon > WP_NONE && ent->s.weapon < WP_NUM_WEAPONS &&
                    (tr.entityNum < MAX_CLIENTS || g_entities[tr.entityNum].s.eType == ET_NPC))
            {   //player or NPC, try making a mark on him
                //copy current pos to s.origin, and current projected traj to origin2
                VectorCopy(ent->r.currentOrigin, ent->s.origin);
                BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin2 );

                if (VectorCompare(ent->s.origin, ent->s.origin2))
                {
                    ent->s.origin2[2] += 2.0f; //whatever, at least it won't mess up.
                }
            }

            G_MissileImpact( ent, &tr );

            if (tr.entityNum == ent->s.otherEntityNum)
            {   //if the impact event other and the trace ent match then it's ok to do the g2 mark
                ent->s.trickedentindex = 1;
            }

            if ( ent->s.eType != ET_MISSILE && ent->s.weapon != G2_MODEL_PART )
            {
                return;		// exploded
            }
        }
    }

passthrough:
    if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
    {   //stuck missiles should check some special stuff
        G_RunStuckMissile( ent );
        return;
    }

    if (ent->s.weapon == G2_MODEL_PART)
    {
        if (ent->s.groundEntityNum == ENTITYNUM_WORLD)
        {
            ent->s.pos.trType = TR_LINEAR;
            VectorClear(ent->s.pos.trDelta);
            ent->s.pos.trTime = level.time;

            VectorCopy(groundSpot, ent->s.pos.trBase);
            VectorCopy(groundSpot, ent->r.currentOrigin);

            if (ent->s.apos.trType != TR_STATIONARY)
            {
                ent->s.apos.trType = TR_STATIONARY;
                ent->s.apos.trTime = level.time;

                ent->s.apos.trBase[ROLL] = 0;
                ent->s.apos.trBase[PITCH] = 0;
            }
        }
    }
    // check think function after bouncing
    G_RunThink( ent );
}
コード例 #19
0
void G_RunMissile( gentity_t *ent ) 
{
	vec3_t		origin, oldOrg;
	trace_t		tr;
	int			trHitLoc=HL_NONE;

	VectorCopy( ent->currentOrigin, oldOrg );

	// get current position
	if ( ent->s.pos.trType == TR_INTERPOLATE )
	{//rolling missile?
		//FIXME: WTF?!!  Sticks to stick missiles?
		//FIXME: they stick inside the player
		G_RollMissile( ent );
		if ( ent->s.eType != ET_GENERAL )
		{//didn't explode
			VectorCopy( ent->currentOrigin, ent->s.pos.trBase );
			gi.trace( &tr, oldOrg, ent->mins, ent->maxs, ent->currentOrigin, ent->s.number, ent->clipmask, G2_RETURNONHIT, 10 );
			if ( VectorCompare( ent->s.pos.trDelta, vec3_origin ) )
			{
				//VectorCopy( ent->currentAngles, ent->s.apos.trBase );
				VectorClear( ent->s.apos.trDelta );
			}
			else
			{
				vec3_t	ang, fwdDir, rtDir;
				float	speed;
				
				ent->s.apos.trType = TR_INTERPOLATE;
				VectorSet( ang, 0, ent->s.apos.trBase[1], 0 );
				AngleVectors( ang, fwdDir, rtDir, NULL );
				speed = VectorLength( ent->s.pos.trDelta )*4;

				//HMM, this works along an axis-aligned dir, but not along diagonals
				//This is because when roll gets to 90, pitch becomes yaw, and vice-versa
				//Maybe need to just set the angles directly?
				ent->s.apos.trDelta[0] = DotProduct( fwdDir, ent->s.pos.trDelta );
				ent->s.apos.trDelta[1] = 0;//never spin!
				ent->s.apos.trDelta[2] = DotProduct( rtDir, ent->s.pos.trDelta );

				VectorNormalize( ent->s.apos.trDelta );
				VectorScale( ent->s.apos.trDelta, speed, ent->s.apos.trDelta );

				ent->s.apos.trTime = level.previousTime;
			}
		}
	}
	else
	{
		EvaluateTrajectory( &ent->s.pos, level.time, origin );
		// trace a line from the previous position to the current position,
		// ignoring interactions with the missile owner
		/*
		gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, 
			ent->owner ? ent->owner->s.number : ENTITYNUM_NONE, ent->clipmask, G2_RETURNONHIT, 10 );
		*/
		gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, 
			ent->owner ? ent->owner->s.number : ent->s.number, ent->clipmask, G2_COLLIDE, 10 );
		/*
		if ( !VectorCompare( ent->mins, vec3_origin ) || !VectorCompare( ent->maxs, vec3_origin ) )
		{//don't do ghoul trace if ent has size because g2 just ignores that anyway
			gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, 
				ent->owner ? ent->owner->s.number : ENTITYNUM_NONE, ent->clipmask, G2_NOCOLLIDE, 10 );
		}
		else
		//Now we always do ghoul trace, regardless of bbox size of missile, this is presuming that non-point ghoul traces will be possible...?
		{
			gi.trace( &tr, ent->currentOrigin, vec3_origin, vec3_origin, origin, 
				ent->owner ? ent->owner->s.number : ENTITYNUM_NONE, ent->clipmask, G2_RETURNONHIT, 10 );
		}
		*/
		/*
		if ( tr.fraction == 0.0f && tr.plane.normal[2] == 1.0f && origin[2] < ent->currentOrigin[2] )
		{
			if ( ent->s.pos.trType == TR_GRAVITY && !(ent->s.eFlags&EF_BOUNCE) && !(ent->s.eFlags&EF_BOUNCE_HALF) && ent->s.weapon == WP_THERMAL )//FIXME: EF_ROLLING
			{
				//FIXME: Needs to stop sometime!
				ent->s.pos.trType = TR_LINEAR;
				ent->s.pos.trDelta[2] = 0;
				EvaluateTrajectory( &ent->s.pos, level.time, origin );
				// trace a line from the previous position to the current position,
				// ignoring interactions with the missile owner
				gi.trace( &tr, ent->currentOrigin, ent->mins, ent->maxs, origin, 
					ent->owner ? ent->owner->s.number : ENTITYNUM_NONE, ent->clipmask | CONTENTS_GHOUL2 );
				if ( tr.fraction == 1.0f )
				{
					VectorCopy( tr.endpos, ent->s.pos.trBase );
					VectorScale( ent->s.pos.trDelta, 0.975f, ent->s.pos.trDelta );
					ent->s.pos.trTime = level.time;
				}
				ent->s.pos.trType = TR_GRAVITY;
			}
		}
		*/

		if ( tr.entityNum != ENTITYNUM_NONE && &g_entities[tr.entityNum] != NULL )
		{
			gentity_t *other = &g_entities[tr.entityNum];
			// check for hitting a lightsaber
			if ( other->contents & CONTENTS_LIGHTSABER )
			{//hit a lightsaber bbox
				if ( other->owner && other->owner->client && !other->owner->client->ps.saberInFlight && !InFront( ent->currentOrigin, other->owner->currentOrigin, other->owner->client->ps.viewangles, SABER_REFLECT_MISSILE_CONE ) )//other->owner->s.number == 0 &&
				{//Jedi cannot block shots from behind!
					//re-trace from here, ignoring the lightsaber
					gi.trace( &tr, tr.endpos, ent->mins, ent->maxs, origin, tr.entityNum, ent->clipmask, G2_RETURNONHIT, 10 );
				}
			}
		}

		VectorCopy( tr.endpos, ent->currentOrigin );
	}

	// get current angles
	VectorMA( ent->s.apos.trBase, (level.time - ent->s.apos.trTime) * 0.001, ent->s.apos.trDelta, ent->s.apos.trBase );

	//FIXME: Rolling things hitting G2 polys is weird
	///////////////////////////////////////////////////////
//?	if ( tr.fraction != 1 ) 
	{
	// did we hit or go near a Ghoul2 model?
//		qboolean hitModel = qfalse;
		for (int i=0; i < MAX_G2_COLLISIONS; i++)
		{
			if (tr.G2CollisionMap[i].mEntityNum == -1)
			{
				break;
			}

			CCollisionRecord &coll = tr.G2CollisionMap[i];
			gentity_t	*hitEnt = &g_entities[coll.mEntityNum];

/*	Sorry...this was just getting in the way....
#if _DEBUG
			vec3_t delta;
			VectorSubtract(origin, coll.mCollisionPosition, delta);
			VectorNormalize(delta);
			VectorScale(delta, 30, delta);

			if (coll.mFlags & G2_BACKFACE)
			{
				VectorAdd(delta, coll.mCollisionPosition, delta);
				G_DebugLine(coll.mCollisionPosition, delta, 10000, 0x00ff0000, qtrue);
			}
			else
			{
				VectorSubtract(coll.mCollisionPosition, delta, delta);
				G_DebugLine(coll.mCollisionPosition, delta, 10000, 0x0000ff00, qtrue);
			}

//loadsavecrash
//			VectorCopy(hitEnt->mins, hitEnt->s.mins);
//			VectorCopy(hitEnt->maxs, hitEnt->s.maxs);
#endif
*/

			// process collision records here...
			// make sure we only do this once, not for all the entrance wounds we might generate
			if ((coll.mFlags & G2_FRONTFACE)/* && !(hitModel)*/ && hitEnt->health)
			{
				// create a new surface using the details of what poly/surface/model we hit
//				int newSurface = gi.G2API_AddSurface(&hitEnt->ghoul2[coll.mModelIndex], coll.mSurfaceIndex, coll.mPolyIndex, coll.mBarycentricI, coll.mBarycentricJ, 10);
//				surfaceInfo_t	*newSuf = &hitEnt->ghoul2[coll.mModelIndex].mSlist[newSurface];
				// attach a bolt to this surface
//				int newBolt = gi.G2API_AddBoltSurfNum(&hitEnt->ghoul2[coll.mModelIndex], newSurface);
				// now attach an effect to this new bolt

//	Bolting on this effect just looks dumb and adds lots of unnecessary effects to the scene
//				
//				G_PlayEffect( G_EffectIndex( "blaster/smoke_bolton") , coll.mModelIndex, newBolt, hitEnt->s.number);
//
//

//				G_SetBoltSurfaceRemoval(coll.mEntityNum, coll.mModelIndex, newBolt, newSurface, 10000);
//				hitModel = qtrue;

				if (trHitLoc==HL_NONE)
				{
					G_GetHitLocFromSurfName( &g_entities[coll.mEntityNum], gi.G2API_GetSurfaceName( &g_entities[coll.mEntityNum].ghoul2[coll.mModelIndex], coll.mSurfaceIndex ), &trHitLoc, coll.mCollisionPosition, NULL, NULL, ent->methodOfDeath );
				}

				break; // NOTE: the way this whole section was working, it would only get inside of this IF once anyway, might as well break out now
			}
		}
	}
/////////////////////////////////////////////////////////

	if ( tr.startsolid ) 
	{
		tr.fraction = 0;
	}

	gi.linkentity( ent );

	if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
	{//stuck missiles should check some special stuff
		G_RunStuckMissile( ent );
		return;
	}

	// check think function
	G_RunThink( ent );

	if ( ent->s.eType != ET_MISSILE ) 
	{
		return;		// exploded
	}

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

	AddSightEvent( ent->owner, ent->currentOrigin, 512, AEL_DISCOVERED, 75 );//wakes them up when see a shot passes in front of them
	if ( !Q_irand( 0, 10 ) )
	{//not so often...
		if ( ent->splashDamage && ent->splashRadius )
		{//I'm an exploder, let people around me know danger is coming
			if ( ent->s.weapon == WP_TRIP_MINE )
			{//???
			}
			else 
			{
				if ( ent->s.weapon == WP_ROCKET_LAUNCHER && ent->e_ThinkFunc == thinkF_rocketThink )
				{//homing rocket- run like hell!
					AddSightEvent( ent->owner, ent->currentOrigin, ent->splashRadius, AEL_DANGER_GREAT, 50 );
				}
				else
				{
					AddSightEvent( ent->owner, ent->currentOrigin, ent->splashRadius, AEL_DANGER, 50 );
				}
				AddSoundEvent( ent->owner, ent->currentOrigin, ent->splashRadius, AEL_DANGER );
			}
		}
		else
		{//makes them run from near misses
			AddSightEvent( ent->owner, ent->currentOrigin, 48, AEL_DANGER, 50 );
		}
	}

	if ( tr.fraction == 1 ) 
	{
		return;
	}

	// never explode or bounce on sky
	if ( tr.surfaceFlags & SURF_NOIMPACT ) 
	{
		G_FreeEntity( ent );
		return;
	}

	G_MissileImpact( ent, &tr, trHitLoc );
}
コード例 #20
0
ファイル: g_missile.c プロジェクト: Mauii/Rend2
/*
================
G_RunMissile
================
*/
void G_RunMissile( gentity_t *ent ) {
    vec3_t		origin, groundSpot;
    trace_t		tr;
    int			passent;
    qboolean	isKnockedSaber = qfalse;

    if (ent->neverFree && ent->s.weapon == WP_SABER && (ent->flags & FL_BOUNCE_HALF))
    {
        isKnockedSaber = qtrue;
        ent->s.pos.trType = TR_GRAVITY;
    }

    // get current position
    BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

    // if this missile bounced off an invulnerability sphere
    if ( ent->target_ent ) {
        passent = ent->target_ent->s.number;
    }
    else {
        // ignore interactions with the missile owner
        if ( (ent->r.svFlags&SVF_OWNERNOTSHARED)
                && (ent->s.eFlags&EF_JETPACK_ACTIVE) )
        {   //A vehicle missile that should be solid to its owner
            //I don't care about hitting my owner
            passent = ent->s.number;
        }
        else
        {
            passent = ent->r.ownerNum;
        }
    }
    // trace a line from the previous position to the current position
    if (d_projectileGhoul2Collision.integer)
    {
        trap->Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask, qfalse, G2TRFLAG_DOGHOULTRACE|G2TRFLAG_GETSURFINDEX|G2TRFLAG_THICK|G2TRFLAG_HITCORPSES, g_g2TraceLod.integer );

        if (tr.fraction != 1.0 && tr.entityNum < ENTITYNUM_WORLD)
        {
            gentity_t *g2Hit = &g_entities[tr.entityNum];

            if (g2Hit->inuse && g2Hit->client && g2Hit->ghoul2)
            {   //since we used G2TRFLAG_GETSURFINDEX, tr.surfaceFlags will actually contain the index of the surface on the ghoul2 model we collided with.
                g2Hit->client->g2LastSurfaceHit = tr.surfaceFlags;
                g2Hit->client->g2LastSurfaceTime = level.time;
            }

            if (g2Hit->ghoul2)
            {
                tr.surfaceFlags = 0; //clear the surface flags after, since we actually care about them in here.
            }
        }
    }
    else
    {
        trap->Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask, qfalse, 0, 0 );
    }

    if ( tr.startsolid || tr.allsolid ) {
        // make sure the tr.entityNum is set to the entity we're stuck in
        trap->Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, passent, ent->clipmask, qfalse, 0, 0 );
        tr.fraction = 0;
    }
    else {
        VectorCopy( tr.endpos, ent->r.currentOrigin );
    }

    if (ent->passThroughNum && tr.entityNum == (ent->passThroughNum-1))
    {
        VectorCopy( origin, ent->r.currentOrigin );
        trap->LinkEntity( (sharedEntity_t *)ent );
        goto passthrough;
    }

    trap->LinkEntity( (sharedEntity_t *)ent );

    if (ent->s.weapon == G2_MODEL_PART && !ent->bounceCount)
    {
        vec3_t lowerOrg;
        trace_t trG;

        VectorCopy(ent->r.currentOrigin, lowerOrg);
        lowerOrg[2] -= 1;
        trap->Trace( &trG, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, lowerOrg, passent, ent->clipmask, qfalse, 0, 0 );

        VectorCopy(trG.endpos, groundSpot);

        if (!trG.startsolid && !trG.allsolid && trG.entityNum == ENTITYNUM_WORLD)
        {
            ent->s.groundEntityNum = trG.entityNum;
        }
        else
        {
            ent->s.groundEntityNum = ENTITYNUM_NONE;
        }
    }

    if ( tr.fraction != 1) {
        // never explode or bounce on sky
        if ( tr.surfaceFlags & SURF_NOIMPACT ) {
            // If grapple, reset owner
            if (ent->parent && ent->parent->client && ent->parent->client->hook == ent) {
                ent->parent->client->hook = NULL;
            }

            if ((ent->s.weapon == WP_SABER && ent->isSaberEntity) || isKnockedSaber)
            {
                G_RunThink( ent );
                return;
            }
            else if (ent->s.weapon != G2_MODEL_PART)
            {
                G_FreeEntity( ent );
                return;
            }
        }

#if 0 //will get stomped with missile impact event...
        if (ent->s.weapon > WP_NONE && ent->s.weapon < WP_NUM_WEAPONS &&
                (tr.entityNum < MAX_CLIENTS || g_entities[tr.entityNum].s.eType == ET_NPC))
        {   //player or NPC, try making a mark on him
            /*
            gentity_t *evEnt = G_TempEntity(ent->r.currentOrigin, EV_GHOUL2_MARK);

            evEnt->s.owner = tr.entityNum; //the entity the mark should be placed on
            evEnt->s.weapon = ent->s.weapon; //the weapon used (to determine mark type)
            VectorCopy(ent->r.currentOrigin, evEnt->s.origin); //the point of impact

            //origin2 gets the predicted trajectory-based position.
            BG_EvaluateTrajectory( &ent->s.pos, level.time, evEnt->s.origin2 );

            //If they are the same, there will be problems.
            if (VectorCompare(evEnt->s.origin, evEnt->s.origin2))
            {
            	evEnt->s.origin2[2] += 2; //whatever, at least it won't mess up.
            }
            */
            //ok, let's try adding it to the missile ent instead (tempents bad!)
            G_AddEvent(ent, EV_GHOUL2_MARK, 0);

            //copy current pos to s.origin, and current projected traj to origin2
            VectorCopy(ent->r.currentOrigin, ent->s.origin);
            BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin2 );

            //the index for whoever we are hitting
            ent->s.otherEntityNum = tr.entityNum;

            if (VectorCompare(ent->s.origin, ent->s.origin2))
            {
                ent->s.origin2[2] += 2.0f; //whatever, at least it won't mess up.
            }
        }
#else
        if (ent->s.weapon > WP_NONE && ent->s.weapon < WP_NUM_WEAPONS &&
                (tr.entityNum < MAX_CLIENTS || g_entities[tr.entityNum].s.eType == ET_NPC))
        {   //player or NPC, try making a mark on him
            //copy current pos to s.origin, and current projected traj to origin2
            VectorCopy(ent->r.currentOrigin, ent->s.origin);
            BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin2 );

            if (VectorCompare(ent->s.origin, ent->s.origin2))
            {
                ent->s.origin2[2] += 2.0f; //whatever, at least it won't mess up.
            }
        }
#endif

        G_MissileImpact( ent, &tr );

        if (tr.entityNum == ent->s.otherEntityNum)
        {   //if the impact event other and the trace ent match then it's ok to do the g2 mark
            ent->s.trickedentindex = 1;
        }

        if ( ent->s.eType != ET_MISSILE && ent->s.weapon != G2_MODEL_PART )
        {
            return;		// exploded
        }
    }

passthrough:
    if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
    {   //stuck missiles should check some special stuff
        G_RunStuckMissile( ent );
        return;
    }

    if (ent->s.weapon == G2_MODEL_PART)
    {
        if (ent->s.groundEntityNum == ENTITYNUM_WORLD)
        {
            ent->s.pos.trType = TR_LINEAR;
            VectorClear(ent->s.pos.trDelta);
            ent->s.pos.trTime = level.time;

            VectorCopy(groundSpot, ent->s.pos.trBase);
            VectorCopy(groundSpot, ent->r.currentOrigin);

            if (ent->s.apos.trType != TR_STATIONARY)
            {
                ent->s.apos.trType = TR_STATIONARY;
                ent->s.apos.trTime = level.time;

                ent->s.apos.trBase[ROLL] = 0;
                ent->s.apos.trBase[PITCH] = 0;
            }
        }
    }

    // check think function after bouncing
    G_RunThink( ent );
}
コード例 #21
0
ファイル: g_missile.cpp プロジェクト: bibendovsky/rtcw
/*
================
G_RunMissile

================
*/
void G_RunMissile( gentity_t *ent ) {
	vec3_t origin;
	trace_t tr;
	int impactDamage;

	// Ridah, make AI aware of this danger
	// DHM - Nerve :: Only in single player
	if ( g_gametype.integer == GT_SINGLE_PLAYER ) {
		AICast_CheckDangerousEntity( ent, DANGER_MISSILE, ent->splashRadius, 0.1, 0.99, qtrue );
	}

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

	if ( ( ent->clipmask & CONTENTS_BODY ) && ( ent->s.weapon == WP_DYNAMITE || ent->s.weapon == WP_ARTY
												|| ent->s.weapon == WP_GRENADE_LAUNCHER || ent->s.weapon == WP_GRENADE_PINEAPPLE ) ) {

		if ( !ent->s.pos.trDelta[0] && !ent->s.pos.trDelta[1] && !ent->s.pos.trDelta[2] ) {
			ent->clipmask &= ~CONTENTS_BODY;
		}
	}

	// 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->r.ownerNum, ent->clipmask );

	VectorCopy( tr.endpos, ent->r.currentOrigin );

	if ( tr.startsolid ) {
		tr.fraction = 0;
	}

	trap_LinkEntity( ent );

	if ( tr.fraction != 1 ) {
		// never explode or bounce on sky
		if  (   tr.surfaceFlags & SURF_NOIMPACT ) {
			// If grapple, reset owner
			if ( ent->parent && ent->parent->client && ent->parent->client->hook == ent ) {
				ent->parent->client->hook = NULL;
			}
			G_FreeEntity( ent );
			return;
		}

		if ( ent->s.weapon == WP_ROCKET_LAUNCHER || ent->s.weapon == WP_PANZERFAUST ) {
			impactDamage = 999; // goes through pretty much any func_explosives
		} else {
			impactDamage = 20;  // "grenade"/"dynamite"		// probably adjust this based on velocity

		}
		G_MissileImpact( ent, &tr, impactDamage );

		if ( ent->s.eType != ET_MISSILE ) {
// JPW NERVE
			if ( g_gametype.integer != GT_SINGLE_PLAYER ) {
				Ground_Shaker( ent->r.currentOrigin, ent->splashDamage * 4 );
			}
// jpw
			return;     // exploded
		}
	}

	// check think function after bouncing
	G_RunThink( ent );
}
コード例 #22
0
void G_RunFrame( int levelTime ) {
	int			i;
	gentity_t	*ent;
	int			msec;
	int			ents_inuse=0; // someone's gonna be pissed I put this here...
#if	AI_TIMERS
	AITime = 0;
	navTime = 0;
#endif//	AI_TIMERS
	
	level.framenum++;
	level.previousTime = level.time;
	level.time = levelTime;
	msec = level.time - level.previousTime;
	
	NAV_CheckCalcPaths();
	//ResetTeamCounters();
	
	AI_UpdateGroups();

	if ( d_altRoutes->integer )
	{
		navigator.CheckAllFailedEdges();
	}
	navigator.ClearCheckedNodes();

	//remember last waypoint, clear current one
//	for ( i = 0, ent = &g_entities[0]; i < globals.num_entities ; i++, ent++) 
	for ( i = 0; i < globals.num_entities ; i++) 
	{
//		if ( !ent->inuse )
//			continue;

		if(!PInUse(i))
			continue;
		
		ent = &g_entities[i];
	
		if ( ent->waypoint != WAYPOINT_NONE 
			&& ent->noWaypointTime < level.time )
		{
			ent->lastWaypoint = ent->waypoint;
			ent->waypoint = WAYPOINT_NONE;
		}
		if ( d_altRoutes->integer )
		{
			navigator.CheckFailedNodes( ent );
		}
	}

	//Look to clear out old events
	ClearPlayerAlertEvents();

	//Run the frame for all entities
//	for ( i = 0, ent = &g_entities[0]; i < globals.num_entities ; i++, ent++)
	for ( i = 0; i < globals.num_entities ; i++) 
	{
//		if ( !ent->inuse )
//			continue;

		if(!PInUse(i))
			continue;
		ents_inuse++;
		ent = &g_entities[i];

		// clear events that are too old
		if ( level.time - ent->eventTime > EVENT_VALID_MSEC ) {
			if ( ent->s.event ) {
				ent->s.event = 0;	// &= EV_EVENT_BITS;
				if ( ent->client ) {
					ent->client->ps.externalEvent = 0;
				}
			}
			if ( ent->freeAfterEvent ) {
				// tempEntities or dropped items completely go away after their event
				G_FreeEntity( ent );
				continue;
			} else if ( ent->unlinkAfterEvent ) {
				// items that will respawn will hide themselves after their pickup event
				ent->unlinkAfterEvent = qfalse;
				gi.unlinkentity( ent );
			}
		}

		// temporary entities don't think
		if ( ent->freeAfterEvent )
			continue;

		G_CheckTasksCompleted(ent);

		G_Roff( ent );

		if( !ent->client )
		{
			if ( !(ent->svFlags & SVF_SELF_ANIMATING) )
			{//FIXME: make sure this is done only for models with frames?
				//Or just flag as animating?
				if ( ent->s.eFlags & EF_ANIM_ONCE )
				{
					ent->s.frame++;
				}
				else if ( !(ent->s.eFlags & EF_ANIM_ALLFAST) )
				{
					G_Animate( ent );
				}
			}
		}
		G_CheckSpecialPersistentEvents( ent );

		if ( ent->s.eType == ET_MISSILE ) 
		{
			G_RunMissile( ent );
			continue;
		}

		if ( ent->s.eType == ET_ITEM ) 
		{
			G_RunItem( ent );
			continue;
		}

		if ( ent->s.eType == ET_MOVER ) 
		{
			if ( ent->model && Q_stricmp( "models/test/mikeg/tie_fighter.md3", ent->model ) == 0 )
			{
				TieFighterThink( ent );
			}
			G_RunMover( ent );
			continue;
		}

		//The player
		if ( i == 0 ) 
		{
			// decay batteries if the goggles are active
			if ( cg.zoomMode == 1 && ent->client->ps.batteryCharge > 0 )
			{
				ent->client->ps.batteryCharge--;
			}
			else if ( cg.zoomMode == 3 && ent->client->ps.batteryCharge > 0 )
			{
				ent->client->ps.batteryCharge -= 2;

				if ( ent->client->ps.batteryCharge < 0 )
				{
					ent->client->ps.batteryCharge = 0;
				}
			}

			G_CheckEndLevelTimers( ent );
			//Recalculate the nearest waypoint for the coming NPC updates
			NAV_FindPlayerWaypoint();

			if( ent->taskManager && !stop_icarus )
			{
				ent->taskManager->Update();
			}
			//dead
			if ( ent->health <= 0 )
			{
				if ( ent->client->ps.groundEntityNum != ENTITYNUM_NONE )
				{//on the ground
					pitch_roll_for_slope( ent, NULL );
				}
			}

			continue;	// players are ucmd driven
		}

		G_RunThink( ent );	// be aware that ent may be free after returning from here, at least one func frees them
		ClearNPCGlobals();			//	but these 2 funcs are ok
		//UpdateTeamCounters( ent );	//	   to call anyway on a freed ent.
	}

	// perform final fixups on the player
	ent = &g_entities[0];
	if ( ent->inuse ) 
	{
		ClientEndFrame( ent );
	}
	if( g_numEntities->integer )
	{
		gi.Printf( S_COLOR_WHITE"Number of Entities in use : %d\n", ents_inuse );
	}
	//DEBUG STUFF
	NAV_ShowDebugInfo();
	NPC_ShowDebugInfo();

	G_DynamicMusicUpdate();

#if	AI_TIMERS
	AITime -= navTime;
	if ( AITime > 20 )
	{
		gi.Printf( S_COLOR_RED"ERROR: total AI time: %d\n", AITime );
	}
	else if ( AITime > 10 )
	{
		gi.Printf( S_COLOR_YELLOW"WARNING: total AI time: %d\n", AITime );
	}
	else if ( AITime > 2 )
	{
		gi.Printf( S_COLOR_GREEN"total AI time: %d\n", AITime );
	}
	if ( navTime > 20 )
	{
		gi.Printf( S_COLOR_RED"ERROR: total nav time: %d\n", navTime );
	}
	else if ( navTime > 10 )
	{
		gi.Printf( S_COLOR_YELLOW"WARNING: total nav time: %d\n", navTime );
	}
	else if ( navTime > 2 )
	{
		gi.Printf( S_COLOR_GREEN"total nav time: %d\n", navTime );
	}
#endif//	AI_TIMERS

#ifndef FINAL_BUILD
	if ( delayedShutDown != 0 && delayedShutDown < level.time )
	{
		G_Error( "Game Errors. Scroll up the console to read them.\n" );
	}
#endif

#ifdef _DEBUG
	if(!(level.framenum&0xff))
	{
		ValidateInUseBits();
	}
#endif
}
コード例 #23
0
ファイル: g_missile.cpp プロジェクト: bibendovsky/rtcw
void G_RunFlamechunk( gentity_t *ent ) {
	vec3_t vel, add;
	vec3_t neworg;
	trace_t tr;
	float speed, dot;

	// Adust the current speed of the chunk
	if ( level.time - ent->timestamp > 50 ) {
		VectorCopy( ent->s.pos.trDelta, vel );
		speed = VectorNormalize( vel );
		speed -= ( 50.f / 1000.f ) * FLAME_FRICTION_PER_SEC;

		if ( speed < FLAME_MIN_SPEED ) {
			speed = FLAME_MIN_SPEED;
		}

		VectorScale( vel, speed, ent->s.pos.trDelta );
	} else {
		speed = FLAME_START_SPEED;
	}

	// Move the chunk
	VectorScale( ent->s.pos.trDelta, 50.f / 1000.f, add );
	VectorAdd( ent->r.currentOrigin, add, neworg );

	trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, neworg, ent->r.ownerNum, MASK_SHOT | MASK_WATER ); // JPW NERVE

	if ( tr.startsolid ) {
		VectorCopy( vec3_origin, ent->s.pos.trDelta );
	} else if ( tr.fraction != 1.0f && !( tr.surfaceFlags & SURF_NOIMPACT ) ) {
		VectorCopy( tr.endpos, ent->r.currentOrigin );

		dot = DotProduct( vel, tr.plane.normal );
		VectorMA( vel, -2 * dot, tr.plane.normal, vel );
		VectorNormalize( vel );
		speed *= 0.5 * ( 0.25 + 0.75 * ( ( dot + 1.0 ) * 0.5 ) );
		VectorScale( vel, speed, ent->s.pos.trDelta );
	} else {
		VectorCopy( neworg, ent->r.currentOrigin );
	}

	// Do damage to nearby entities, every 100ms
	if ( ent->flameQuotaTime <= level.time ) {
		ent->flameQuotaTime = level.time + 100;
		G_FlameDamage( ent );
	}

	// Show debugging bbox
	if ( g_debugBullets.integer > 3 ) {
		gentity_t *bboxEnt;
		float size = ent->speed / 2;
		vec3_t b1, b2;
		vec3_t temp;
		VectorSet( temp, -size, -size, -size );
		VectorCopy( ent->r.currentOrigin, b1 );
		VectorCopy( ent->r.currentOrigin, b2 );
		VectorAdd( b1, temp, b1 );
		VectorSet( temp, size, size, size );
		VectorAdd( b2, temp, b2 );
		bboxEnt = G_TempEntity( b1, EV_RAILTRAIL );
		VectorCopy( b2, bboxEnt->s.origin2 );
		bboxEnt->s.dmgFlags = 1;    // ("type")
	}

	// Adjust the size
	if ( ent->speed < FLAME_START_MAX_SIZE ) {
		ent->speed += 10.f;

		if ( ent->speed > FLAME_START_MAX_SIZE ) {
			ent->speed = FLAME_START_MAX_SIZE;
		}
	}

	// Remove after 2 seconds
	if ( level.time - ent->timestamp > ( FLAME_LIFETIME - 150 ) ) { // JPW NERVE increased to 350 from 250 to match visuals better
		G_FreeEntity( ent );
		return;
	}

	G_RunThink( ent );
}
コード例 #24
0
ファイル: g_missile.cpp プロジェクト: Arcadiaprime/japp
void G_RunMissile( gentity_t *ent ) {
	vector3		origin, groundSpot;
	trace_t		tr;
	int			passent;
	qboolean	isKnockedSaber = qfalse;

	if ( ent->neverFree && ent->s.weapon == WP_SABER && (ent->flags & FL_BOUNCE_HALF) ) {
		isKnockedSaber = qtrue;
		ent->s.pos.trType = TR_GRAVITY;
	}

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, &origin );

	// if this missile bounced off an invulnerability sphere
	if ( ent->target_ent ) {
		passent = ent->target_ent->s.number;
	}
	else {
		// ignore interactions with the missile owner
		if ( (ent->r.svFlags&SVF_OWNERNOTSHARED)
			&& (ent->s.eFlags&EF_JETPACK_ACTIVE) ) {//A vehicle missile that should be solid to its owner
			//I don't care about hitting my owner
			passent = ent->s.number;
		}
		else {
			passent = ent->r.ownerNum;
		}
	}
	// trace a line from the previous position to the current position
	if ( d_projectileGhoul2Collision.integer ) {
		trap->Trace( &tr, &ent->r.currentOrigin, &ent->r.mins, &ent->r.maxs, &origin, passent, ent->clipmask, qfalse, G2TRFLAG_DOGHOULTRACE | G2TRFLAG_GETSURFINDEX | G2TRFLAG_THICK | G2TRFLAG_HITCORPSES, g_g2TraceLod.integer );

		if ( tr.fraction != 1.0f && tr.entityNum < ENTITYNUM_WORLD ) {
			gentity_t *g2Hit = &g_entities[tr.entityNum];

			if ( g2Hit->inuse && g2Hit->client && g2Hit->ghoul2 ) { //since we used G2TRFLAG_GETSURFINDEX, tr.surfaceFlags will actually contain the index of the surface on the ghoul2 model we collided with.
				g2Hit->client->g2LastSurfaceHit = tr.surfaceFlags;
				g2Hit->client->g2LastSurfaceTime = level.time;
			}

			if ( g2Hit->ghoul2 ) {
				tr.surfaceFlags = 0; //clear the surface flags after, since we actually care about them in here.
			}

			//Raz: Portals!
			if ( g2Hit->s.eType == ET_SPECIAL && g2Hit->s.userInt1 ) {
				if ( g2Hit->touch ) {
					g2Hit->touch( g2Hit, ent, &tr );
				}
				JPLua::Entity_CallFunction( g2Hit, JPLua::JPLUA_ENTITY_TOUCH, (intptr_t)ent, (intptr_t)&tr );
				goto passthrough;
			}
		}
	}
	else {
		trap->Trace( &tr, &ent->r.currentOrigin, &ent->r.mins, &ent->r.maxs, &origin, passent, ent->clipmask, qfalse, 0, 0 );
	}

	if ( tr.startsolid || tr.allsolid ) {
		// make sure the tr.entityNum is set to the entity we're stuck in
		trap->Trace( &tr, &ent->r.currentOrigin, &ent->r.mins, &ent->r.maxs, &ent->r.currentOrigin, passent, ent->clipmask, qfalse, 0, 0 );
		tr.fraction = 0;
	}
	else {
		VectorCopy( &tr.endpos, &ent->r.currentOrigin );
	}

	if ( ent->passThroughNum && tr.entityNum == (ent->passThroughNum - 1) ) {
		VectorCopy( &origin, &ent->r.currentOrigin );
		trap->LinkEntity( (sharedEntity_t *)ent );
		goto passthrough;
	}

	trap->LinkEntity( (sharedEntity_t *)ent );

	if ( ent->s.weapon == G2_MODEL_PART && !ent->bounceCount ) {
		vector3 lowerOrg;
		trace_t trG;

		VectorCopy( &ent->r.currentOrigin, &lowerOrg );
		lowerOrg.z -= 1;
		trap->Trace( &trG, &ent->r.currentOrigin, &ent->r.mins, &ent->r.maxs, &lowerOrg, passent, ent->clipmask, qfalse, 0, 0 );

		VectorCopy( &trG.endpos, &groundSpot );

		if ( !trG.startsolid && !trG.allsolid && trG.entityNum == ENTITYNUM_WORLD ) {
			ent->s.groundEntityNum = trG.entityNum;
		}
		else {
			ent->s.groundEntityNum = ENTITYNUM_NONE;
		}
	}

	if ( ent->parent && ent->parent->client && ent->parent->client->hook && ent->parent->client->hook == ent
		&& (ent->parent->client->ps.duelInProgress
		|| BG_SaberInSpecial( ent->parent->client->ps.saberMove )
		|| !(japp_allowHook.integer & (1 << level.gametype))
		|| ent->parent->client->pers.adminData.isSlept
		|| g_entities[tr.entityNum].client) )
	{
		// not allowed to have hook out
		Weapon_HookFree( ent );
		return;
	}

	if ( tr.fraction != 1 ) {
		// never explode or bounce on sky
		if ( tr.surfaceFlags & SURF_NOIMPACT ) {
			// If grapple, reset owner
			//	if ( ent->parent && ent->parent->client && ent->parent->client->hook == ent )
			//		ent->parent->client->hook = NULL;
			if ( ent->parent && ent->parent->client && ent->parent->client->hook && ent->parent->client->hook == ent ) {
				Weapon_HookFree( ent->parent->client->hook );
			}

			if ( (ent->s.weapon == WP_SABER && ent->isSaberEntity) || isKnockedSaber ) {
				G_RunThink( ent );
				return;
			}
			else if ( ent->s.weapon != G2_MODEL_PART ) {
				G_FreeEntity( ent );
				return;
			}
		}

		if ( ent->s.weapon > WP_NONE && ent->s.weapon < WP_NUM_WEAPONS &&
			(tr.entityNum < MAX_CLIENTS || g_entities[tr.entityNum].s.eType == ET_NPC) ) { //player or NPC, try making a mark on him
			//copy current pos to s.origin, and current projected traj to origin2
			VectorCopy( &ent->r.currentOrigin, &ent->s.origin );
			BG_EvaluateTrajectory( &ent->s.pos, level.time, &ent->s.origin2 );

			if ( VectorCompare( &ent->s.origin, &ent->s.origin2 ) ) {
				ent->s.origin2.z += 2.0f; //whatever, at least it won't mess up.
			}
		}

		G_MissileImpact( ent, &tr );

		if ( tr.entityNum == ent->s.otherEntityNum ) {
			// if the impact event other and the trace ent match then it's ok to do the g2 mark
			ent->s.trickedEntIndex[0] = 1;
		}

		if ( ent->s.eType != ET_MISSILE && ent->s.weapon != G2_MODEL_PART ) {
			return;		// exploded
		}
	}

passthrough:
	if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags & EF_MISSILE_STICK) ) {
		// stuck missiles should check some special stuff
		G_RunStuckMissile( ent );
		return;
	}

	if ( ent->s.weapon == G2_MODEL_PART ) {
		if ( ent->s.groundEntityNum == ENTITYNUM_WORLD ) {
			ent->s.pos.trType = TR_LINEAR;
			VectorClear( &ent->s.pos.trDelta );
			ent->s.pos.trTime = level.time;

			VectorCopy( &groundSpot, &ent->s.pos.trBase );
			VectorCopy( &groundSpot, &ent->r.currentOrigin );

			if ( ent->s.apos.trType != TR_STATIONARY ) {
				ent->s.apos.trType = TR_STATIONARY;
				ent->s.apos.trTime = level.time;

				ent->s.apos.trBase.roll = 0;
				ent->s.apos.trBase.pitch = 0;
			}
		}
	}

	// check think function after bouncing
	G_RunThink( ent );
}
コード例 #25
0
ファイル: g_items.c プロジェクト: zturtleman/reaction
/*
================
G_RunItem

================
*/
void G_RunItem(gentity_t * ent)
{
	vec3_t origin;
	trace_t tr;
	int contents;
	int mask;

	// if its groundentity has been set to none, it may have been pushed off an edge
	if (ent->s.groundEntityNum == ENTITYNUM_NONE) {
		if (ent->s.pos.trType != TR_GRAVITY) {
			ent->s.pos.trType = TR_GRAVITY;
			ent->s.pos.trTime = level.time;
		}
	}
	if (ent->s.pos.trType == TR_STATIONARY) {
		// check think function
		G_RunThink(ent);
		return;
	}
	// get current position
	G_EvaluateTrajectory(&ent->s.pos, level.time, origin);

	// trace a line from the previous position to the current position
	if (ent->clipmask) {
		mask = ent->clipmask;
	} else {
		mask = MASK_PLAYERSOLID & ~CONTENTS_BODY;	//MASK_SOLID;
	}
	trap_Trace(&tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, ent->r.ownerNum, mask);

	VectorCopy(tr.endpos, ent->r.currentOrigin);

	if (tr.startsolid) {
		tr.fraction = 0;
	}

	if (ent->flags & FL_DROPPED_ITEM && VectorLength(ent->s.pos.trDelta) != 0 &&
	    (ent->item->giType == IT_WEAPON || ent->item->giType == IT_HOLDABLE)) {
		// calculate spin -- should be identical to cg.autoAngles
		//cg.autoAnglesFast[1] = ( cg.time & 1023 ) * 360 / 1024.0f;
		ent->s.angles[1] = (level.time & 1023) * 360 / 1024.0f;
	}

	trap_LinkEntity(ent);	// FIXME: avoid this for stationary?

	// check think function
	G_RunThink(ent);

	if (tr.fraction == 1) {
		return;
	}
	//Elder: debug
	//if (ent->item && ent->item->giType == IT_WEAPON) {
	//G_Printf("item velocity: %s\n", vtos(ent->s.pos.trDelta));
	//}

	// if it is in a nodrop volume, remove it
	contents = trap_PointContents(ent->r.currentOrigin, -1);
	if (contents & CONTENTS_NODROP) {
		if (ent->item && ent->item->giType == IT_TEAM) {
			Team_FreeEntity(ent);
		} else if (ent->item && ent->item->giType == IT_WEAPON) {
			//Elder: force-call the weaponthink function
			RQ3_DroppedWeaponThink(ent);
		} else if (ent->item && ent->item->giType == IT_HOLDABLE) {
			RQ3_DroppedItemThink(ent);
		} else {
			G_FreeEntity(ent);
		}
		return;
	}

	G_BounceItem(ent, &tr);
}
コード例 #26
0
ファイル: g_missile.c プロジェクト: Asvarox/Unvanquished
/*
================
G_RunMissile

================
*/
void G_RunMissile( gentity_t *ent )
{
	vec3_t   origin;
	trace_t  tr;
	int      passent;
	qboolean impact = qfalse;

	// get current position
	BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

	// ignore interactions with the missile owner
	passent = ent->r.ownerNum;

	// general trace to see if we hit anything at all
	trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs,
	            origin, passent, ent->clipmask );

	if ( tr.startsolid || tr.allsolid )
	{
		tr.fraction = 0.0f;
		VectorCopy( ent->r.currentOrigin, tr.endpos );
	}

	if ( tr.fraction < 1.0f )
	{
		if ( !ent->pointAgainstWorld || (tr.contents & CONTENTS_BODY) )
		{
			// We hit an entity or we don't care
			impact = qtrue;
		}
		else
		{
			trap_Trace( &tr, ent->r.currentOrigin, NULL, NULL, origin,
			            passent, ent->clipmask );

			if ( tr.fraction < 1.0f )
			{
				// Hit the world with point trace
				impact = qtrue;
			}
			else
			{
				if ( tr.contents & CONTENTS_BODY )
				{
					// Hit an entity
					impact = qtrue;
				}
				else
				{
					trap_Trace( &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs,
					            origin, passent, CONTENTS_BODY );

					if ( tr.fraction < 1.0f )
					{
						impact = qtrue;
					}
				}
			}
		}
	}

	VectorCopy( tr.endpos, ent->r.currentOrigin );

	if ( impact )
	{
		if ( tr.surfaceFlags & SURF_NOIMPACT )
		{
			// Never explode or bounce on sky
			G_FreeEntity( ent );
			return;
		}

		G_MissileImpact( ent, &tr );

		if ( ent->s.eType != ET_MISSILE )
		{
			return; // exploded
		}
	}

	ent->r.contents = CONTENTS_SOLID; //trick trap_LinkEntity into...
	trap_LinkEntity( ent );
	ent->r.contents = 0; //...encoding bbox information

	if ( ent->flightSplashDamage )
	{
		G_RadiusDamage( tr.endpos, ent->parent,
		                ent->flightSplashDamage * G_DoMissileTimePowerReduce( ent ), ent->splashRadius,
		                ent->parent, ent->splashMethodOfDeath );
	}

	// check think function after bouncing
	G_RunThink( ent );
}
コード例 #27
0
ファイル: g_missile.c プロジェクト: jwginge/ojpa
//[/RealTrace]
void G_RunMissile( gentity_t *ent ) {
    vec3_t		origin, groundSpot;
    trace_t		tr;
    int			passent;
    qboolean	isKnockedSaber = qfalse;

    if (ent->neverFree && ent->s.weapon == WP_SABER && (ent->flags & FL_BOUNCE_HALF))
    {
        isKnockedSaber = qtrue;
        //[SaberThrowSys]
        if(!(ent->s.eFlags & EF_MISSILE_STICK) )
        {   //only go into gravity mode if we're not stuck to something
            ent->s.pos.trType = TR_GRAVITY;
        }
        //[/SaberThrowSys]
    }

    // get current position
    BG_EvaluateTrajectory( &ent->s.pos, level.time, origin );

    // if this missile bounced off an invulnerability sphere
    if ( ent->target_ent ) {
        passent = ent->target_ent->s.number;
    }
    else {
        // ignore interactions with the missile owner
        if ( (ent->r.svFlags&SVF_OWNERNOTSHARED)
                && (ent->s.eFlags&EF_JETPACK_ACTIVE) )
        {   //A vehicle missile that should be solid to its owner
            //I don't care about hitting my owner
            passent = ent->s.number;
        }
        else
        {
            passent = ent->r.ownerNum;
        }
    }
    // trace a line from the previous position to the current position
    //[RealTrace]
    G_RealTrace( ent, &tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, origin, passent, ent->clipmask, -1, -1 );
    //[/RealTrace]

    if ( !tr.startsolid && !tr.allsolid )
        VectorCopy( tr.endpos, ent->r.currentOrigin );

    if (ent->passThroughNum && tr.entityNum == (ent->passThroughNum-1))
    {
        VectorCopy( origin, ent->r.currentOrigin );
        trap_LinkEntity( ent );
        goto passthrough;
    }

    trap_LinkEntity( ent );
    //racc - assign groundEntityNum for body parts.
    if (ent->s.weapon == G2_MODEL_PART && !ent->bounceCount)
    {
        vec3_t lowerOrg;
        trace_t trG;

        VectorCopy(ent->r.currentOrigin, lowerOrg);
        lowerOrg[2] -= 1;
        trap_Trace( &trG, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, lowerOrg, passent, ent->clipmask );

        VectorCopy(trG.endpos, groundSpot);

        if (!trG.startsolid && !trG.allsolid && trG.entityNum == ENTITYNUM_WORLD)
        {
            ent->s.groundEntityNum = trG.entityNum;
        }
        else
        {
            ent->s.groundEntityNum = ENTITYNUM_NONE;
        }
    }

    if ( tr.fraction != 1) {
        // never explode or bounce on sky
        if ( tr.surfaceFlags & SURF_NOIMPACT ) {
            // If grapple, reset owner
            if (ent->parent && ent->parent->client && ent->parent->client->hook == ent) {
                ent->parent->client->hook = NULL;
            }

            //racc - make dropped sabers think when they hit a non-impact surface.
            if ((ent->s.weapon == WP_SABER && ent->isSaberEntity) || isKnockedSaber)
            {
                G_RunThink( ent );
                return;
            }
            //just kill off other weapon shots when they hit a non-impact surface.
            else if (ent->s.weapon != G2_MODEL_PART)
            {
                G_FreeEntity( ent );
                return;
            }
        }
        if (ent->s.weapon > WP_NONE && ent->s.weapon < WP_NUM_WEAPONS &&
                (tr.entityNum < MAX_CLIENTS || g_entities[tr.entityNum].s.eType == ET_NPC))
        {   //player or NPC, try making a mark on him
            //copy current pos to s.origin, and current projected traj to origin2
            VectorCopy(ent->r.currentOrigin, ent->s.origin);
            BG_EvaluateTrajectory( &ent->s.pos, level.time, ent->s.origin2 );

            if (VectorCompare(ent->s.origin, ent->s.origin2))
            {   //racc - don't allow the current origin/predicted origin be the same.
                ent->s.origin2[2] += 2.0f; //whatever, at least it won't mess up.
            }
        }

        //[DodgeSys]
        //changed G_MissileImpact to qboolean so that dodges will cause passthru behavor.
        if(!G_MissileImpact( ent, &tr ))
        {   //target dodged the damage.
            VectorCopy( origin, ent->r.currentOrigin );
            trap_LinkEntity( ent );
            return;
        }
        //G_MissileImpact( ent, &tr );
        //[/DodgeSys]

        if (tr.entityNum == ent->s.otherEntityNum)
        {   //if the impact event other and the trace ent match then it's ok to do the g2 mark
            ent->s.trickedentindex = 1;
        }

        if ( ent->s.eType != ET_MISSILE && ent->s.weapon != G2_MODEL_PART )
        {
            return;		// exploded
        }
    }

passthrough:
    if ( ent->s.pos.trType == TR_STATIONARY && (ent->s.eFlags&EF_MISSILE_STICK) )
    {   //stuck missiles should check some special stuff
        G_RunStuckMissile( ent );
        return;
    }

    if (ent->s.weapon == G2_MODEL_PART)
    {
        if (ent->s.groundEntityNum == ENTITYNUM_WORLD)
        {
            ent->s.pos.trType = TR_LINEAR;
            VectorClear(ent->s.pos.trDelta);
            ent->s.pos.trTime = level.time;

            VectorCopy(groundSpot, ent->s.pos.trBase);
            VectorCopy(groundSpot, ent->r.currentOrigin);

            if (ent->s.apos.trType != TR_STATIONARY)
            {
                ent->s.apos.trType = TR_STATIONARY;
                ent->s.apos.trTime = level.time;

                ent->s.apos.trBase[ROLL] = 0;
                ent->s.apos.trBase[PITCH] = 0;
            }
        }
    }

    if(ent->damageDecreaseTime && ent->damageDecreaseTime <= level.time)
    {
        ent->damage-=4;
        ent->damageDecreaseTime = level.time + 300;
    }

    // check think function after bouncing
    G_RunThink( ent );
}