示例#1
0
/*
* G_RunEntities
* treat each object in turn
* even the world and clients get a chance to think
*/
static void G_RunEntities( void )
{
	edict_t	*ent;

	for( ent = &game.edicts[0]; ENTNUM( ent ) < game.numentities; ent++ )
	{
		if( !ent->r.inuse )
			continue;
		if( ISEVENTENTITY( &ent->s ) )
			continue; // events do not think

		level.current_entity = ent;

		// backup oldstate ( for world frame ).
		ent->olds = ent->s;

		// if the ground entity moved, make sure we are still on it
		if( !ent->r.client )
		{
			if( ( ent->groundentity ) && ( ent->groundentity->linkcount != ent->groundentity_linkcount ) )
				G_CheckGround( ent );
		}

		G_RunEntity( ent );

		if( ent->takedamage )
			ent->s.effects |= EF_TAKEDAMAGE;
		else
			ent->s.effects &= ~EF_TAKEDAMAGE;
	}
}
示例#2
0
文件: g_phys.cpp 项目: Picmip/qfusion
/*
* G_BoxSlideMove
* calls GS_SlideMove for edict_t and triggers touch functions of touched objects
*/
int G_BoxSlideMove( edict_t *ent, int contentmask, float slideBounce, float friction ) {
	int i;
	move_t entMove;
	int blockedmask = 0;
	float oldVelocity;
	memset( &entMove, 0, sizeof( move_t ) );

	oldVelocity = VectorLength( ent->velocity );
	if( !ent->groundentity ) {
		SV_AddGravity( ent );
	} else { // horizontal friction
		G_AddGroundFriction( ent, friction );
	}

	entMove.numClipPlanes = 0;
	entMove.numtouch = 0;

	if( oldVelocity > 0 ) {
		VectorCopy( ent->s.origin, entMove.origin );
		VectorCopy( ent->velocity, entMove.velocity );
		VectorCopy( ent->r.mins, entMove.mins );
		VectorCopy( ent->r.maxs, entMove.maxs );

		entMove.remainingTime = FRAMETIME;

		VectorSet( entMove.gravityDir, 0, 0, -1 );
		entMove.slideBounce = slideBounce;
		entMove.groundEntity = ( ent->groundentity == NULL ) ? -1 : ENTNUM( ent->groundentity );

		entMove.passent = ENTNUM( ent );
		entMove.contentmask = contentmask;

		blockedmask = GS_SlideMove( &entMove );

		// update with the new values
		VectorCopy( entMove.origin, ent->s.origin );
		VectorCopy( entMove.velocity, ent->velocity );
		ent->groundentity = ( entMove.groundEntity == -1 ) ? NULL : &game.edicts[entMove.groundEntity];

		GClip_LinkEntity( ent );
	}

	// call touches
	if( contentmask != 0 ) {
		edict_t *other;
		GClip_TouchTriggers( ent );

		// touch other objects
		for( i = 0; i < entMove.numtouch; i++ ) {
			other = &game.edicts[entMove.touchents[i]];
			if( other->r.svflags & SVF_PROJECTILE ) {
				continue;
			}

			G_CallTouch( other, ent, NULL, 0 );

			// if self touch function, fire up touch and if freed stop
			G_CallTouch( ent, other, NULL, 0 );
			if( !ent->r.inuse ) { // it may have been freed by the touch function
				break;
			}
		}
	}

	if( ent->r.inuse ) {
		G_CheckGround( ent );
		if( ent->groundentity && VectorLength( ent->velocity ) <= 1 && oldVelocity > 1 ) {
			VectorClear( ent->velocity );
			VectorClear( ent->avelocity );
			G_CallStop( ent );
		}
	}

	return blockedmask;
}
示例#3
0
文件: g_phys.cpp 项目: Picmip/qfusion
/*
* SV_Physics_Toss
*
* Toss, bounce, and fly movement.  When onground, do nothing.
*
* FIXME: This function needs a serious rewrite
*/
static void SV_Physics_Toss( edict_t *ent ) {
	trace_t trace;
	vec3_t move;
	float backoff;
	edict_t *slave;
	bool wasinwater;
	bool isinwater;
	vec3_t old_origin;
	float oldSpeed;

	// if not a team captain, so movement will be handled elsewhere
	if( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	// refresh the ground entity
	if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
		if( ent->velocity[2] > 0.1f ) {
			ent->groundentity = NULL;
		}
	}

	if( ent->groundentity && ent->groundentity != world && !ent->groundentity->r.inuse ) {
		ent->groundentity = NULL;
	}

	oldSpeed = VectorLength( ent->velocity );

	if( ent->groundentity ) {
		if( !oldSpeed ) {
			return;
		}

		if( ent->movetype == MOVETYPE_TOSS ) {
			if( ent->velocity[2] >= 8 ) {
				ent->groundentity = NULL;
			} else {
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
				return;
			}
		}
	}

	VectorCopy( ent->s.origin, old_origin );

	if( ent->accel != 0 ) {
		if( ent->accel < 0 && VectorLength( ent->velocity ) < 50 ) {
			VectorClear( ent->velocity );
		} else {
			vec3_t acceldir;
			VectorNormalize2( ent->velocity, acceldir );
			VectorScale( acceldir, ent->accel * FRAMETIME, acceldir );
			VectorAdd( ent->velocity, acceldir, ent->velocity );
		}
	}

	SV_CheckVelocity( ent );

	// add gravity
	if( ent->movetype != MOVETYPE_FLY && !ent->groundentity ) {
		SV_AddGravity( ent );
	}

	// move angles
	VectorMA( ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles );

	// move origin
	VectorScale( ent->velocity, FRAMETIME, move );

	trace = SV_PushEntity( ent, move );
	if( !ent->r.inuse ) {
		return;
	}

	if( trace.fraction < 1.0f ) {
		if( ent->movetype == MOVETYPE_BOUNCE ) {
			backoff = 1.5;
		} else if( ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
			backoff = 1.5;
		} else {
			backoff = 1;
		}

		GS_ClipVelocity( ent->velocity, trace.plane.normal, ent->velocity, backoff );

		// stop if on ground

		if( ent->movetype == MOVETYPE_BOUNCE || ent->movetype == MOVETYPE_BOUNCEGRENADE ) {
			// stop dead on allsolid

			// LA: hopefully will fix grenades bouncing down slopes
			// method taken from Darkplaces sourcecode
			if( trace.allsolid ||
				( ISWALKABLEPLANE( &trace.plane ) &&
				  fabs( DotProduct( trace.plane.normal, ent->velocity ) ) < 40
				)
				) {
				ent->groundentity = &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		} else {
			// in movetype_toss things stop dead when touching ground
#if 0
			G_CheckGround( ent );

			if( ent->groundentity ) {
#else

			// walkable or trapped inside solid brush
			if( trace.allsolid || ISWALKABLEPLANE( &trace.plane ) ) {
				ent->groundentity = trace.ent < 0 ? world : &game.edicts[trace.ent];
				ent->groundentity_linkcount = ent->groundentity->linkcount;
#endif
				VectorClear( ent->velocity );
				VectorClear( ent->avelocity );
				G_CallStop( ent );
			}
		}
	}

	// check for water transition
	wasinwater = ( ent->watertype & MASK_WATER ) ? true : false;
	ent->watertype = G_PointContents( ent->s.origin );
	isinwater = ent->watertype & MASK_WATER ? true : false;

	// never allow items in CONTENTS_NODROP
	if( ent->item && ( ent->watertype & CONTENTS_NODROP ) ) {
		G_FreeEdict( ent );
		return;
	}

	if( isinwater ) {
		ent->waterlevel = 1;
	} else {
		ent->waterlevel = 0;
	}

	if( !wasinwater && isinwater ) {
		G_PositionedSound( old_origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( wasinwater && !isinwater ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}

	// move teamslaves
	for( slave = ent->teamchain; slave; slave = slave->teamchain ) {
		VectorCopy( ent->s.origin, slave->s.origin );
		GClip_LinkEntity( slave );
	}
}

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

void SV_Physics_LinearProjectile( edict_t *ent ) {
	vec3_t start, end;
	int mask;
	float startFlyTime, endFlyTime;
	trace_t trace;
	int old_waterLevel;

	// if not a team captain movement will be handled elsewhere
	if( ent->flags & FL_TEAMSLAVE ) {
		return;
	}

	old_waterLevel = ent->waterlevel;

	mask = ( ent->r.clipmask ) ? ent->r.clipmask : MASK_SOLID;

	// find it's current position given the starting timeStamp
	startFlyTime = (float)( max( game.prevServerTime - ent->s.linearMovementTimeStamp, 0 ) ) * 0.001f;
	endFlyTime = (float)( game.serverTime - ent->s.linearMovementTimeStamp ) * 0.001f;

	VectorMA( ent->s.linearMovementBegin, startFlyTime, ent->s.linearMovementVelocity, start );
	VectorMA( ent->s.linearMovementBegin, endFlyTime, ent->s.linearMovementVelocity, end );

	G_Trace4D( &trace, start, ent->r.mins, ent->r.maxs, end, ent, mask, ent->timeDelta );
	VectorCopy( trace.endpos, ent->s.origin );
	GClip_LinkEntity( ent );
	SV_Impact( ent, &trace );

	if( !ent->r.inuse ) { // the projectile may be freed if touched something
		return;
	}

	// update some data required for the transmission
	//VectorCopy( ent->velocity, ent->s.linearMovementVelocity );

	GClip_TouchTriggers( ent );
	ent->groundentity = NULL; // projectiles never have ground entity
	ent->waterlevel = ( G_PointContents4D( ent->s.origin, ent->timeDelta ) & MASK_WATER ) ? true : false;

	if( !old_waterLevel && ent->waterlevel ) {
		G_PositionedSound( start, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	} else if( old_waterLevel && !ent->waterlevel ) {
		G_PositionedSound( ent->s.origin, CHAN_AUTO, trap_SoundIndex( S_HIT_WATER ), ATTN_IDLE );
	}
}