Esempio n. 1
0
/*
==============
AICast_QueryThink
==============
*/
void AICast_QueryThink( cast_state_t *cs ) {
	gentity_t *ent;
	qboolean visible;
	cast_state_t *ocs;
	vec3_t vec;

	ent = &g_entities[cs->entityNum];
	ocs = AICast_GetCastState( cs->bs->enemy );

	// never crouch while in this state (by choice anyway)
	cs->bs->attackcrouch_time = 0;

	// look at where we last (thought we) saw them
	VectorSubtract( cs->vislist[cs->bs->enemy].visible_pos, cs->bs->origin, vec );
	VectorNormalize( vec );
	vectoangles( vec, cs->bs->ideal_viewangles );

	// are they visible now?
	visible = AICast_VisibleFromPos( cs->bs->origin, cs->entityNum, g_entities[cs->bs->enemy].r.currentOrigin, cs->bs->enemy, qfalse );

	// make sure we dont process the sighting of this enemy by going into query mode again, without them being visible again after we leave here
	cs->vislist[cs->bs->enemy].flags &= ~AIVIS_PROCESS_SIGHTING;

	// look towards where we last saw them
	AICast_AimAtEnemy( cs );

	// if visible and alert time has expired, go POSTAL
	if ( ( cs->queryAlertSightTime < 0 ) || ( ( cs->queryAlertSightTime < level.time ) && visible ) ) {
		if ( !cs->queryAlertSightTime ) {
			// set the "short reaction" condition
			BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SHORT_REACTION, qtrue, qfalse );
		}
		AICast_StateChange( cs, AISTATE_COMBAT );
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SHORT_REACTION, qfalse, qfalse );
		AIFunc_BattleStart( cs );
		return;
	}

	// if they've fired since the start of the query mode, go POSTAL
	if ( ocs->lastWeaponFired > cs->queryStartTime ) {
		// set the "short reaction" condition
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SHORT_REACTION, qtrue, qfalse );
		AICast_StateChange( cs, AISTATE_COMBAT );
		BG_UpdateConditionValue( cs->entityNum, ANIM_COND_SHORT_REACTION, qfalse, qfalse );
		AIFunc_BattleStart( cs );
		return;
	}

	// if not visible, then kill the Lock On timer
	if ( ( cs->queryAlertSightTime > 0 ) && !visible ) {
		cs->queryAlertSightTime = 0;
	}

	// if the query has expired, go back to relaxed
	if ( !ent->client->ps.legsTimer ) {
		AICast_StateChange( cs, AISTATE_RELAXED );
	}
}
Esempio n. 2
0
/*
==============
AICast_CheckVisibility
==============
*/
qboolean AICast_CheckVisibility( gentity_t *srcent, gentity_t *destent ) {
	vec3_t dir, entangles, middle, eye, viewangles;
	cast_state_t        *cs, *ocs;
	float fov, dist;
	int viewer, ent;
	cast_visibility_t   *vis;
	orientation_t       or;

	if ( destent->flags & FL_NOTARGET ) {
		return qfalse;
	}
	//
	viewer = srcent->s.number;
	ent = destent->s.number;
	//
	cs = AICast_GetCastState( viewer );
	ocs = AICast_GetCastState( ent );
	//
	vis = &cs->vislist[ent];
	//
	// if the destent is the client, and they have just loaded a savegame, ignore them temporarily
	if ( !destent->aiCharacter && level.lastLoadTime && ( level.lastLoadTime > level.time - 2000 ) && !vis->visible_timestamp ) {
		return qfalse;
	}
	// if we heard them
	/*
	if (	(vis->lastcheck_timestamp) &&
			(ocs->lastWeaponFired) &&
			(ocs->lastWeaponFired >= vis->lastcheck_timestamp) &&
			(AICast_GetWeaponSoundRange( ocs->lastWeaponFiredWeaponNum ) > Distance( srcent->r.currentOrigin, ocs->lastWeaponFiredPos ))) {
		return qtrue;
	}
	*/
	//
	// set the FOV
	fov = cs->attributes[FOV] * aiStateFovScales[cs->aiState];
	if ( !fov ) { // assume it's a player, give them a generic fov
		fov = 180;
	}
	if ( cs->aiFlags & AIFL_ZOOMING ) {
		fov *= 0.8;
	} else {
		if ( cs->lastEnemy >= 0 ) {   // they've already been in a fight, so give them a very large fov
			if ( fov < 270 ) {
				fov = 270;
			}
		}
	}
	// RF, if they were visible last check, then give us a full FOV, since we are aware of them
	if ( cs->aiState >= AISTATE_ALERT && vis->visible_timestamp == vis->lastcheck_timestamp ) {
		fov = 360;
	}
	//calculate middle of bounding box
	VectorAdd( destent->r.mins, destent->r.maxs, middle );
	VectorScale( middle, 0.5, middle );
	VectorAdd( destent->client->ps.origin, middle, middle );
	// calculate eye position
	if ( ( level.lastLoadTime < level.time - 4000 ) && ( srcent->r.svFlags & SVF_CASTAI ) ) {
		if ( clientHeadTagTimes[srcent->s.number] == level.time ) {
			// use the actual direction the head is facing
			vectoangles( clientHeadTags[srcent->s.number].axis[0], viewangles );
			// and the actual position of the head
			VectorCopy( clientHeadTags[srcent->s.number].origin, eye );
		} else if ( trap_GetTag( srcent->s.number, "tag_head", &or ) ) {
			// use the actual direction the head is facing
			vectoangles( or.axis[0], viewangles );
			// and the actual position of the head
			VectorCopy( or.origin, eye );
			VectorMA( eye, 12, or.axis[2], eye );
			// save orientation data
			memcpy( &clientHeadTags[srcent->s.number], &or, sizeof( orientation_t ) );
			clientHeadTagTimes[srcent->s.number] = level.time;
		} else {
			VectorCopy( srcent->client->ps.origin, eye );
			eye[2] += srcent->client->ps.viewheight;
			VectorCopy( srcent->client->ps.viewangles, viewangles );
			// save orientation data (so we dont keep checking for a tag when it doesn't exist)
			VectorCopy( eye, clientHeadTags[srcent->s.number].origin );
			AnglesToAxis( viewangles, clientHeadTags[srcent->s.number].axis );
			clientHeadTagTimes[srcent->s.number] = level.time;
		}
	} else {
		VectorCopy( srcent->client->ps.origin, eye );
		eye[2] += srcent->client->ps.viewheight;
		VectorCopy( srcent->client->ps.viewangles, viewangles );
	}
	//check if entity is within field of vision
	VectorSubtract( middle, eye, dir );
	vectoangles( dir, entangles );
	//
	dist = VectorLength( dir );
	//
	// alertness is visible range
	if ( cs->bs && dist > cs->attributes[ALERTNESS] ) {
		return qfalse;
	}
	// check FOV
	if ( !AICast_InFieldOfVision( viewangles, fov, entangles ) ) {
		return qfalse;
	}
	//
	if ( !AICast_VisibleFromPos( srcent->client->ps.origin, srcent->s.number, destent->client->ps.origin, destent->s.number, qtrue ) ) {
		return qfalse;
	}
	//
	return qtrue;
}
Esempio n. 3
0
/*
==============
AICast_CheckVisibility
==============
*/
qboolean AICast_CheckVisibility( gentity_t *srcent, gentity_t *destent ) {
	vec3_t dir, entangles, middle, eye, viewangles;
	cast_state_t        *cs;
	float fov, dist;
	int viewer, ent;
	orientation_t       or;

	if ( destent->flags & FL_NOTARGET ) {
		return qfalse;
	}

	viewer = srcent->s.number;
	ent = destent->s.number;
	//
	cs = AICast_GetCastState( viewer );
	AICast_GetCastState( ent );

	// set the FOV
	fov = cs->attributes[FOV] * aiStateFovScales[cs->aiState];
	if ( !fov ) { // assume it's a player, give them a generic fov
		fov = 180;
	}
	if ( cs->aiFlags & AIFL_ZOOMING ) {
		fov *= 0.8;
	}
	//calculate middle of bounding box
	VectorAdd( destent->r.mins, destent->r.maxs, middle );
	VectorScale( middle, 0.5, middle );
	VectorAdd( destent->client->ps.origin, middle, middle );
	// calculate eye position
	if ( srcent->r.svFlags & SVF_CASTAI ) {
		if ( trap_GetTag( srcent->s.number, "tag_head", &or ) ) {
			// use the actual direction the head is facing
			vectoangles( or.axis[0], viewangles );
			// and the actual position of the head
			VectorCopy( or.origin, eye );
		} else {
			VectorCopy( srcent->client->ps.origin, eye );
			eye[2] += srcent->client->ps.viewheight;
			VectorCopy( srcent->client->ps.viewangles, viewangles );
		}
	} else {
		VectorCopy( srcent->client->ps.origin, eye );
		eye[2] += srcent->client->ps.viewheight;
		VectorCopy( srcent->client->ps.viewangles, viewangles );
	}
	//check if entity is within field of vision
	VectorSubtract( middle, eye, dir );
	vectoangles( dir, entangles );
	//
	dist = VectorLength( dir );
	//
	// alertness is visible range
	if ( cs->bs && dist > cs->attributes[ALERTNESS] ) {
		return qfalse;
	}
	// check FOV
	if ( !AICast_InFieldOfVision( viewangles, fov, entangles ) ) {
		return qfalse;
	}
	//
	if ( !AICast_VisibleFromPos( srcent->client->ps.origin, srcent->s.number, destent->client->ps.origin, destent->s.number, qtrue ) ) {
		return qfalse;
	}
	//
	return qtrue;
}