//	Return true if object A is expected to collide with object B within time duration
//	For purposes of this check, the first object moves from current location to predicted
//	location.  The second object is assumed to be where it will be at time duration, NOT
//	where it currently is.
//	radius_scale is used to control the precision of the check.
//		If 0.0, then use polygon models to perform check, slow and accurate
//		If !0.0, then use as a scale on the radius of the objects.  1.0 is Descent style
//			collisions.  Larger values can be used to be sloppy about the collisions which
//			is useful if a moving object wants to prevent a collision.
int objects_will_collide(object *A, object *B, float duration, float radius_scale)
{
	object	A_future;
	vec3d	hitpos;


	A_future = *A;
	vm_vec_scale_add2(&A_future.pos, &A->phys_info.vel, duration);

	if (radius_scale == 0.0f) {
		return ship_check_collision_fast(B, &A_future, &hitpos );
	} else {
		float		size_A, size_B, dist, r;
		vec3d	nearest_point;

		size_A = A->radius * radius_scale;
		size_B = B->radius * radius_scale;

		//	If A is moving, check along vector.
		if (A->phys_info.speed != 0.0f) {
			r = find_nearest_point_on_line(&nearest_point, &A->pos, &A_future.pos, &B->pos);
			if (r < 0) {
				nearest_point = A->pos;
			} else if (r > 1) {
				nearest_point = A_future.pos;
			}
			dist = vm_vec_dist_quick(&B->pos, &nearest_point);
			return (dist < size_A + size_B);
		} else {
			return vm_vec_dist_quick(&B->pos, &A->pos) < size_A + size_B;
		}
	}
}
示例#2
0
// ----------------------------------------------------------------------------------------------
void apply_light(fix obj_intensity, int obj_seg, vms_vector *obj_pos, int n_render_vertices, short *render_vertices, int objnum)
{
	int	vv;

	if (obj_intensity) {
		fix	obji_64 = obj_intensity*64;

		// for pretty dim sources, only process vertices in object's own segment.
		if (obji_64 <= F1_0*8) {
			short *vp = Segments[obj_seg].verts;

			for (vv=0; vv<MAX_VERTICES_PER_SEGMENT; vv++) {
				int			vertnum;
				vms_vector	*vertpos;
				fix			dist;

				vertnum = vp[vv];
				vertpos = &Vertices[vertnum];
				dist = vm_vec_dist_quick(obj_pos, vertpos);
				dist = fixmul(dist/4, dist/4);
				if (dist < obji_64) {
					if (dist < MIN_LIGHT_DIST)
						dist = MIN_LIGHT_DIST;

					Dynamic_light[vertnum] += fixdiv(obj_intensity, dist);
				}
			}
		} else {
			for (vv=FrameCount&1; vv<n_render_vertices; vv+=2) {
				int			vertnum;
				vms_vector	*vertpos;
				fix			dist;
				int			apply_light;

				vertnum = render_vertices[vv];
				vertpos = &Vertices[vertnum];
				dist = vm_vec_dist_quick(obj_pos, vertpos);
				apply_light = 0;

				if (dist < obji_64) {

					if (dist < MIN_LIGHT_DIST)
						dist = MIN_LIGHT_DIST;

					Dynamic_light[vertnum] += fixdiv(obj_intensity, dist);
				}
			}
		}
	}
}
static float get_current_alpha(vec3d *pos)
{
	float dist;
	float alpha;

	const float inner_radius = 30.0f;
	const float magic_num = 2.75f;

	// determine what alpha to draw this bitmap with
	// higher alpha the closer the bitmap gets to the eye
	dist = vm_vec_dist_quick(&Eye_position, pos);

	// if the point is inside the inner radius, alpha is based on distance to the player's eye,
	// becoming more transparent as it gets close
	if (dist <= inner_radius) {
		// alpha per meter between the magic # and the inner radius
		alpha = 0.99999f / (inner_radius - magic_num);

		// above value times the # of meters away we are
		alpha *= (dist - magic_num);
		return (alpha < 0.05f) ? 0.0f : alpha;
	}

	return 0.99999f;
}
unsigned int DistanceTo(int nav)
{
	if (nav >= MAX_NAVPOINTS || nav < 0)
		return 0xFFFFFFFF;

	return (uint)vm_vec_dist_quick(&Player_obj->pos, Navs[nav].GetPosition());
}
//	Return true if objp will collide with some large object.
//	Don't check for an object this ship is docked to.
int collide_predict_large_ship(object *objp, float distance)
{
	object	*objp2;
	vec3d	cur_pos, goal_pos;
	ship_info	*sip;

	sip = &Ship_info[Ships[objp->instance].ship_info_index];

	cur_pos = objp->pos;

	vm_vec_scale_add(&goal_pos, &cur_pos, &objp->orient.vec.fvec, distance);

	for ( objp2 = GET_FIRST(&obj_used_list); objp2 != END_OF_LIST(&obj_used_list); objp2 = GET_NEXT(objp2) ) {
		if ((objp != objp2) && (objp2->type == OBJ_SHIP)) {
			if (Ship_info[Ships[objp2->instance].ship_info_index].flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) {
				if (dock_check_find_docked_object(objp, objp2))
					continue;

				if (cpls_aux(&goal_pos, objp2, objp))
					return 1;
			}
		} else if (!(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) && (objp2->type == OBJ_ASTEROID)) {
			if (vm_vec_dist_quick(&objp2->pos, &objp->pos) < (distance + objp2->radius)*2.5f) {
				vec3d	pos, delvec;
				int		count;
				float		d1;

				d1 = 2.5f * distance + objp2->radius;
				count = (int) (d1/(objp2->radius + objp->radius));	//	Scale up distance, else looks like there would be a collision.
				pos = cur_pos;
				vm_vec_normalized_dir(&delvec, &goal_pos, &cur_pos);
				vm_vec_scale(&delvec, d1/count);

				for (; count>0; count--) {
					if (vm_vec_dist_quick(&pos, &objp2->pos) < objp->radius + objp2->radius)
						return 1;
					vm_vec_add2(&pos, &delvec);
				}
			}
		}
	}

	return 0;
}
/**
 * Render jump node
 *
 * @param pos		World position
 * @param view_pos	Viewer's world position, can be NULL
 */
void CJumpNode::RenderDEPRECATED(vec3d *pos, vec3d *view_pos)
{
	Assert(pos != NULL);
    // Assert(view_pos != NULL); - view_pos can be NULL
	
	if(m_flags & JN_HIDE)
		return;
	
	if(m_modelnum < 0)
		return;
	
	matrix node_orient = IDENTITY_MATRIX;
	
	int mr_flags = MR_NO_LIGHTING;
	if(!(m_flags & JN_SHOW_POLYS)) {
		mr_flags |= MR_NO_CULL | MR_NO_POLYS | MR_SHOW_OUTLINE_PRESET;
	}
	
	if ( Fred_running ) {
		gr_set_color_fast(&m_display_color);		
		model_render_DEPRECATED(m_modelnum, &node_orient, pos, mr_flags );
	} else {
		if (m_flags & JN_USE_DISPLAY_COLOR) {
			gr_set_color_fast(&m_display_color);
		}
		else if ( view_pos != NULL) {
			int alpha_index = HUD_color_alpha;
			
			// generate alpha index based on distance to jump this
			float dist;
			
			dist = vm_vec_dist_quick(view_pos, pos);
			
			// linearly interpolate alpha.  At 1000m or less, full intensity.  At 10000m or more 1/2 intensity.
			if ( dist < 1000 ) {
				alpha_index = HUD_COLOR_ALPHA_USER_MAX - 2;
			} else if ( dist > 10000 ) {
				alpha_index = HUD_COLOR_ALPHA_USER_MIN;
			} else {
				alpha_index = fl2i( HUD_COLOR_ALPHA_USER_MAX - 2 + (dist-1000) * (HUD_COLOR_ALPHA_USER_MIN-HUD_COLOR_ALPHA_USER_MAX-2) / (9000) + 0.5f);
				if ( alpha_index < HUD_COLOR_ALPHA_USER_MIN ) {
					alpha_index = HUD_COLOR_ALPHA_USER_MIN;
				}
			}
			
			gr_set_color_fast(&HUD_color_defaults[alpha_index]);
			
		} else {
			gr_set_color(HUD_color_red, HUD_color_green, HUD_color_blue);
		}
		
		model_render_DEPRECATED(m_modelnum, &node_orient, pos, mr_flags );
	}
	
}
示例#7
0
/**
 * Render debris
 */
void debris_render(object * obj)
{
	int			i, num, swapped;
	polymodel	*pm;
	debris		*db;


	swapped = -1;
	pm = NULL;	
	num = obj->instance;

	Assert(num >= 0 && num < MAX_DEBRIS_PIECES);
	db = &Debris[num];

	Assert(db->flags & DEBRIS_USED);

	texture_info *tbase = NULL;
	
	model_clear_instance( db->model_num );
	
	// Swap in a different texture depending on the species
	if (db->species >= 0)
	{
		pm = model_get( db->model_num );

		//WMC - Someday, we should have glowing debris.
		if ( pm != NULL && (pm->n_textures == 1) ) {
			tbase = &pm->maps[0].textures[TM_BASE_TYPE];
			swapped = tbase->GetTexture();
			tbase->SetTexture(Species_info[db->species].debris_texture.bitmap_id);
		}
	}

	// Only render electrical arcs if within 500m of the eye (for a 10m piece)
	if ( vm_vec_dist_quick( &obj->pos, &Eye_position ) < obj->radius*50.0f )	{
		for (i=0; i<MAX_DEBRIS_ARCS; i++ )	{
			if ( timestamp_valid( db->arc_timestamp[i] ) )	{
				model_add_arc( db->model_num, db->submodel_num, &db->arc_pts[i][0], &db->arc_pts[i][1], MARC_TYPE_NORMAL );
			}
		}
	}

	if ( db->is_hull )	{
		MONITOR_INC(NumHullDebrisRend,1);
		submodel_render( db->model_num, db->submodel_num, &obj->orient, &obj->pos );
	} else {
		MONITOR_INC(NumSmallDebrisRend,1);
		submodel_render( db->model_num, db->submodel_num, &obj->orient, &obj->pos, MR_NO_LIGHTING );
	}

	if (tbase != NULL && (swapped!=-1) && pm)	{
		tbase->SetTexture(swapped);
	}
}
示例#8
0
int asteroid_editor::query_modified()
{
	int i;

	for (i=0; i<1 /*MAX_ASTEROID_FIELDS*/; i++) {
		if (a_field[i].num_initial_asteroids != Asteroid_field.num_initial_asteroids)
			return 1;
		if (vm_vec_dist_quick(&a_field[i].vel, &Asteroid_field.vel) == 0.0f)
			return 1;
		if (a_field[i].min_bound.x != Asteroid_field.min_bound.x)
			return 1;
		if (a_field[i].min_bound.y != Asteroid_field.min_bound.y)
			return 1;
		if (a_field[i].min_bound.z != Asteroid_field.min_bound.z)
			return 1;
		if (a_field[i].max_bound.x != Asteroid_field.max_bound.x)
			return 1;
		if (a_field[i].max_bound.y != Asteroid_field.max_bound.y)
			return 1;
		if (a_field[i].max_bound.z != Asteroid_field.max_bound.z)
			return 1;


		if (a_field[i].has_inner_bound != Asteroid_field.has_inner_bound)
			return 1;

		if (a_field[i].field_type != Asteroid_field.field_type)
			return 1;

		if (a_field[i].has_inner_bound) {
			if (a_field[i].inner_max_bound.x != Asteroid_field.inner_max_bound.x)
				return 1;

			if (a_field[i].inner_max_bound.y != Asteroid_field.inner_max_bound.y)
				return 1;

			if (a_field[i].inner_max_bound.z != Asteroid_field.inner_max_bound.z)
				return 1;

			if (a_field[i].inner_min_bound.x != Asteroid_field.inner_min_bound.x)
				return 1;

			if (a_field[i].inner_min_bound.y != Asteroid_field.inner_min_bound.y)
				return 1;

			if (a_field[i].inner_min_bound.z != Asteroid_field.inner_min_bound.z)
				return 1;
		}

	}

	return 0;
}
// Creates a bunch of particles. You pass a structure
// rather than a bunch of parameters.
void particle_emit( particle_emitter *pe, int type, int optional_data, float range )
{
	int i, n;

	if ( !Particles_enabled )
		return;

	int n1, n2;

	// Account for detail
	int percent = get_percent(Detail.num_particles);

	//Particle rendering drops out too soon.  Seems to be around 150 m.  Is it detail level controllable?  I'd like it to be 500-1000 
	float min_dist = 125.0f;
	float dist = vm_vec_dist_quick( &pe->pos, &Eye_position ) / range;
	if ( dist > min_dist )	{
		percent = fl2i( i2fl(percent)*min_dist / dist );
		if ( percent < 1 ) {
			return;
		}
	}
	//mprintf(( "Dist = %.1f, percent = %d%%\n", dist, percent ));

	n1 = (pe->num_low*percent)/100;
	n2 = (pe->num_high*percent)/100;

	// How many to emit?
	n = (rand() % (n2-n1+1)) + n1;
	
	if ( n < 1 ) return;


	for (i=0; i<n; i++ )	{
		// Create a particle
		vec3d tmp_vel;
		vec3d normal;				// What normal the particle emit arond

		float radius = (( pe->max_rad - pe->min_rad ) * frand()) + pe->min_rad;

		float speed = (( pe->max_vel - pe->min_vel ) * frand()) + pe->min_vel;

		float life = (( pe->max_life - pe->min_life ) * frand()) + pe->min_life;

		normal.xyz.x = pe->normal.xyz.x + (frand()*2.0f - 1.0f)*pe->normal_variance;
		normal.xyz.y = pe->normal.xyz.y + (frand()*2.0f - 1.0f)*pe->normal_variance;
		normal.xyz.z = pe->normal.xyz.z + (frand()*2.0f - 1.0f)*pe->normal_variance;
		vm_vec_normalize_safe( &normal );
		vm_vec_scale_add( &tmp_vel, &pe->vel, &normal, speed );

		particle_create( &pe->pos, &tmp_vel, life, radius, type, optional_data );
	}
}
//	Return true if the vector from *start_pos to *end_pos is within objp->radius*radius_scale of *objp
int vector_object_collision(vec3d *start_pos, vec3d *end_pos, object *objp, float radius_scale)
{
	float		dist, r;
	vec3d	nearest_point;

	r = find_nearest_point_on_line(&nearest_point, start_pos, end_pos, &objp->pos);
	if ((r >= 0.0f) && (r <= 1.0f)) {
		dist = vm_vec_dist_quick(&objp->pos, &nearest_point);

		return (dist < objp->radius * radius_scale);
	} else
		return 0;
}
示例#11
0
//	Return true if object A is expected to collide with object B within time duration
//	For purposes of this check, the first object moves from current location to predicted
//	location.  The second object is assumed to be where it will be at time duration, NOT
//	where it currently is.
//	radius_scale is used to control the precision of the check.
//		If 0.0, then use polygon models to perform check, slow and accurate
//		If !0.0, then use as a scale on the radius of the objects.  1.0 is Descent style
//			collisions.  Larger values can be used to be sloppy about the collisions which
//			is useful if a moving object wants to prevent a collision.
int objects_will_collide(object *A, object *B, float duration, float radius_scale)
{
	vec3d	prev_pos;
	vec3d	hitpos;
	int ret;


	prev_pos = A->pos;
	vm_vec_scale_add2(&A->pos, &A->phys_info.vel, duration);

	if (radius_scale == 0.0f) {
		ret = ship_check_collision_fast(B, A, &hitpos);
	} else {
		float		size_A, size_B, dist, r;
		vec3d	nearest_point;

		size_A = A->radius * radius_scale;
		size_B = B->radius * radius_scale;

		//	If A is moving, check along vector.
		if (A->phys_info.speed != 0.0f) {
			r = find_nearest_point_on_line(&nearest_point, &prev_pos, &A->pos, &B->pos);
			if (r < 0) {
				nearest_point = prev_pos;
			} else if (r > 1) {
				nearest_point = A->pos;
			}
			dist = vm_vec_dist_quick(&B->pos, &nearest_point);
			ret = (dist < size_A + size_B);
		} else {
			ret = vm_vec_dist_quick(&B->pos, &prev_pos) < size_A + size_B;
		}
	}

	// Reset the position to the previous value
	A->pos = prev_pos;

	return ret;
}
示例#12
0
/**
 * If debris piece *db is far away from all players, make it go away very soon.
 * In single player game, delete if MAX_DEBRIS_DIST from player.
 * In multiplayer game, delete if MAX_DEBRIS_DIST from all players.
 */
void maybe_delete_debris(debris *db)
{
	object	*objp;

	if (timestamp_elapsed(db->next_distance_check) && timestamp_elapsed(db->must_survive_until)) {
		if (!(Game_mode & GM_MULTIPLAYER)) {		//	In single player game, just check against player.
			if (vm_vec_dist_quick(&Player_obj->pos, &Objects[db->objnum].pos) > MAX_DEBRIS_DIST)
				db->lifeleft = 0.1f;
			else
				db->next_distance_check = timestamp(DEBRIS_DISTANCE_CHECK_TIME);
		} else {
			for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) {
				if (objp->flags[Object::Object_Flags::Player_ship]) {
					if (vm_vec_dist_quick(&objp->pos, &Objects[db->objnum].pos) < MAX_DEBRIS_DIST) {
						db->next_distance_check = timestamp(DEBRIS_DISTANCE_CHECK_TIME);
						return;
					}
				}
			}
			db->lifeleft = 0.1f;
		}
	}
}
示例#13
0
// ------------------------------------------------------------------------------------
// shockwave_render()
//
//	Draw the shockwave identified by handle
//
//	input:	objp	=>		pointer to shockwave object
//
void shockwave_render(object *objp)
{
	shockwave		*sw;
	shockwave_info	*si;
	vertex			p;

	Assert(objp->type == OBJ_SHOCKWAVE);
	Assert(objp->instance >= 0 && objp->instance < MAX_SHOCKWAVES);

	sw = &Shockwaves[objp->instance];
	si = &Shockwave_info[sw->shockwave_info_index];

	if( (sw->delay_stamp != -1) && !timestamp_elapsed(sw->delay_stamp)){
		return;
	}

	if ( (sw->current_bitmap < 0) && (sw->model_id < 0) )
		return;

	// turn off fogging
	if(The_mission.flags & MISSION_FLAG_FULLNEB){
		gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
	}

	if (sw->model_id > -1) {
		float model_Interp_scale_xyz = sw->radius / 50.0f;

		model_set_warp_globals( model_Interp_scale_xyz, model_Interp_scale_xyz, model_Interp_scale_xyz, -1, 1.0f - (sw->radius/sw->outer_radius) );
		
		float dist = vm_vec_dist_quick( &sw->pos, &Eye_position );

		model_set_detail_level((int)(dist / (sw->radius * 10.0f)));
		model_render( sw->model_id, &Objects[sw->objnum].orient, &sw->pos, MR_NO_LIGHTING | MR_NO_FOGGING | MR_NORMAL | MR_CENTER_ALPHA | MR_NO_CULL, sw->objnum);

		model_set_warp_globals();
	}else{
		if (!Cmdline_nohtl) {
			g3_transfer_vertex(&p, &sw->pos);
		} else {
			g3_rotate_vertex(&p, &sw->pos);
		}
	
		gr_set_bitmap(sw->current_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.3f );
		g3_draw_rotated_bitmap(&p, fl_radian(sw->rot_angles.p), sw->radius, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT);	
	}
}
示例#14
0
文件: wall.c 项目: gameplayer22/d2x-1
void bng_process_segment(object *objp, fix damage, segment *segp, int depth, byte *visited)
{
	int	i, sidenum;

	if (depth > MAX_BLAST_GLASS_DEPTH)
		return;

	depth++;

	for (sidenum=0; sidenum<MAX_SIDES_PER_SEGMENT; sidenum++) {
		int			tm;
		fix			dist;
		vms_vector	pnt;

		//	Process only walls which have glass.
		if ((tm=segp->sides[sidenum].tmap_num2) != 0) {
			int	ec, db;

			tm &= 0x3fff;			//tm without flags

			if ((((ec=TmapInfo[tm].eclip_num)!=-1) && ((db=Effects[ec].dest_bm_num)!=-1 && !(Effects[ec].flags&EF_ONE_SHOT))) ||	(ec==-1 && (TmapInfo[tm].destroyed!=-1))) {
				compute_center_point_on_side(&pnt, segp, sidenum);
				dist = vm_vec_dist_quick(&pnt, &objp->pos);
				if (dist < damage/2) {
					dist = find_connected_distance(&pnt, segp-Segments, &objp->pos, objp->segnum, MAX_BLAST_GLASS_DEPTH, WID_RENDPAST_FLAG);
					if ((dist > 0) && (dist < damage/2))
						check_effect_blowup(segp, sidenum, &pnt, &Objects[objp->ctype.laser_info.parent_num], 1);
				}
			}
		}
	}

	for (i=0; i<MAX_SIDES_PER_SEGMENT; i++) {
		int	segnum = segp->children[i];

		if (segnum != -1) {
			if (!visited[segnum]) {
				if (WALL_IS_DOORWAY(segp, i) & WID_FLY_FLAG) {
					visited[segnum] = 1;
					bng_process_segment(objp, damage, &Segments[segnum], depth, visited);
				}
			}
		}
	}
}
示例#15
0
// Determine is ship is visible by team
// Goober5000 - now accounts for primitive sensors
int ship_is_visible_by_team(object *target, ship *viewer)
{
	Assert(target);
	Assert(viewer);
	Assert(target->type == OBJ_SHIP);

	// not visible if viewer has primitive sensors
	if (viewer->flags[Ship::Ship_Flags::Primitive_sensors])
		return 0;

	// not visible if out of range
	if ((Hud_max_targeting_range > 0) && (vm_vec_dist_quick(&target->pos, &Objects[viewer->objnum].pos) > Hud_max_targeting_range))
		return 0;

	// now evaluate this the old way
	int ship_num = target->instance;
	int team = viewer->team;

	return (int)Ship_visibility_by_team[team][ship_num];
}
示例#16
0
void shockwave_render(object *objp, draw_list *scene)
{
	shockwave		*sw;
	vertex			p;

	Assert(objp->type == OBJ_SHOCKWAVE);
	Assert(objp->instance >= 0 && objp->instance < MAX_SHOCKWAVES);

	sw = &Shockwaves[objp->instance];

	if( (sw->delay_stamp != -1) && !timestamp_elapsed(sw->delay_stamp)){
		return;
	}

	if ( (sw->current_bitmap < 0) && (sw->model_id < 0) )
		return;

	if (sw->model_id > -1) {
		vec3d scale;
		scale.xyz.x = scale.xyz.y = scale.xyz.z = sw->radius / 50.0f;

		model_render_params render_info;

		render_info.set_warp_params(-1, 1.0f - (sw->radius/sw->outer_radius), scale);

		float dist = vm_vec_dist_quick( &sw->pos, &Eye_position );

		render_info.set_detail_level_lock((int)(dist / (sw->radius * 10.0f)));
		render_info.set_flags(MR_NO_LIGHTING | MR_NO_FOGGING | MR_NORMAL | MR_CENTER_ALPHA | MR_NO_CULL | MR_NO_BATCH);
		render_info.set_object_number(sw->objnum);

		model_render_queue( &render_info, scene, sw->model_id, &Objects[sw->objnum].orient, &sw->pos);

		if ( Cmdline_fb_explosions ) {
			g3_transfer_vertex(&p, &sw->pos);

			distortion_add_bitmap_rotated(
				Shockwave_info[1].bitmap_id+shockwave_get_framenum(objp->instance, 94), 
				TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD | TMAP_FLAG_DISTORTION, 
				&p, 
				fl_radians(sw->rot_angles.p), 
				sw->radius,
				((sw->time_elapsed/sw->total_time)>0.9f)?(1.0f-(sw->time_elapsed/sw->total_time))*10.0f:1.0f
				);
		}
	} else {
		if (!Cmdline_nohtl) {
			g3_transfer_vertex(&p, &sw->pos);
		} else {
			g3_rotate_vertex(&p, &sw->pos);
		}

		if ( Cmdline_fb_explosions ) {
			distortion_add_bitmap_rotated(
				sw->current_bitmap, 
				TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD | TMAP_FLAG_DISTORTION, 
				&p, 
				fl_radians(sw->rot_angles.p), 
				sw->radius,
				((sw->time_elapsed/sw->total_time)>0.9f)?(1.0f-(sw->time_elapsed/sw->total_time))*10.0f:1.0f
			);
		}

		batch_add_bitmap_rotated(
			sw->current_bitmap, 
			TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD,
			&p, 
			fl_radians(sw->rot_angles.p), 
			sw->radius
		);
	}
}
示例#17
0
/**
 * Draw the shockwave identified by handle
 *
 * @param objp	pointer to shockwave object
 */
void shockwave_render_DEPRECATED(object *objp)
{
	shockwave		*sw;
	vertex			p;

	Assert(objp->type == OBJ_SHOCKWAVE);
	Assert(objp->instance >= 0 && objp->instance < MAX_SHOCKWAVES);

    memset(&p, 0, sizeof(p));
	sw = &Shockwaves[objp->instance];

	if( (sw->delay_stamp != -1) && !timestamp_elapsed(sw->delay_stamp)){
		return;
	}

	if ( (sw->current_bitmap < 0) && (sw->model_id < 0) )
		return;

	// turn off fogging
	if(The_mission.flags & MISSION_FLAG_FULLNEB){
		gr_fog_set(GR_FOGMODE_NONE, 0, 0, 0);
	}

	if (sw->model_id > -1) {
		float model_Interp_scale_xyz = sw->radius / 50.0f;

		model_set_warp_globals( model_Interp_scale_xyz, model_Interp_scale_xyz, model_Interp_scale_xyz, -1, 1.0f - (sw->radius/sw->outer_radius) );
		
		float dist = vm_vec_dist_quick( &sw->pos, &Eye_position );

		model_set_detail_level((int)(dist / (sw->radius * 10.0f)));
		model_render_DEPRECATED( sw->model_id, &Objects[sw->objnum].orient, &sw->pos, MR_DEPRECATED_NO_LIGHTING | MR_DEPRECATED_NO_FOGGING | MR_DEPRECATED_NORMAL | MR_DEPRECATED_CENTER_ALPHA | MR_DEPRECATED_NO_CULL, sw->objnum);

		model_set_warp_globals();
		if(Cmdline_fb_explosions)
		{
			g3_transfer_vertex(&p, &sw->pos);
				
			distortion_add_bitmap_rotated(
				Shockwave_info[1].bitmap_id+shockwave_get_framenum(objp->instance, 94), 
				TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD | TMAP_FLAG_DISTORTION, 
				&p, 
				fl_radians(sw->rot_angles.p), 
				sw->radius,
				((sw->time_elapsed/sw->total_time)>0.9f)?(1.0f-(sw->time_elapsed/sw->total_time))*10.0f:1.0f
			);
		}
	}else{
		if (!Cmdline_nohtl) {
			g3_transfer_vertex(&p, &sw->pos);
		} else {
			g3_rotate_vertex(&p, &sw->pos);
		}
		if(Cmdline_fb_explosions)
		{
			distortion_add_bitmap_rotated(
				sw->current_bitmap, 
				TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD | TMAP_FLAG_DISTORTION, 
				&p, 
				fl_radians(sw->rot_angles.p), 
				sw->radius,
				((sw->time_elapsed/sw->total_time)>0.9f)?(1.0f-(sw->time_elapsed/sw->total_time))*10.0f:1.0f
			);
		}
		batch_add_bitmap_rotated(
			sw->current_bitmap, 
			TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_SOFT_QUAD,
			&p, 
			fl_radians(sw->rot_angles.p), 
			sw->radius
		);
	}
}
示例#18
0
do_endlevel_frame()
{
	static fix timer;
	vms_vector save_last_pos;
	static fix explosion_wait1=0;
	static fix explosion_wait2=0;
	static fix bank_rate;
	static fix ext_expl_halflife;

	save_last_pos = ConsoleObject->last_pos;	//don't let move code change this
	object_move_all();
	ConsoleObject->last_pos = save_last_pos;

	if (ext_expl_playing) {

		external_explosion.lifeleft -= FrameTime;
		do_explosion_sequence(&external_explosion);

		if (external_explosion.lifeleft < ext_expl_halflife)
			mine_destroyed = 1;

		if (external_explosion.flags & OF_SHOULD_BE_DEAD)
			ext_expl_playing = 0;
	}

	if (cur_fly_speed != desired_fly_speed) {
		fix delta = desired_fly_speed - cur_fly_speed;
		fix frame_accel = fixmul(FrameTime,FLY_ACCEL);

		if (abs(delta) < frame_accel)
			cur_fly_speed = desired_fly_speed;
		else
			if (delta > 0)
				cur_fly_speed += frame_accel;
			else
				cur_fly_speed -= frame_accel;
	}

	//do big explosions
	if (!outside_mine) {

		if (Endlevel_sequence==EL_OUTSIDE) {
			vms_vector tvec;

			vm_vec_sub(&tvec,&ConsoleObject->pos,&mine_side_exit_point);

			if (vm_vec_dot(&tvec,&mine_exit_orient.fvec) > 0) {
				object *tobj;

				outside_mine = 1;

				tobj = object_create_explosion(exit_segnum,&mine_side_exit_point,i2f(50),VCLIP_BIG_PLAYER_EXPLOSION);

				if (tobj) {
					external_explosion = *tobj;

					tobj->flags |= OF_SHOULD_BE_DEAD;

					flash_scale = 0;	//kill lights in mine

					ext_expl_halflife = tobj->lifeleft;

					ext_expl_playing = 1;
				}
	
				digi_link_sound_to_pos( SOUND_BIG_ENDLEVEL_EXPLOSION, exit_segnum, 0, &mine_side_exit_point, 0, i2f(3)/4 );
			}
		}

		//do explosions chasing player
		if ((explosion_wait1-=FrameTime) < 0) {
			vms_vector tpnt;
			int segnum;
			object *expl;
			static int sound_count;

			vm_vec_scale_add(&tpnt,&ConsoleObject->pos,&ConsoleObject->orient.fvec,-ConsoleObject->size*5);
			vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.rvec,(rand()-RAND_MAX/2)*15);
			vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(rand()-RAND_MAX/2)*15);

			segnum = find_point_seg(&tpnt,ConsoleObject->segnum);

			if (segnum != -1) {
				expl = object_create_explosion(segnum,&tpnt,i2f(20),VCLIP_BIG_PLAYER_EXPLOSION);
				if (rand()<10000 || ++sound_count==7) {		//pseudo-random
					digi_link_sound_to_pos( SOUND_TUNNEL_EXPLOSION, segnum, 0, &tpnt, 0, F1_0 );
					sound_count=0;
				}
			}

			explosion_wait1 = 0x2000 + rand()/4;

		}
	}

	//do little explosions on walls
	if (Endlevel_sequence >= EL_FLYTHROUGH && Endlevel_sequence < EL_OUTSIDE)
		if ((explosion_wait2-=FrameTime) < 0) {
			vms_vector tpnt;
			fvi_query fq;
			fvi_info hit_data;

			//create little explosion on wall

			vm_vec_copy_scale(&tpnt,&ConsoleObject->orient.rvec,(rand()-RAND_MAX/2)*100);
			vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.uvec,(rand()-RAND_MAX/2)*100);
			vm_vec_add2(&tpnt,&ConsoleObject->pos);

			if (Endlevel_sequence == EL_FLYTHROUGH)
				vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,rand()*200);
			else
				vm_vec_scale_add2(&tpnt,&ConsoleObject->orient.fvec,rand()*60);

			//find hit point on wall

			fq.p0 = &ConsoleObject->pos;
			fq.p1 = &tpnt;
			fq.startseg = ConsoleObject->segnum;
			fq.rad = 0;
			fq.thisobjnum = 0;
			fq.ignore_obj_list = NULL;
			fq.flags = 0;

			find_vector_intersection(&fq,&hit_data);

			if (hit_data.hit_type==HIT_WALL && hit_data.hit_seg!=-1)
				object_create_explosion(hit_data.hit_seg,&hit_data.hit_pnt,i2f(3)+rand()*6,VCLIP_SMALL_EXPLOSION);

			explosion_wait2 = (0xa00 + rand()/8)/2;
		}

	switch (Endlevel_sequence) {

		case EL_OFF: return;

		case EL_FLYTHROUGH: {

			do_endlevel_flythrough(0);

			if (ConsoleObject->segnum == transition_segnum) {
				int objnum;

				Endlevel_sequence = EL_LOOKBACK;

				objnum = obj_create(OBJ_CAMERA, 0, 
					ConsoleObject->segnum,&ConsoleObject->pos,&ConsoleObject->orient,0,
					CT_NONE,MT_NONE,RT_NONE);

				if (objnum == -1) {				//can't get object, so abort
					mprintf((1, "Can't get object for endlevel sequence.  Aborting endlevel sequence.\n"));
					stop_endlevel_sequence();
					return;
				}

				Viewer = endlevel_camera = &Objects[objnum];

				select_cockpit(CM_LETTERBOX);

				fly_objects[1] = fly_objects[0];
				fly_objects[1].obj = endlevel_camera;
				fly_objects[1].speed = (5*cur_fly_speed)/4;
				fly_objects[1].offset_frac = 0x4000;

				vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,i2f(7));

				timer=0x20000;
			}

			break;
		}


		case EL_LOOKBACK: {

			do_endlevel_flythrough(0);
			do_endlevel_flythrough(1);

			if (timer>0) {

				timer -= FrameTime;

				if (timer < 0)		//reduce speed
					fly_objects[1].speed = fly_objects[0].speed;
			}

			if (endlevel_camera->segnum == exit_segnum) {
				vms_angvec cam_angles,exit_seg_angles;

				Endlevel_sequence = EL_OUTSIDE;

				timer = i2f(2);

				vm_vec_negate(&endlevel_camera->orient.fvec);
				vm_vec_negate(&endlevel_camera->orient.rvec);

				vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient);
				vm_extract_angles_matrix(&exit_seg_angles,&mine_exit_orient);
				bank_rate = (-exit_seg_angles.b - cam_angles.b)/2;

				ConsoleObject->control_type = endlevel_camera->control_type = CT_NONE;

				//_MARK_("Starting outside");//Commented out by KRB

#ifdef SLEW_ON
 slew_obj = endlevel_camera;
#endif
			}
				
			break;
		}

		case EL_OUTSIDE: {
			#ifndef SLEW_ON
			vms_angvec cam_angles;
			#endif

			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));
#ifndef SLEW_ON
			vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,-2*cur_fly_speed));
			vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.uvec,fixmul(FrameTime,-cur_fly_speed/10));

			vm_extract_angles_matrix(&cam_angles,&endlevel_camera->orient);
			cam_angles.b += fixmul(bank_rate,FrameTime);
			vm_angles_2_matrix(&endlevel_camera->orient,&cam_angles);
#endif

			timer -= FrameTime;

			if (timer < 0) {

				Endlevel_sequence = EL_STOPPED;

				vm_extract_angles_matrix(&player_angles,&ConsoleObject->orient);

				timer = i2f(3);

			}

			break;
		}

		case EL_STOPPED: {

			get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos);
			chase_angles(&player_angles,&player_dest_angles);
			vm_angles_2_matrix(&ConsoleObject->orient,&player_angles);

			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));

			timer -= FrameTime;

			if (timer < 0) {

				#ifdef SLEW_ON
				slew_obj = endlevel_camera;
				_do_slew_movement(endlevel_camera,1,1);
				timer += FrameTime;		//make time stop
				break;
				#else

				#ifdef SHORT_SEQUENCE

				stop_endlevel_sequence();

				#else
				Endlevel_sequence = EL_PANNING;

				vm_extract_angles_matrix(&camera_cur_angles,&endlevel_camera->orient);


				timer = i2f(3);

				if (Game_mode & GM_MULTI) { // try to skip part of the seq if multiplayer
					stop_endlevel_sequence();
					return;
				}

				//mprintf((0,"Switching to pan...\n"));
				#endif		//SHORT_SEQUENCE
				#endif		//SLEW_ON

			}
			break;
		}

		#ifndef SHORT_SEQUENCE
		case EL_PANNING: {
			#ifndef SLEW_ON
			int mask;
			#endif

			get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos);
			chase_angles(&player_angles,&player_dest_angles);
			vm_angles_2_matrix(&ConsoleObject->orient,&player_angles);
			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));

			#ifdef SLEW_ON
			_do_slew_movement(endlevel_camera,1,1);
			#else

			get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos);
			mask = chase_angles(&camera_cur_angles,&camera_desired_angles);
			vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles);

			if ((mask&5) == 5) {

				vms_vector tvec;

				Endlevel_sequence = EL_CHASING;

				//_MARK_("Done outside");//Commented out -KRB

				vm_vec_normalized_dir_quick(&tvec,&station_pos,&ConsoleObject->pos);
				vm_vector_2_matrix(&ConsoleObject->orient,&tvec,&surface_orient.uvec,NULL);

				desired_fly_speed *= 2;

				//mprintf((0,"Switching to chase...\n"));

			}
			#endif

			break;
		}

		case EL_CHASING: {
			fix d,speed_scale;

			#ifdef SLEW_ON
			_do_slew_movement(endlevel_camera,1,1);
			#endif

			get_angs_to_object(&camera_desired_angles,&ConsoleObject->pos,&endlevel_camera->pos);
			chase_angles(&camera_cur_angles,&camera_desired_angles);

			#ifndef SLEW_ON
			vm_angles_2_matrix(&endlevel_camera->orient,&camera_cur_angles);
			#endif

			d = vm_vec_dist_quick(&ConsoleObject->pos,&endlevel_camera->pos);

			speed_scale = fixdiv(d,i2f(0x20));
			if (d<f1_0) d=f1_0;

			get_angs_to_object(&player_dest_angles,&station_pos,&ConsoleObject->pos);
			chase_angles(&player_angles,&player_dest_angles);
			vm_angles_2_matrix(&ConsoleObject->orient,&player_angles);

			vm_vec_scale_add2(&ConsoleObject->pos,&ConsoleObject->orient.fvec,fixmul(FrameTime,cur_fly_speed));
			#ifndef SLEW_ON
			vm_vec_scale_add2(&endlevel_camera->pos,&endlevel_camera->orient.fvec,fixmul(FrameTime,fixmul(speed_scale,cur_fly_speed)));

			if (vm_vec_dist(&ConsoleObject->pos,&station_pos) < i2f(10))
				stop_endlevel_sequence();
			#endif

			break;

		}
		#endif		//ifdef SHORT_SEQUENCE
	}
}
示例#19
0
void warpin_queue_render(draw_list *scene, object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d)
{
	vec3d center;
	vec3d vecs[5];
	vertex verts[5];

	vm_vec_scale_add( &center, pos, &orient->vec.fvec, -(max_radius/2.5f)/3.0f );


	if (Warp_glow_bitmap >= 0) {
		float r = radius;
		bool render_it = true;

#define OUT_PERCENT1 0.80f
#define OUT_PERCENT2 0.90f

#define IN_PERCENT1 0.10f
#define IN_PERCENT2 0.20f

		if (Cmdline_warp_flash)
		{
			if ( (life_percent >= IN_PERCENT1) && (life_percent < IN_PERCENT2) ) {
				r *= (life_percent - IN_PERCENT1) / (IN_PERCENT2 - IN_PERCENT1);
				//render_it = true;
			} else if ( (life_percent >= OUT_PERCENT1) && (life_percent < OUT_PERCENT2) ) {
				r *= (OUT_PERCENT2 - life_percent) / (OUT_PERCENT2 - OUT_PERCENT1);
				//render_it = true;
			}
		}

		if (render_it) {
			// Add in noise 
			int noise_frame = fl2i(Missiontime/15.0f) % NOISE_NUM_FRAMES;

			r *= (0.40f + Noise[noise_frame] * 0.30f);

			// Bobboau's warp thingie, toggled by cmdline
			if (Cmdline_warp_flash) {
				r += powf((2.0f * life_percent) - 1.0f, 24.0f) * max_radius * 1.5f;
			}

			vecs[4] = center;
			verts[4].texture_position.u = 0.5f; verts[4].texture_position.v = 0.5f; 

			g3_transfer_vertex( &verts[4], &vecs[4] );

			float alpha = (The_mission.flags[Mission::Mission_Flags::Fullneb]) ? (1.0f - neb2_get_fog_intensity(obj)) : 1.0f;

			batch_add_bitmap(Warp_glow_bitmap, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT | TMAP_FLAG_EMISSIVE , &verts[4], 0, r, alpha);
		}
	}

	if ( (Warp_model >= 0) && (warp_3d || Cmdline_3dwarp) ) {
		model_render_params render_info;

		float scale = radius / 25.0f;

		vec3d warp_scale;

		warp_scale.xyz.x = warp_scale.xyz.y = warp_scale.xyz.z = scale;

		float dist = vm_vec_dist_quick( pos, &Eye_position );

		render_info.set_warp_params(texture_bitmap_num, radius/max_radius, warp_scale);
		render_info.set_detail_level_lock((int)(dist / (radius * 10.0f)));
		render_info.set_flags(MR_NO_LIGHTING | MR_NORMAL | MR_NO_FOGGING | MR_NO_CULL | MR_NO_BATCH);

		model_render_queue( &render_info, scene, Warp_model, orient, pos);
	} else {
		float Grid_depth = radius/2.5f;

		// gr_set_bitmap( texture_bitmap_num, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f );	

		vm_vec_scale_add( &vecs[0], &center, &orient->vec.uvec, radius );
		vm_vec_scale_add2( &vecs[0], &orient->vec.rvec, -radius );
		vm_vec_scale_add2( &vecs[0], &orient->vec.fvec, Grid_depth );

		vm_vec_scale_add( &vecs[1], &center, &orient->vec.uvec, radius );
		vm_vec_scale_add2( &vecs[1], &orient->vec.rvec, radius );
		vm_vec_scale_add2( &vecs[1], &orient->vec.fvec, Grid_depth );

		vm_vec_scale_add( &vecs[2], &center, &orient->vec.uvec, -radius );
		vm_vec_scale_add2( &vecs[2], &orient->vec.rvec, radius );
		vm_vec_scale_add2( &vecs[2], &orient->vec.fvec, Grid_depth );

		vm_vec_scale_add( &vecs[3], &center, &orient->vec.uvec, -radius );
		vm_vec_scale_add2( &vecs[3], &orient->vec.rvec, -radius );
		vm_vec_scale_add2( &vecs[3], &orient->vec.fvec, Grid_depth );

		//	vm_vec_scale_add( &vecs[4], ¢er, &orient->vec.fvec, -Grid_depth );
		vecs[4] = center;

		verts[0].texture_position.u = 0.01f;
		verts[0].texture_position.v = 0.01f;

		verts[1].texture_position.u = 0.99f;
		verts[1].texture_position.v = 0.01f;

		verts[2].texture_position.u = 0.99f;
		verts[2].texture_position.v = 0.99f;

		verts[3].texture_position.u = 0.01f;
		verts[3].texture_position.v = 0.99f;

		verts[4].texture_position.u = 0.5f;
		verts[4].texture_position.v = 0.5f; 

		g3_transfer_vertex( &verts[0], &vecs[0] );
		g3_transfer_vertex( &verts[1], &vecs[1] );
		g3_transfer_vertex( &verts[2], &vecs[2] );
		g3_transfer_vertex( &verts[3], &vecs[3] );
		g3_transfer_vertex( &verts[4], &vecs[4] );

		warpin_batch_draw_face( texture_bitmap_num, &verts[0], &verts[4], &verts[1] );
		warpin_batch_draw_face( texture_bitmap_num, &verts[1], &verts[4], &verts[2] );
		warpin_batch_draw_face( texture_bitmap_num, &verts[4], &verts[3], &verts[2] );
		warpin_batch_draw_face( texture_bitmap_num, &verts[0], &verts[3], &verts[4] );
	}

	if (Warp_ball_bitmap > -1 && Cmdline_warp_flash == 1) {
		//flash_ball warp_ball(20, .1f,.25f, &vmd_z_vector, &vmd_zero_vector, 4.0f, 0.5f);
		flash_ball warp_ball(20, .1f,.25f, &orient->vec.fvec, pos, 4.0f, 0.5f);

		float adg = (2.0f * life_percent) - 1.0f;
		float pct = (powf(adg, 4.0f) - powf(adg, 128.0f)) * 4.0f;

		if (pct > 0.00001f) {
			warp_ball.render(Warp_ball_bitmap, max_radius * pct * 0.5f, adg * adg, adg * adg * 6.0f);
		}
	}
}
示例#20
0
object *object_create_explosion_sub(object *objp, short segnum, vms_vector * position, fix size, int vclip_type, fix maxdamage, fix maxdistance, fix maxforce, int parent )
{
	int objnum;
	object *obj;

	objnum = obj_create( OBJ_FIREBALL,vclip_type,segnum,position,&vmd_identity_matrix,size,
					CT_EXPLOSION,MT_NONE,RT_FIREBALL);

	if (objnum < 0 ) {
		mprintf((1, "Can't create object in object_create_explosion_sub.\n"));
		return NULL;
	}

	obj = &Objects[objnum];

	//mprintf( 0, "Fireball created at %d, %d, %d\n", obj->pos.x, obj->pos.y, obj->pos.z );

	//now set explosion-specific data

	obj->lifeleft = Vclip[vclip_type ].play_time;
	obj->ctype.expl_info.spawn_time = -1;
	obj->ctype.expl_info.delete_objnum = -1;
	obj->ctype.expl_info.delete_time = -1;

	if (maxdamage > 0) {
		fix dist, force;
		vms_vector pos_hit, vforce;
		fix damage;
		int i;
		object * obj0p = &Objects[0];
					  
		// -- now legal for badass explosions on a wall. Assert(objp != NULL);

		for (i=0; i<=Highest_object_index; i++ )	{
			//	Weapons used to be affected by badass explosions, but this introduces serious problems.
			//	When a smart bomb blows up, if one of its children goes right towards a nearby wall, it will
			//	blow up, blowing up all the children.  So I remove it.  MK, 09/11/94
			if ( (obj0p->type == OBJ_CNTRLCEN) || (obj0p->type==OBJ_PLAYER) || ((obj0p->type==OBJ_ROBOT) && ((Objects[parent].type != OBJ_ROBOT) || (Objects[parent].id != obj0p->id)))) {
				dist = vm_vec_dist_quick( &obj0p->pos, &obj->pos );
				// Make damage be from 'maxdamage' to 0.0, where 0.0 is 'maxdistance' away;
				if ( dist < maxdistance ) {
					if (object_to_object_visibility(obj, obj0p, FQ_TRANSWALL)) {
						damage = maxdamage - fixmuldiv( dist, maxdamage, maxdistance );
						force = maxforce - fixmuldiv( dist, maxforce, maxdistance );
						
						// Find the force vector on the object
						vm_vec_sub( &vforce, &obj0p->pos, &obj->pos );
						vm_vec_normalize_quick(&vforce);
						vm_vec_scale(&vforce, force );
	
						// Find where the point of impact is... ( pos_hit )
						vm_vec_scale(vm_vec_sub(&pos_hit, &obj->pos, &obj0p->pos), fixdiv(obj0p->size, obj0p->size + dist));
	
						switch ( obj0p->type )	{
							case OBJ_ROBOT:
								phys_apply_force(obj0p,&vforce);

								//	When a robot gets whacked by a badass force, he looks towards it because robots tend to get blasted from behind.
								{
									vms_vector neg_vforce; 
									neg_vforce.x = vforce.x * -2 * (7 - Difficulty_level)/8;
									neg_vforce.y = vforce.y * -2 * (7 - Difficulty_level)/8;
									neg_vforce.z = vforce.z * -2 * (7 - Difficulty_level)/8;
									phys_apply_rot(obj0p,&neg_vforce);
								}
								if ( obj0p->shields >= 0 ) {
									if (apply_damage_to_robot(obj0p, damage, parent))
										if ((objp != NULL) && (parent == Players[Player_num].objnum))
											add_points_to_score(Robot_info[obj0p->id].score_value);
								}
								break;
							case OBJ_CNTRLCEN:
								if ( obj0p->shields >= 0 ) {
									apply_damage_to_controlcen(obj0p, damage, parent );
								}
								break;
							case OBJ_PLAYER:	{
								object * killer=NULL; 
								vms_vector	vforce2;
								if ((objp != NULL) && (Game_mode & GM_MULTI) && (objp->type == OBJ_PLAYER)) {
//									mprintf((0, "Damaged by player %d's explosion.\n", objp->id));
									killer = objp;
								}
								vforce2 = vforce;
								if (parent > -1 ) {
									killer = &Objects[parent];
									if (killer != ConsoleObject)		// if someone else whacks you, cut force by 2x
										vforce2.x /= 2;	vforce2.y /= 2;	vforce2.z /= 2;
								}
								vforce2.x /= 2;	vforce2.y /= 2;	vforce2.z /= 2;

								phys_apply_force(obj0p,&vforce);
								phys_apply_rot(obj0p,&vforce2);
								if ( obj0p->shields >= 0 )
									apply_damage_to_player(obj0p, killer, damage );
							}
								break;

							default:
								Int3();	//	Illegal object type
						}	// end switch
					} else {
						; // mprintf((0, "No badass: robot=%2i, dist=%7.3f, maxdistance=%7.3f .\n", i, f2fl(dist), f2fl(maxdistance)));
					}	// end if (object_to_object_visibility...
				}	// end if (dist < maxdistance)
			}
			obj0p++;
		}	// end for
	}	// end if (maxdamage...

//	mprintf(0, "\n");

	return obj;

}
示例#21
0
void CJumpNode::Render(draw_list* scene, vec3d *pos, vec3d *view_pos)
{
	Assert(pos != NULL);
	// Assert(view_pos != NULL); - view_pos can be NULL

	if(m_flags & JN_HIDE)
		return;

	if(m_modelnum < 0)
		return;

	matrix node_orient = IDENTITY_MATRIX;

	int mr_flags = MR_NO_LIGHTING | MR_NO_BATCH;
	if(!(m_flags & JN_SHOW_POLYS)) {
		mr_flags |= MR_NO_CULL | MR_NO_POLYS | MR_SHOW_OUTLINE | MR_SHOW_OUTLINE_HTL | MR_NO_TEXTURING;
	}

	model_render_params render_info;

	render_info.set_detail_level_lock(0);
	render_info.set_flags(mr_flags);

	if ( Fred_running ) {
		render_info.set_outline_color(m_display_color);

		model_render_queue(&render_info, scene, m_modelnum, &node_orient, pos);
	} else {
		if (m_flags & JN_USE_DISPLAY_COLOR) {
			//gr_set_color_fast(&m_display_color);
			render_info.set_outline_color(m_display_color);
		}
		else if ( view_pos != NULL) {
			int alpha_index = HUD_color_alpha;

			// generate alpha index based on distance to jump this
			float dist;

			dist = vm_vec_dist_quick(view_pos, pos);

			// linearly interpolate alpha.  At 1000m or less, full intensity.  At 10000m or more 1/2 intensity.
			if ( dist < 1000 ) {
				alpha_index = HUD_COLOR_ALPHA_USER_MAX - 2;
			} else if ( dist > 10000 ) {
				alpha_index = HUD_COLOR_ALPHA_USER_MIN;
			} else {
				alpha_index = fl2i( HUD_COLOR_ALPHA_USER_MAX - 2 + (dist-1000) * (HUD_COLOR_ALPHA_USER_MIN-HUD_COLOR_ALPHA_USER_MAX-2) / (9000) + 0.5f);
				if ( alpha_index < HUD_COLOR_ALPHA_USER_MIN ) {
					alpha_index = HUD_COLOR_ALPHA_USER_MIN;
				}
			}

			render_info.set_outline_color(HUD_color_defaults[alpha_index]);
		} else {
			render_info.set_outline_color(HUD_color_red, HUD_color_green, HUD_color_blue);
		}

		model_render_queue(&render_info, scene, m_modelnum, &node_orient, pos);
	}

}
void warpin_render(object *obj, matrix *orient, vec3d *pos, int texture_bitmap_num, float radius, float life_percent, float max_radius, int warp_3d)
{
	vec3d center;
	vec3d vecs[5];
	vertex verts[5];
	int saved_gr_zbuffering = gr_zbuffer_get();

	gr_zbuffer_set(GR_ZBUFF_READ);

	vm_vec_scale_add( &center, pos, &orient->vec.fvec, -(max_radius/2.5f)/3.0f );


	if (Warp_glow_bitmap >= 0) {
		float r = radius;
		bool render_it = true;

		#define OUT_PERCENT1 0.80f
		#define OUT_PERCENT2 0.90f

		#define IN_PERCENT1 0.10f
		#define IN_PERCENT2 0.20f

		if (Cmdline_warp_flash)
		{
			if ( (life_percent >= IN_PERCENT1) && (life_percent < IN_PERCENT2) ) {
				r *= (life_percent - IN_PERCENT1) / (IN_PERCENT2 - IN_PERCENT1);
				//render_it = true;
			} else if ( (life_percent >= OUT_PERCENT1) && (life_percent < OUT_PERCENT2) ) {
				r *= (OUT_PERCENT2 - life_percent) / (OUT_PERCENT2 - OUT_PERCENT1);
				//render_it = true;
			}
		}

		if (render_it) {
			// Add in noise 
			int noise_frame = fl2i(Missiontime/15.0f) % NOISE_NUM_FRAMES;

			r *= (0.40f + Noise[noise_frame] * 0.30f);

			// Bobboau's warp thingie, toggled by cmdline
			if (Cmdline_warp_flash) {
				r += powf((2.0f * life_percent) - 1.0f, 24.0f) * max_radius * 1.5f;
			}

			vecs[4] = center;
			verts[4].texture_position.u = 0.5f; verts[4].texture_position.v = 0.5f; 

			if (Cmdline_nohtl) {
				g3_rotate_vertex( &verts[4], &vecs[4] );
			} else {
				g3_transfer_vertex( &verts[4], &vecs[4] );
			}

			float alpha = (The_mission.flags & MISSION_FLAG_FULLNEB) ? (1.0f - neb2_get_fog_intensity(obj)) : 1.0f;
			gr_set_bitmap( Warp_glow_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, alpha );

			g3_draw_bitmap( &verts[4], 0, r, TMAP_FLAG_TEXTURED | TMAP_HTL_3D_UNLIT );
		}
	}

	if ( (Warp_model >= 0) && (warp_3d || Cmdline_3dwarp) ) {
		float scale = radius / 25.0f;
		model_set_warp_globals(scale, scale, scale, texture_bitmap_num, (radius/max_radius) );

		float dist = vm_vec_dist_quick( pos, &Eye_position );
		model_set_detail_level((int)(dist / (radius * 10.0f)));

		model_render( Warp_model, orient, pos, MR_LOCK_DETAIL | MR_NO_LIGHTING | MR_NORMAL | MR_NO_FOGGING | MR_NO_CULL );

		model_set_warp_globals();
	} else {
		float Grid_depth = radius/2.5f;

		gr_set_bitmap( texture_bitmap_num, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1.0f );	

		vm_vec_scale_add( &vecs[0], &center, &orient->vec.uvec, radius );
		vm_vec_scale_add2( &vecs[0], &orient->vec.rvec, -radius );
		vm_vec_scale_add2( &vecs[0], &orient->vec.fvec, Grid_depth );

		vm_vec_scale_add( &vecs[1], &center, &orient->vec.uvec, radius );
		vm_vec_scale_add2( &vecs[1], &orient->vec.rvec, radius );
		vm_vec_scale_add2( &vecs[1], &orient->vec.fvec, Grid_depth );

		vm_vec_scale_add( &vecs[2], &center, &orient->vec.uvec, -radius );
		vm_vec_scale_add2( &vecs[2], &orient->vec.rvec, radius );
		vm_vec_scale_add2( &vecs[2], &orient->vec.fvec, Grid_depth );

		vm_vec_scale_add( &vecs[3], &center, &orient->vec.uvec, -radius );
		vm_vec_scale_add2( &vecs[3], &orient->vec.rvec, -radius );
		vm_vec_scale_add2( &vecs[3], &orient->vec.fvec, Grid_depth );

	//	vm_vec_scale_add( &vecs[4], ¢er, &orient->vec.fvec, -Grid_depth );
		vecs[4] = center;

		verts[0].texture_position.u = 0.01f;
		verts[0].texture_position.v = 0.01f;
		
		verts[1].texture_position.u = 0.99f;
		verts[1].texture_position.v = 0.01f;

		verts[2].texture_position.u = 0.99f;
		verts[2].texture_position.v = 0.99f;

		verts[3].texture_position.u = 0.01f;
		verts[3].texture_position.v = 0.99f;

		verts[4].texture_position.u = 0.5f;
		verts[4].texture_position.v = 0.5f; 

		if (Cmdline_nohtl) {
			g3_rotate_vertex( &verts[0], &vecs[0] );
			g3_rotate_vertex( &verts[1], &vecs[1] );
			g3_rotate_vertex( &verts[2], &vecs[2] );
			g3_rotate_vertex( &verts[3], &vecs[3] );
			g3_rotate_vertex( &verts[4], &vecs[4] );
		} else {
			g3_transfer_vertex( &verts[0], &vecs[0] );
			g3_transfer_vertex( &verts[1], &vecs[1] );
			g3_transfer_vertex( &verts[2], &vecs[2] );
			g3_transfer_vertex( &verts[3], &vecs[3] );
			g3_transfer_vertex( &verts[4], &vecs[4] );
		}

		int cull = gr_set_cull(0); // fixes rendering problem in D3D - taylor
		draw_face( &verts[0], &verts[4], &verts[1] );
		draw_face( &verts[1], &verts[4], &verts[2] );
		draw_face( &verts[4], &verts[3], &verts[2] );
		draw_face( &verts[0], &verts[3], &verts[4] );
		gr_set_cull(cull);
	}

	if (Warp_ball_bitmap > -1 && Cmdline_warp_flash == 1) {
		flash_ball warp_ball(20, .1f,.25f, &vmd_z_vector, &vmd_zero_vector, 4.0f, 0.5f);
		float adg = (2.0f * life_percent) - 1.0f;
		float pct = (powf(adg, 4.0f) - powf(adg, 128.0f)) * 4.0f;

		if (pct > 0.00001f) {
			g3_start_instance_matrix(pos, orient, true);

			gr_set_bitmap(Warp_ball_bitmap, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 0.9999f);		

			warp_ball.render(max_radius * pct * 0.5f, adg * adg, adg * adg * 6.0f);

			g3_done_instance(true);
		}
	}

	gr_zbuffer_set( saved_gr_zbuffering );
}
/**
 * Checks weapon-weapon collisions.  
 * @param pair obj_pair pointer to the two objects. pair->a and pair->b are weapons.
 * @return 1 if all future collisions between these can be ignored
 */
int collide_weapon_weapon( obj_pair * pair )
{
	float A_radius, B_radius;
	object *A = pair->a;
	object *B = pair->b;

	Assert( A->type == OBJ_WEAPON );
	Assert( B->type == OBJ_WEAPON );
	
	//	Don't allow ship to shoot down its own missile.
	if (A->parent_sig == B->parent_sig)
		return 1;

	//	Only shoot down teammate's missile if not traveling in nearly same direction.
	if (Weapons[A->instance].team == Weapons[B->instance].team)
		if (vm_vec_dot(&A->orient.vec.fvec, &B->orient.vec.fvec) > 0.7f)
			return 1;

	//	Ignore collisions involving a bomb if the bomb is not yet armed.
	weapon	*wpA, *wpB;
	weapon_info	*wipA, *wipB;

	wpA = &Weapons[A->instance];
	wpB = &Weapons[B->instance];
	wipA = &Weapon_info[wpA->weapon_info_index];
	wipB = &Weapon_info[wpB->weapon_info_index];

	A_radius = A->radius;
	B_radius = B->radius;

	if (wipA->weapon_hitpoints > 0) {
		if (!(wipA->wi_flags2 & WIF2_HARD_TARGET_BOMB)) {
			A_radius *= 2;		// Makes bombs easier to hit
		}
		
		if (wipA->wi_flags & WIF_LOCKED_HOMING) {
			if ( (wipA->max_lifetime - wpA->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] )
				return 0;
		}
		else if ( (wipA->lifetime - wpA->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] )
			return 0;
	}

	if (wipB->weapon_hitpoints > 0) {
		if (!(wipB->wi_flags2 & WIF2_HARD_TARGET_BOMB)) {
			B_radius *= 2;		// Makes bombs easier to hit
		}
		if (wipB->wi_flags & WIF_LOCKED_HOMING) {
			if ( (wipB->max_lifetime - wpB->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] )
				return 0;
		}
		else if ( (wipB->lifetime - wpB->lifeleft) < The_mission.ai_profile->delay_bomb_arm_timer[Game_skill_level] )
			return 0;
	}

	//	Rats, do collision detection.
	if (collide_subdivide(&A->last_pos, &A->pos, A_radius, &B->last_pos, &B->pos, B_radius))
	{
		Script_system.SetHookObjects(4, "Weapon", A, "WeaponB", B, "Self",A, "Object", B);
		bool a_override = Script_system.IsConditionOverride(CHA_COLLIDEWEAPON, A);
		
		//Should be reversed
		Script_system.SetHookObjects(4, "Weapon", B, "WeaponB", A, "Self",B, "Object", A);
		bool b_override = Script_system.IsConditionOverride(CHA_COLLIDEWEAPON, B);

		if(!a_override && !b_override)
		{
			float aDamage = wipA->damage;
			if (wipB->armor_type_idx >= 0)
				aDamage = Armor_types[wipB->armor_type_idx].GetDamage(aDamage, wipA->damage_type_idx, 1.0f);

			float bDamage = wipB->damage;
			if (wipA->armor_type_idx >= 0)
				bDamage = Armor_types[wipA->armor_type_idx].GetDamage(bDamage, wipB->damage_type_idx, 1.0f);

			if (wipA->weapon_hitpoints > 0) {
				if (wipB->weapon_hitpoints > 0) {		//	Two bombs collide, detonate both.
					if ((wipA->wi_flags & WIF_BOMB) && (wipB->wi_flags & WIF_BOMB)) {
						Weapons[A->instance].lifeleft = 0.01f;
						Weapons[B->instance].lifeleft = 0.01f;
						Weapons[A->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
						Weapons[B->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
					} else {
						A->hull_strength -= bDamage;
						B->hull_strength -= aDamage;

						// safety to make sure either of the weapons die - allow 'bulkier' to keep going
						if ((A->hull_strength > 0.0f) && (B->hull_strength > 0.0f)) {
							if (wipA->weapon_hitpoints > wipB->weapon_hitpoints) {
								B->hull_strength = -1.0f;
							} else {
								A->hull_strength = -1.0f;
							}
						}
						
						if (A->hull_strength < 0.0f) {
							Weapons[A->instance].lifeleft = 0.01f;
							Weapons[A->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
						}
						if (B->hull_strength < 0.0f) {
							Weapons[B->instance].lifeleft = 0.01f;
							Weapons[B->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
						}
					}
				} else {
					A->hull_strength -= bDamage;
					Weapons[B->instance].lifeleft = 0.01f;
					Weapons[B->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
					if (A->hull_strength < 0.0f) {
						Weapons[A->instance].lifeleft = 0.01f;
						Weapons[A->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
					}
				}
			} else if (wipB->weapon_hitpoints > 0) {
				B->hull_strength -= aDamage;
				Weapons[A->instance].lifeleft = 0.01f;
				Weapons[A->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
				if (B->hull_strength < 0.0f) {
					Weapons[B->instance].lifeleft = 0.01f;
					Weapons[B->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
				}
			}

			// single player and multiplayer masters evaluate the scoring and kill stuff
			if (!MULTIPLAYER_CLIENT) {

				//Save damage for bomb so we can do scoring once it's destroyed. -Halleck
				if (wipA->wi_flags & WIF_BOMB) {
					scoring_add_damage_to_weapon(A, B, wipB->damage);
					//Update stats. -Halleck
					scoring_eval_hit(A, B, 0);
				}
				if (wipB->wi_flags & WIF_BOMB) {
					scoring_add_damage_to_weapon(B, A, wipA->damage);
					//Update stats. -Halleck
					scoring_eval_hit(B, A, 0);
				}
			}

	#ifndef NDEBUG
			float dist = 0.0f;

			if (Weapons[A->instance].lifeleft == 0.01f) {
				dist = vm_vec_dist_quick(&A->pos, &wpA->homing_pos);
			}
			if (Weapons[B->instance].lifeleft == 0.01f) {
				dist = vm_vec_dist_quick(&B->pos, &wpB->homing_pos);
			}
	#endif
		}

		if(!(b_override && !a_override))
		{
			Script_system.SetHookObjects(4, "Weapon", A, "WeaponB", B, "Self",A, "Object", B);
			Script_system.RunCondition(CHA_COLLIDEWEAPON, '\0', NULL, A, wpA->weapon_info_index);
		}
		if((b_override && !a_override) || (!b_override && !a_override))
		{
			//Should be reversed
			Script_system.SetHookObjects(4, "Weapon", B, "WeaponB", A, "Self",B, "Object", A);
			Script_system.RunCondition(CHA_COLLIDEWEAPON, '\0', NULL, B, wpB->weapon_info_index);
		}

		Script_system.RemHookVars(4, "Weapon", "WeaponB", "Self","ObjectB");
		return 1;
	}

	return 0;
}
示例#24
0
//	----------------------------------------------------------------------------------------------------------
void robotmaker_proc( FuelCenter * robotcen )
{
	fix		dist_to_player;
	vms_vector	cur_object_loc; //, direction;
	int		matcen_num, segnum, objnum;
	object	*obj;
	fix		top_time;
	vms_vector	direction;

	if (robotcen->Enabled == 0)
		return;

	if (robotcen->Disable_time > 0) {
		robotcen->Disable_time -= FrameTime;
		if (robotcen->Disable_time <= 0) {
			robotcen->Enabled = 0;
		}
	}

	//	No robot making in multiplayer mode.
#ifdef NETWORK
#ifndef SHAREWARE
	if ((Game_mode & GM_MULTI) && (!(Game_mode & GM_MULTI_ROBOTS) || !multi_i_am_master()))
		return;
#else
	if (Game_mode & GM_MULTI)
		return;
#endif
#endif

	// Wait until transmorgafier has capacity to make a robot...
	if ( robotcen->Capacity <= 0 ) {
		return;
	}

	matcen_num = Segment2s[robotcen->segnum].matcen_num;

	if ( matcen_num == -1 ) {
		return;
	}

	if (RobotCenters[matcen_num].robot_flags[0]==0 && RobotCenters[matcen_num].robot_flags[1]==0) {
		return;
	}

	// Wait until we have a free slot for this puppy...
   //	  <<<<<<<<<<<<<<<< Num robots in mine >>>>>>>>>>>>>>>>>>>>>>>>>>    <<<<<<<<<<<< Max robots in mine >>>>>>>>>>>>>>>
	if ( (Players[Player_num].num_robots_level - Players[Player_num].num_kills_level) >= (Gamesave_num_org_robots + Num_extry_robots ) ) {
		return;
	}

	robotcen->Timer += FrameTime;

	switch( robotcen->Flag )	{
	case 0:		// Wait until next robot can generate
		if (Game_mode & GM_MULTI)
		{
			top_time = ROBOT_GEN_TIME;	
		}
		else
		{
			dist_to_player = vm_vec_dist_quick( &ConsoleObject->pos, &robotcen->Center );
			top_time = dist_to_player/64 + d_rand() * 2 + F1_0*2;
			if ( top_time > ROBOT_GEN_TIME )
				top_time = ROBOT_GEN_TIME + d_rand();
			if ( top_time < F1_0*2 )
				top_time = F1_0*3/2 + d_rand()*2;
		}

		if (robotcen->Timer > top_time )	{
			int	count=0;
			int	i, my_station_num = robotcen-Station;
			object *obj;

			//	Make sure this robotmaker hasn't put out its max without having any of them killed.
			for (i=0; i<=Highest_object_index; i++)
				if (Objects[i].type == OBJ_ROBOT)
					if ((Objects[i].matcen_creator^0x80) == my_station_num)
						count++;
			if (count > Difficulty_level + 3) {
				robotcen->Timer /= 2;
				return;
			}

			//	Whack on any robot or player in the matcen segment.
			count=0;
			segnum = robotcen->segnum;
			for (objnum=Segments[segnum].objects;objnum!=-1;objnum=Objects[objnum].next)	{
				count++;
				if ( count > MAX_OBJECTS )	{
					Int3();
					return;
				}
				if (Objects[objnum].type==OBJ_ROBOT) {
					collide_robot_and_materialization_center(&Objects[objnum]);
					robotcen->Timer = top_time/2;
					return;
				} else if (Objects[objnum].type==OBJ_PLAYER ) {
					collide_player_and_materialization_center(&Objects[objnum]);
					robotcen->Timer = top_time/2;
					return;
				}
			}

			compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);
			// HACK!!! The 10 under here should be something equal to the 1/2 the size of the segment.
			obj = object_create_explosion(robotcen->segnum, &cur_object_loc, i2f(10), VCLIP_MORPHING_ROBOT );

			if (obj)
				extract_orient_from_segment(&obj->orient,&Segments[robotcen->segnum]);

			if ( Vclip[VCLIP_MORPHING_ROBOT].sound_num > -1 )		{
				digi_link_sound_to_pos( Vclip[VCLIP_MORPHING_ROBOT].sound_num, robotcen->segnum, 0, &cur_object_loc, 0, F1_0 );
			}
			robotcen->Flag	= 1;
			robotcen->Timer = 0;

		}
		break;
	case 1:			// Wait until 1/2 second after VCLIP started.
		if (robotcen->Timer > (Vclip[VCLIP_MORPHING_ROBOT].play_time/2) )	{

			robotcen->Capacity -= EnergyToCreateOneRobot;
			robotcen->Flag = 0;

			robotcen->Timer = 0;
			compute_segment_center(&cur_object_loc, &Segments[robotcen->segnum]);

			// If this is the first materialization, set to valid robot.
			if (RobotCenters[matcen_num].robot_flags[0] != 0 || RobotCenters[matcen_num].robot_flags[1] != 0) {
				int	type;
				uint	flags;
				sbyte   legal_types[64];   // 64 bits, the width of robot_flags[].
				int	num_types, robot_index, i;

				num_types = 0;
				for (i=0;i<2;i++) {
					robot_index = i*32;
					flags = RobotCenters[matcen_num].robot_flags[i];
					while (flags) {
						if (flags & 1)
							legal_types[num_types++] = robot_index;
						flags >>= 1;
						robot_index++;
					}
				}

				if (num_types == 1)
					type = legal_types[0];
				else
					type = legal_types[(d_rand() * num_types) / 32768];

				obj = create_morph_robot(&Segments[robotcen->segnum], &cur_object_loc, type );
				if (obj != NULL) {
#ifndef SHAREWARE
#ifdef NETWORK
					if (Game_mode & GM_MULTI)
						multi_send_create_robot(robotcen-Station, obj-Objects, type);
#endif
#endif
					obj->matcen_creator = (robotcen-Station) | 0x80;

					// Make object faces player...
					vm_vec_sub( &direction, &ConsoleObject->pos,&obj->pos );
					vm_vector_2_matrix( &obj->orient, &direction, &obj->orient.uvec, NULL);
	
					morph_start( obj );
					//robotcen->last_created_obj = obj;
					//robotcen->last_created_sig = robotcen->last_created_obj->signature;
				}
			}
 
		}
int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float time_limit = 0.0f, int *next_hit = NULL)
{
    mc_info mc, mc_shield, mc_hull;
    ship	*shipp;
    ship_info *sip;
    weapon	*wp;
    weapon_info	*wip;

    Assert( ship_objp != NULL );
    Assert( ship_objp->type == OBJ_SHIP );
    Assert( ship_objp->instance >= 0 );

    shipp = &Ships[ship_objp->instance];
    sip = &Ship_info[shipp->ship_info_index];

    Assert( weapon_objp != NULL );
    Assert( weapon_objp->type == OBJ_WEAPON );
    Assert( weapon_objp->instance >= 0 );

    wp = &Weapons[weapon_objp->instance];
    wip = &Weapon_info[wp->weapon_info_index];


    Assert( shipp->objnum == OBJ_INDEX(ship_objp));

    // Make ships that are warping in not get collision detection done
    if ( shipp->is_arriving() ) return 0;

    //	Return information for AI to detect incoming fire.
    //	Could perhaps be done elsewhere at lower cost --MK, 11/7/97
    float	dist = vm_vec_dist_quick(&ship_objp->pos, &weapon_objp->pos);
    if (dist < weapon_objp->phys_info.speed) {
        update_danger_weapon(ship_objp, weapon_objp);
    }

    int	valid_hit_occurred = 0;				// If this is set, then hitpos is set
    int	quadrant_num = -1;
    polymodel *pm = model_get(sip->model_num);

    //	total time is flFrametime + time_limit (time_limit used to predict collisions into the future)
    vec3d weapon_end_pos;
    vm_vec_scale_add( &weapon_end_pos, &weapon_objp->pos, &weapon_objp->phys_info.vel, time_limit );


    // Goober5000 - I tried to make collision code here much saner... here begin the (major) changes
    mc_info_init(&mc);

    // set up collision structs
    mc.model_instance_num = shipp->model_instance_num;
    mc.model_num = sip->model_num;
    mc.submodel_num = -1;
    mc.orient = &ship_objp->orient;
    mc.pos = &ship_objp->pos;
    mc.p0 = &weapon_objp->last_pos;
    mc.p1 = &weapon_end_pos;
    mc.lod = sip->collision_lod;
    memcpy(&mc_shield, &mc, sizeof(mc_info));
    memcpy(&mc_hull, &mc, sizeof(mc_info));

    // (btw, these are leftover comments from below...)
    //
    //	Note: This code is obviously stupid. We want to add the shield point if there is shield to hit, but:
    //		1. We want the size/color of the hit effect to indicate shield damage done.  (i.e., for already-weak shield, smaller effect)
    //		2. Currently (8/9/97), apply_damage_to_shield() passes lefer damage to hull, which might not make sense.  If
    //			wouldn't have collided with hull, shouldn't do damage.  Once this is fixed, the code below needs to cast the
    //			vector through to the hull if there is leftover damage.
    //
    // WIF2_PIERCE_SHIELDS pierces shields
    // AL 1-14-97: "Puncture" doesn't mean penetrate shield anymore, it means that it punctures
    //					hull to inflict maximum subsystem damage
    //
    // _argv[-1], 16 Jan 2005: Surface shields.
    // Surface shields allow for shields on a ship without a shield mesh.  Good for putting real shields
    // on the Lucifer.  This also fixes the strange bug where shots will occasionally go through the
    // shield mesh when they shouldn't.  I don't know what causes this, but this fixes that -- shields
    // will absorb it when it hits the hull instead.  This has no fancy graphical effect, though.
    // Someone should make one.

    // check both kinds of collisions
    int shield_collision = 0;
    int hull_collision = 0;

    // check shields for impact
    if (!(ship_objp->flags[Object::Object_Flags::No_shields])) {
        if (sip->flags[Ship::Info_Flags::Auto_spread_shields]) {
            // The weapon is not allowed to impact the shield before it reaches this point
            vec3d shield_ignored_until = weapon_objp->last_pos;

            float weapon_flown_for = vm_vec_dist(&wp->start_pos, &weapon_objp->last_pos);
            float min_weapon_span;

            if (sip->auto_shield_spread_min_span >= 0.0f) {
                min_weapon_span = sip->auto_shield_spread_min_span;
            } else {
                min_weapon_span = sip->auto_shield_spread;
            }

            // If weapon hasn't yet flown a distance greater than the maximum ignore
            // range, then some part of the currently checked range needs to be
            // ignored
            if (weapon_flown_for < min_weapon_span) {
                vm_vec_sub(&shield_ignored_until, &weapon_end_pos, &wp->start_pos);
                vm_vec_normalize(&shield_ignored_until);
                vm_vec_scale(&shield_ignored_until, min_weapon_span);
                vm_vec_add2(&shield_ignored_until, &wp->start_pos);
            }

            float this_range = vm_vec_dist(&weapon_objp->last_pos, &weapon_end_pos);

            // The range during which the weapon is not allowed to collide with the
            // shield, except if it actually hits the hull
            float ignored_range;

            // If the weapon has not yet surpassed the ignore range, calculate the
            // remaining ignore range
            if (vm_vec_dist(&wp->start_pos, &shield_ignored_until) > weapon_flown_for)
                ignored_range = vm_vec_dist(&weapon_objp->last_pos, &shield_ignored_until);
            else
                ignored_range = 0.0f;

            // The range during which the weapon may impact the shield
            float active_range = this_range - ignored_range;

            // During the ignored range, we only check for a ray collision with
            // the model
            if (ignored_range > 0.0f) {
                mc_shield.flags = MC_CHECK_MODEL;
                mc_shield.p1 = &shield_ignored_until;

                shield_collision = model_collide(&mc_shield);

                mc_shield.p1 = &weapon_end_pos;
                mc_shield.hit_dist = mc_shield.hit_dist * (ignored_range / this_range);
            }

            // If no collision with the model found in the ignore range, only
            // then do we check for sphereline collisions with the model during the
            // non-ignored range
            if (!shield_collision && weapon_flown_for + this_range > min_weapon_span) {
                mc_shield.p0 = &shield_ignored_until;

                mc_shield.p1 = &weapon_end_pos;

                mc_shield.radius = sip->auto_shield_spread;

                if (sip->auto_shield_spread_from_lod > -1) {
                    mc_shield.lod = sip->auto_shield_spread_from_lod;
                }

                mc_shield.flags = MC_CHECK_MODEL | MC_CHECK_SPHERELINE;

                shield_collision = model_collide(&mc_shield);

                mc_shield.lod = sip->collision_lod;
                mc_shield.submodel_num = -1;

                // Because we manipulated p0 and p1 above, hit_dist will be
                // relative to the values we used, not the values the rest of
                // the code expects; this fixes that
                mc_shield.p0 = &weapon_objp->last_pos;
                mc_shield.p1 = &weapon_end_pos;
                mc_shield.hit_dist = (ignored_range + (active_range * mc_shield.hit_dist)) / this_range;
            }

            if (shield_collision) {
                // If we used a sphereline check, then the collision point will lie
                // somewhere on the ship's hull; this re-positions it to lie on the
                // correct point along the weapon's path
                if (mc_shield.flags & MC_CHECK_SPHERELINE) {
                    vec3d tempv;
                    vm_vec_sub(&tempv, mc_shield.p1, mc_shield.p0);
                    vm_vec_scale(&tempv, mc_shield.hit_dist);
                    vm_vec_add2(&tempv, mc_shield.p0);
                    mc_shield.hit_point_world = tempv;
                }

                // Re-calculate hit_point because it's likely pointing to the wrong
                // place
                vec3d tempv;
                vm_vec_sub(&tempv, &mc_shield.hit_point_world, &ship_objp->pos);
                vm_vec_rotate(&mc_shield.hit_point, &tempv, &ship_objp->orient);
            }
        } else if (sip->flags[Ship::Info_Flags::Surface_shields]) {
            if (pm->shield.ntris > 0) {
                // If there is a shield mesh, we need to check that first
                mc_shield.flags = MC_CHECK_SHIELD;
                shield_collision = model_collide(&mc_shield);
            }

            if (!shield_collision) {
                // But if no shield mesh or it was missed, check for a hull collision
                mc_shield.flags = MC_CHECK_MODEL;
                shield_collision = model_collide(&mc_shield);

                // Because we used MC_CHECK_MODEL, the returned hit position might be
                // in a submodel's frame of reference, so we need to ensure we end up
                // in the ship's frame of reference
                vec3d local_pos;
                vm_vec_sub(&local_pos, &mc_shield.hit_point_world, &ship_objp->pos);
                vm_vec_rotate(&mc_shield.hit_point, &local_pos, &ship_objp->orient);
            }
        } else {
            // Normal collision check against a shield mesh
            mc_shield.flags = MC_CHECK_SHIELD;
            shield_collision = (pm->shield.ntris > 0) ? model_collide(&mc_shield) : 0;
        }
    }

    // If we found a shield collision but were only checking for a simple model
    // collision, we can re-use the same collision info for the hull as well
    if (shield_collision && mc_shield.flags == MC_CHECK_MODEL) {
        memcpy(&mc_hull, &mc_shield, sizeof(mc_info));
        hull_collision = shield_collision;

        // The weapon has impacted on the hull, so if it should therefore bypass
        // the shields altogether, we do it here
        if (sip->auto_shield_spread_bypass) {
            shield_collision = 0;
        }
    } else {
        mc_hull.flags = MC_CHECK_MODEL;
        hull_collision = model_collide(&mc_hull);
    }

    if (shield_collision) {
        // pick out the shield quadrant
        quadrant_num = get_quadrant(&mc_shield.hit_point, ship_objp);

        // make sure that the shield is active in that quadrant
        if (shipp->flags[Ship::Ship_Flags::Dying] || !ship_is_shield_up(ship_objp, quadrant_num))
            quadrant_num = -1;

        // see if we hit the shield
        if (quadrant_num >= 0) {
            // do the hit effect
            if ( mc_shield.shield_hit_tri != -1 && (mc_shield.hit_dist*(flFrametime + time_limit) - flFrametime) < 0.0f ) {
                add_shield_point(OBJ_INDEX(ship_objp), mc_shield.shield_hit_tri, &mc_shield.hit_point);
            }

            // if this weapon pierces the shield, then do the hit effect, but act like a shield collision never occurred;
            // otherwise, we have a valid hit on this shield
            if (wip->wi_flags[Weapon::Info_Flags::Pierce_shields])
                quadrant_num = -1;
            else
                valid_hit_occurred = 1;
        }
    }

    // see which impact we use
    if (shield_collision && valid_hit_occurred)
    {
        memcpy(&mc, &mc_shield, sizeof(mc_info));
        Assert(quadrant_num >= 0);
    }
    else if (hull_collision)
    {
        memcpy(&mc, &mc_hull, sizeof(mc_info));
        valid_hit_occurred = 1;
    }

    // check if the hit point is beyond the clip plane when warping out.
    if ((shipp->flags[Ship::Ship_Flags::Depart_warp]) &&
            (shipp->warpout_effect) &&
            (valid_hit_occurred))
    {
        vec3d warp_pnt, hit_direction;
        matrix warp_orient;

        shipp->warpout_effect->getWarpPosition(&warp_pnt);
        shipp->warpout_effect->getWarpOrientation(&warp_orient);

        vm_vec_sub(&hit_direction, &mc.hit_point_world, &warp_pnt);

        if (vm_vec_dot(&hit_direction, &warp_orient.vec.fvec) < 0.0f)
        {
            valid_hit_occurred = 0;
        }
    }

    // deal with predictive collisions.  Find their actual hit time and see if they occured in current frame
    if (next_hit && valid_hit_occurred) {
        // find hit time
        *next_hit = (int) (1000.0f * (mc.hit_dist*(flFrametime + time_limit) - flFrametime) );
        if (*next_hit > 0)
            // if hit occurs outside of this frame, do not do damage
            return 1;
    }

    if ( valid_hit_occurred )
    {
        wp->collisionInfo = new mc_info;	// The weapon will free this memory later
        memcpy(wp->collisionInfo, &mc, sizeof(mc_info));

        Script_system.SetHookObjects(4, "Ship", ship_objp, "Weapon", weapon_objp, "Self",ship_objp, "Object", weapon_objp);
        bool ship_override = Script_system.IsConditionOverride(CHA_COLLIDEWEAPON, ship_objp);

        Script_system.SetHookObjects(2, "Self",weapon_objp, "Object", ship_objp);
        bool weapon_override = Script_system.IsConditionOverride(CHA_COLLIDESHIP, weapon_objp);

        if(!ship_override && !weapon_override) {
            if (shield_collision && quadrant_num >= 0) {
                if ((sip->shield_impact_explosion_anim > -1) && (wip->shield_impact_explosion_radius > 0)) {
                    shield_impact_explosion(&mc.hit_point, ship_objp, wip->shield_impact_explosion_radius, sip->shield_impact_explosion_anim);
                }
            }
            ship_weapon_do_hit_stuff(ship_objp, weapon_objp, &mc.hit_point_world, &mc.hit_point, quadrant_num, mc.hit_submodel, mc.hit_normal);
        }

        Script_system.SetHookObjects(2, "Self",ship_objp, "Object", weapon_objp);
        if(!(weapon_override && !ship_override))
            Script_system.RunCondition(CHA_COLLIDEWEAPON, '\0', NULL, ship_objp, wp->weapon_info_index);

        Script_system.SetHookObjects(2, "Self",weapon_objp, "Object", ship_objp);
        if((weapon_override && !ship_override) || (!weapon_override && !ship_override))
            Script_system.RunCondition(CHA_COLLIDESHIP, '\0', NULL, weapon_objp);

        Script_system.RemHookVars(4, "Ship", "Weapon", "Self","Object");
    }
    else if ((Missiontime - wp->creation_time > F1_0/2) && (wip->is_homing()) && (wp->homing_object == ship_objp)) {
        if (dist < wip->shockwave.inner_rad) {
            vec3d	vec_to_ship;

            vm_vec_normalized_dir(&vec_to_ship, &ship_objp->pos, &weapon_objp->pos);

            if (vm_vec_dot(&vec_to_ship, &weapon_objp->orient.vec.fvec) < 0.0f) {
                // check if we're colliding against "invisible" ship
                if (!(shipp->flags[Ship::Ship_Flags::Dont_collide_invis])) {
                    wp->lifeleft = 0.001f;
                    if (ship_objp == Player_obj)
                        nprintf(("Jim", "Frame %i: Weapon %d set to detonate, dist = %7.3f.\n", Framecount, OBJ_INDEX(weapon_objp), dist));
                    valid_hit_occurred = 1;
                }
            }

        }
    }

    return valid_hit_occurred;
}
示例#26
0
int automap_process_input(window *wind, d_event *event, automap *am)
{
	vms_matrix tempm;

	Controls = am->controls;
	kconfig_read_controls(event, 1);
	am->controls = Controls;
	memset(&Controls, 0, sizeof(control_info));

	if ( !am->controls.automap_state && (am->leave_mode==1) )
	{
		window_close(wind);
		return 1;
	}
	
	if ( am->controls.automap_count > 0)
	{
		am->controls.automap_count = 0;
		if (am->leave_mode==0)
		{
			window_close(wind);
			return 1;
		}
	}
	
	if (PlayerCfg.AutomapFreeFlight)
	{
		if ( am->controls.fire_primary_count > 0)
		{
			// Reset orientation
			am->viewMatrix = Objects[Players[Player_num].objnum].orient;
			vm_vec_scale_add(&am->view_position, &Objects[Players[Player_num].objnum].pos, &am->viewMatrix.fvec, -ZOOM_DEFAULT );
			am->controls.fire_primary_count = 0;
		}
		
		if (am->controls.pitch_time || am->controls.heading_time || am->controls.bank_time)
		{
			vms_angvec tangles;
			vms_matrix new_m;

			tangles.p = fixdiv( am->controls.pitch_time, ROT_SPEED_DIVISOR );
			tangles.h = fixdiv( am->controls.heading_time, ROT_SPEED_DIVISOR );
			tangles.b = fixdiv( am->controls.bank_time, ROT_SPEED_DIVISOR*2 );

			vm_angles_2_matrix(&tempm, &tangles);
			vm_matrix_x_matrix(&new_m,&am->viewMatrix,&tempm);
			am->viewMatrix = new_m;
			check_and_fix_matrix(&am->viewMatrix);
		}
		
		if ( am->controls.forward_thrust_time || am->controls.vertical_thrust_time || am->controls.sideways_thrust_time )
		{
			vm_vec_scale_add2( &am->view_position, &am->viewMatrix.fvec, am->controls.forward_thrust_time*ZOOM_SPEED_FACTOR );
			vm_vec_scale_add2( &am->view_position, &am->viewMatrix.uvec, am->controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &am->view_position, &am->viewMatrix.rvec, am->controls.sideways_thrust_time*SLIDE_SPEED );
			
			// Crude wrapping check
			if (am->view_position.x >  F1_0*32000) am->view_position.x =  F1_0*32000;
			if (am->view_position.x < -F1_0*32000) am->view_position.x = -F1_0*32000;
			if (am->view_position.y >  F1_0*32000) am->view_position.y =  F1_0*32000;
			if (am->view_position.y < -F1_0*32000) am->view_position.y = -F1_0*32000;
			if (am->view_position.z >  F1_0*32000) am->view_position.z =  F1_0*32000;
			if (am->view_position.z < -F1_0*32000) am->view_position.z = -F1_0*32000;
		}
	}
	else
	{
		if ( am->controls.fire_primary_count > 0)
		{
			// Reset orientation
			am->viewDist = ZOOM_DEFAULT;
			am->tangles.p = PITCH_DEFAULT;
			am->tangles.h  = 0;
			am->tangles.b  = 0;
			am->view_target = Objects[Players[Player_num].objnum].pos;
			am->controls.fire_primary_count = 0;
		}

		am->viewDist -= am->controls.forward_thrust_time*ZOOM_SPEED_FACTOR;
		am->tangles.p += fixdiv( am->controls.pitch_time, ROT_SPEED_DIVISOR );
		am->tangles.h  += fixdiv( am->controls.heading_time, ROT_SPEED_DIVISOR );
		am->tangles.b  += fixdiv( am->controls.bank_time, ROT_SPEED_DIVISOR*2 );

		if ( am->controls.vertical_thrust_time || am->controls.sideways_thrust_time )
		{
			vms_angvec      tangles1;
			vms_vector      old_vt;

			old_vt = am->view_target;
			tangles1 = am->tangles;
			vm_angles_2_matrix(&tempm,&tangles1);
			vm_matrix_x_matrix(&am->viewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
			vm_vec_scale_add2( &am->view_target, &am->viewMatrix.uvec, am->controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &am->view_target, &am->viewMatrix.rvec, am->controls.sideways_thrust_time*SLIDE_SPEED );
			if ( vm_vec_dist_quick( &am->view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )
				am->view_target = old_vt;
		}

		vm_angles_2_matrix(&tempm,&am->tangles);
		vm_matrix_x_matrix(&am->viewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);

		if ( am->viewDist < ZOOM_MIN_VALUE ) am->viewDist = ZOOM_MIN_VALUE;
		if ( am->viewDist > ZOOM_MAX_VALUE ) am->viewDist = ZOOM_MAX_VALUE;
	}
	
	return 0;
}
示例#27
0
void do_automap( int key_code )	{
	int done=0;
	vms_matrix	tempm;
	vms_angvec	tangles;
	int leave_mode=0;
	int first_time=1;
	int pcx_error;
	int i;
	int c;
	char filename[] = "MAP.PCX";
	fix entry_time;
	int pause_game=1;		// Set to 1 if everything is paused during automap...No pause during net.
	fix t1, t2;
	control_info saved_control_info;
	int Max_segments_away = 0;
	int SegmentLimit = 1;

	key_code = key_code;	// disable warning...

	if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
		pause_game = 0;

	if (pause_game)
		stop_time();

	create_name_canv();

	Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES);			//make maybe smaller than max
	//Edges	= malloc( sizeof(Edge_info)*Max_edges);
	//if ( Edges == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(Edge_info)*Max_edges/1024));
	//	return;
	//}
	//DrawingListBright = malloc( sizeof(short)*Max_edges);
	//if ( DrawingListBright == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(short)*Max_edges/1024));
	//	return;
	//}

	mprintf( (0, "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES ));
	mprintf( (0, "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 ));

	gr_palette_clear();
	gr_init_sub_canvas(&Page,&VR_render_buffer[0],0, 0, 640, 480);
	gr_init_sub_canvas(&DrawingPage,&Page,38,77,564,381);

#if 0
	gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,320,400);
	gr_init_sub_canvas(&Pages[1],grd_curcanv,0,401,320,400);
	gr_init_sub_canvas(&DrawingPages[0],&Pages[0],16,69,288,272);
	gr_init_sub_canvas(&DrawingPages[1],&Pages[1],16,69,288,272);
#endif

	gr_set_current_canvas(&Page);
	pcx_error = pcx_read_bitmap(filename,&(grd_curcanv->cv_bitmap),BM_LINEAR,NULL);
	if ( pcx_error != PCX_ERROR_NONE )	{
		printf("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
		Error("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
		return;
	}

	gr_set_curfont(Gamefonts[GFONT_BIG_1]);
	gr_set_fontcolor(BM_XRGB(20, 20, 20), -1);
	gr_printf( 80, 36,TXT_AUTOMAP,GFONT_BIG_1);
	gr_set_curfont(Gamefonts[GFONT_SMALL]);
	gr_set_fontcolor(BM_XRGB(20, 20, 20), -1);
	gr_printf( 265, 27,TXT_TURN_SHIP);
	gr_printf( 265, 44,TXT_SLIDE_UPDOWN);
	gr_printf( 265, 61,TXT_VIEWING_DISTANCE);

	gr_set_current_canvas(&DrawingPage);

	automap_build_edge_list();

	if ( ViewDist==0 ) 
		ViewDist = ZOOM_DEFAULT;
	ViewMatrix = Objects[Players[Player_num].objnum].orient;

	tangles.p = PITCH_DEFAULT;
	tangles.h  = 0;
	tangles.b  = 0;

	done = 0;

	view_target = Objects[Players[Player_num].objnum].pos;

	t1 = entry_time = timer_get_fixed_seconds();
	t2 = t1;

	//Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum
	Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
	SegmentLimit = Max_segments_away;

	adjust_segment_limit(SegmentLimit);

	while(!done)	{
#ifndef MAC_SHAREWARE
		redbook_restart_track();
#endif
		
		if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME)
			leave_mode = 1;

		if ( !Controls.automap_state && (leave_mode==1) )
			done=1;

		if (!pause_game)	{
			ushort old_wiggle;

			saved_control_info = Controls;				// Save controls so we can zero them
			memset(&Controls,0,sizeof(control_info));	// Clear everything...
			old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE;	// Save old wiggle
			ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE;		// Turn off wiggle
			#ifdef NETWORK
			if (multi_menu_poll())
				done = 1;
			#endif
//			GameLoop( 0, 0 );		// Do game loop with no rendering and no reading controls.
			ConsoleObject->mtype.phys_info.flags |= old_wiggle;	// Restore wiggle
			Controls = saved_control_info;
		} 

		controls_read_all();		
		if ( Controls.automap_down_count )	{
			if (leave_mode==0)
				done = 1;
			c = 0;
		}

		while( (c=key_inkey()) )	{
			switch( c ) {
			#ifndef NDEBUG
			case KEY_BACKSP: Int3(); break;
			#endif
	
			case KEY_PRINT_SCREEN: save_screen_shot(1); break;
	
			case KEY_ESC:
				if (leave_mode==0)
					done = 1;
				 break;
			case KEY_ALTED+KEY_F:		// Alt+F shows full map, if cheats enabled
				if (Cheats_enabled) 
				{
					uint t;	
					t = Players[Player_num].flags;
					Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL_CHEAT;
					automap_build_edge_list();
					Players[Player_num].flags=t;
			 	}
				break;
	
	#ifndef NDEBUG
		  	case KEY_DEBUGGED+KEY_F: 	{
				for (i=0; i<=Highest_segment_index; i++ )
					Automap_visited[i] = 1;
				automap_build_edge_list();
				Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
				SegmentLimit = Max_segments_away;
				adjust_segment_limit(SegmentLimit);
				}
				break;
	#endif
			case KEY_MINUS:
				if (SegmentLimit > 1) 		{
					SegmentLimit--;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			case KEY_EQUAL:
				if (SegmentLimit < Max_segments_away) 	{
					SegmentLimit++;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			}
		}

		if ( Controls.fire_primary_down_count )	{
			// Reset orientation
			ViewDist = ZOOM_DEFAULT;
			tangles.p = PITCH_DEFAULT;
			tangles.h  = 0;
			tangles.b  = 0;
			view_target = Objects[Players[Player_num].objnum].pos;
		}

		ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR;

		tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR );
		tangles.h  += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR );
		tangles.b  += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 );
		
		if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time )	{
			vms_angvec	tangles1;
			vms_vector	old_vt;
			old_vt = view_target;
			tangles1 = tangles;
			vm_angles_2_matrix(&tempm,&tangles1);
			vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
			vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED );
			if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )	{
				view_target = old_vt;
			}
		} 

		vm_angles_2_matrix(&tempm,&tangles);
		vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);

		if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE;
		if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE;

		draw_automap();

		if ( first_time )	{
			first_time = 0;
			gr_palette_load( gr_palette );
		}

		t2 = timer_get_fixed_seconds();
		if (pause_game)
			FrameTime=t2-t1;
		t1 = t2;
	}

	//free(Edges);
	//free(DrawingListBright);
	gr_free_canvas(name_canv);  name_canv=NULL;

	mprintf( (0, "Automap memory freed\n" ));

	game_flush_inputs();

	if (pause_game)
		start_time();
}
示例#28
0
//	Call this once/frame to process all super mines in the level.
void process_super_mines_frame(void)
{
	objnum_t	start;
	object_step_interval_t add;

	//	If we don't know of there being any super mines in the level, just
	//	check every 8th object each frame.
	if (Super_mines_yes == 0) {
		start = objnum_t(FrameCount & 7);
		add = 8;
	} else {
		start = object_first;
		add = 1;
	}

	Super_mines_yes = 0;

	for (objnum_t i=start; i<=Highest_object_index; i+=add) {
		if ((Objects[i].type == OBJ_WEAPON) && (Objects[i].id == SUPERPROX_ID)) {
			objnum_t	parent_num;

			parent_num = Objects[i].ctype.laser_info.parent_num;

			Super_mines_yes = 1;
			if (Objects[i].lifeleft + F1_0*2 < Weapon_info[SUPERPROX_ID].lifetime) {
				vms_vector	*bombpos;

				bombpos = &Objects[i].pos;

				for (objnum_t j=object_first; j<=Highest_object_index; j++) {
					if ((Objects[j].type == OBJ_PLAYER) || (Objects[j].type == OBJ_ROBOT)) {
						fix	dist;

						dist = vm_vec_dist_quick(bombpos, &Objects[j].pos);

						if (j != parent_num)
							if (dist - Objects[j].size < F1_0*20)
							{
								if (Objects[i].segnum == Objects[j].segnum)
									Objects[i].lifeleft = 1;
								else {
									//	Object which is close enough to detonate smart mine is not in same segment as smart mine.
									//	Need to do a more expensive check to make sure there isn't an obstruction.
									if (((FrameCount ^ (i+j)) % 4) == 0) {
										fvi_query	fq;
										fvi_info		hit_data;
										int			fate;

										fq.startseg = Objects[i].segnum;
										fq.p0						= &Objects[i].pos;
										fq.p1						= &Objects[j].pos;
										fq.rad					= 0;
										fq.thisobjnum			= i;
										fq.ignore_obj_list	= NULL;
										fq.flags					= 0;

										fate = find_vector_intersection(&fq, &hit_data);
										if (fate != HIT_WALL)
											Objects[i].lifeleft = 1;
									}
								}
							}
					}
				}
			}
		}
	}

}
// Checks weapon-weapon collisions.  pair->a and pair->b are weapons.
// Returns 1 if all future collisions between these can be ignored
int collide_weapon_weapon( obj_pair * pair )
{
	float A_radius, B_radius;
	object *A = pair->a;
	object *B = pair->b;

	Assert( A->type == OBJ_WEAPON );
	Assert( B->type == OBJ_WEAPON );
	
	//	Don't allow ship to shoot down its own missile.
	if (A->parent_sig == B->parent_sig)
		return 1;

	//	Only shoot down teammate's missile if not traveling in nearly same direction.
	if (Weapons[A->instance].team == Weapons[B->instance].team)
		if (vm_vec_dot(&A->orient.vec.fvec, &B->orient.vec.fvec) > 0.7f)
			return 1;

	//	Ignore collisions involving a bomb if the bomb is not yet armed.
	weapon	*wpA, *wpB;
	weapon_info	*wipA, *wipB;

	wpA = &Weapons[A->instance];
	wpB = &Weapons[B->instance];
	wipA = &Weapon_info[wpA->weapon_info_index];
	wipB = &Weapon_info[wpB->weapon_info_index];

	A_radius = A->radius;
	B_radius = B->radius;

	// UnknownPlayer : Should we even be bothering with collision detection is neither one of these is a bomb?

	if (wipA->wi_flags & WIF_BOMB) {
		A_radius *= 2;		// Makes bombs easier to hit
		if (wipA->lifetime - wpA->lifeleft < BOMB_ARM_TIME)
			return 0;
	}

	if (wipB->wi_flags & WIF_BOMB) {
		B_radius *= 2;		// Makes bombs easier to hit
		if (wipB->lifetime - wpB->lifeleft < BOMB_ARM_TIME)
			return 0;
	}

	//	Rats, do collision detection.
	if (collide_subdivide(&A->last_pos, &A->pos, A_radius, &B->last_pos, &B->pos, B_radius)) {
		ship	*sap, *sbp;

		sap = &Ships[Objects[A->parent].instance];
		sbp = &Ships[Objects[B->parent].instance];
		// MWA -- commented out next line because it was too long for output window on occation.
		// Yes -- I should fix the output window, but I don't have time to do it now.
		//nprintf(("AI", "[%s] %s's missile %i shot down by [%s] %s's laser %i\n", lTeamNames[sbp->team], sbp->ship_name, B->instance, lTeamNames[sap->team], sap->ship_name, A->instance));
		if (wipA->wi_flags & WIF_BOMB) {
			if (wipB->wi_flags & WIF_BOMB) {		//	Two bombs collide, detonate both.
				Weapons[A->instance].lifeleft = 0.01f;
				Weapons[B->instance].lifeleft = 0.01f;
				Weapons[A->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
				Weapons[B->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
			} else {
				A->hull_strength -= wipB->damage;
				if (A->hull_strength < 0.0f) {
					Weapons[A->instance].lifeleft = 0.01f;
					Weapons[A->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
				}
			}
		} else if (wipB->wi_flags & WIF_BOMB) {
			B->hull_strength -= wipA->damage;
			if (B->hull_strength < 0.0f) {
				Weapons[B->instance].lifeleft = 0.01f;
				Weapons[B->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON;
			}
		}

		float dist = 0.0f;
		if (Weapons[A->instance].lifeleft == 0.01f) {
			dist = vm_vec_dist_quick(&A->pos, &wpA->homing_pos);
			nprintf(("AI", "Frame %i: Weapon %s shot down. Dist: %.1f, inner: %.0f, outer: %.0f\n", Framecount, wipA->name, dist, wipA->inner_radius, wipA->outer_radius));
		}
		if (Weapons[B->instance].lifeleft == 0.01f) {
			dist = vm_vec_dist_quick(&A->pos, &wpB->homing_pos);
			nprintf(("AI", "Frame %i: Weapon %s shot down. Dist: %.1f, inner: %.0f, outer: %.0f\n", Framecount, wipB->name, dist, wipB->inner_radius, wipB->outer_radius));
		}
		return 1;
	}

	return 0;
}
示例#30
0
void modex_print_message(int x, int y, char *str)
{

#ifndef AUTOMAP_DIRECT_RENDER
#ifndef AUTOMAP_NO_PAGING
	int	i;
	for (i=0; i<2; i++ )	{
		gr_set_current_canvas(&Pages[i]);
#else
	{
		gr_set_current_canvas(OffscreenPage);
#endif		
#endif
		modex_printf(x, y, str, GFONT_MEDIUM_1);
#ifndef AUTOMAP_DIRECT_RENDER
	}

	gr_set_current_canvas(&DrawingPages[current_page]);
#endif
}

extern void GameLoop(int, int );
extern int set_segment_depths(int start_seg, ubyte *segbuf);

u_int32_t automap_mode = SM(640,480);
int automap_width = 640;
int automap_height = 480;
int automap_use_game_res=0;
int nice_automap=0;

void do_automap( int key_code )	{
	int done=0;
	vms_matrix	tempm;
	vms_angvec	tangles;
	int leave_mode=0;
	int first_time=1;
//        int pcx_error;
	int c;
//        char filename[] = "MAP.PCX";
	fix entry_time;
	int pause_game=1;		// Set to 1 if everything is paused during automap...No pause during net.
	fix t1, t2;
	control_info saved_control_info;
	grs_bitmap Automap_background;
	int Max_segments_away = 0;
	int SegmentLimit = 1;
//added on 10/28/98 by adb to fix compile versions
        #if !defined (NDEBUG) || (!defined(AUTOMAP_NO_PAGING) && !defined(AUTOMAP_DIRECT_RENDER)) 
        int i;
        #endif

	key_code = key_code;	// disable warning...

	if ((Game_mode & GM_MULTI) && (Function_mode == FMODE_GAME) && (!Endlevel_sequence))
		pause_game = 0;

	if (pause_game)
		stop_time();

	create_name_canv();

	Max_edges = min(MAX_EDGES_FROM_VERTS(Num_vertices),MAX_EDGES);			//make maybe smaller than max
	//Edges	= malloc( sizeof(Edge_info)*Max_edges);
	//if ( Edges == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(Edge_info)*Max_edges/1024));
	//	return;
	//}
	//DrawingListBright = malloc( sizeof(short)*Max_edges);
	//if ( DrawingListBright == NULL )	{
	//	mprintf((0, "Couldn't get %dK for automap!", sizeof(short)*Max_edges/1024));
	//	return;
	//}

	mprintf( (0, "Num_vertices=%d, Max_edges=%d, (MAX:%d)\n", Num_vertices, Max_edges, MAX_EDGES ));
	mprintf( (0, "Allocated %d K for automap edge list\n", (sizeof(Edge_info)+sizeof(short))*Max_edges/1024 ));
	

	//edit 4/23/99 Matt Mueller - don't switch res unless we need to
	if (grd_curscreen->sc_mode != AUTOMAP_MODE)
		gr_set_mode( AUTOMAP_MODE );
	else
		gr_set_current_canvas(NULL);
	//end edit -MM
	automap_width=grd_curscreen->sc_canvas.cv_bitmap.bm_w;
	automap_height=grd_curscreen->sc_canvas.cv_bitmap.bm_h;

	gr_palette_clear();

#ifndef AUTOMAP_DIRECT_RENDER
	gr_init_sub_canvas(&Pages[0],grd_curcanv,0,0,automap_width,automap_height);
#ifndef AUTOMAP_NO_PAGING
	// NOTICE: should be 0,401! FIXME!
	gr_init_sub_canvas(&Pages[1],grd_curcanv,0,0,automap_width,automap_height);
	gr_init_sub_canvas(&DrawingPages[0],&Pages[0],0,0,automap_width,automap_height);
	gr_init_sub_canvas(&DrawingPages[1],&Pages[1],0,0,automap_width,automap_height);
#else
	OffscreenPage = gr_create_canvas( automap_width,automap_height );
	if (!OffscreenPage) {
    	nm_messagebox("No memory for automap", 1, "Ok");
	    return;
	}
	gr_init_sub_canvas(&DrawingPages[0],OffscreenPage,0,0,automap_width,automap_height);
#endif
#endif

	gr_init_bitmap_data (&Automap_background);
//	pcx_error = pcx_read_bitmap(filename,&Automap_background,BM_LINEAR,NULL);
//	if ( pcx_error != PCX_ERROR_NONE )	{
//		printf("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
//		Error("File %s - PCX error: %s",filename,pcx_errormsg(pcx_error));
//		return;
//	}

#ifndef AUTOMAP_DIRECT_RENDER
#ifndef AUTOMAP_NO_PAGING
        for (i=0; i<2; i++ )        {
		gr_set_current_canvas(&Pages[i]);
#else
	{
		gr_set_current_canvas(OffscreenPage);
#endif
//		gr_bitmap( 0, 0, &Automap_background );
//		modex_printf( 40, 22,TXT_AUTOMAP,GFONT_BIG_1);
//		modex_printf( 70,353,TXT_TURN_SHIP,GFONT_SMALL);
//		modex_printf( 70,369,TXT_SLIDE_UPDOWN,GFONT_SMALL);
//		modex_printf( 70,385,TXT_VIEWING_DISTANCE,GFONT_SMALL);
	}
#ifdef AUTOMAP_NO_PAGING
//killed 05/17/99 Matt Mueller - this seems to merely copy undefined bytes around.. not needed
//--killed--	gr_bm_ubitblt(automap_width,automap_height, 0, 0, 0, 0, &OffscreenPage->cv_bitmap,&Pages[0].cv_bitmap);
//end kill -MM
#endif
	gr_free_bitmap_data (&Automap_background);
	gr_set_current_canvas(&DrawingPages[current_page]);
#endif
	automap_build_edge_list();

	if ( ViewDist==0 ) 
		ViewDist = ZOOM_DEFAULT;
	ViewMatrix = Objects[Players[Player_num].objnum].orient;

	tangles.p = PITCH_DEFAULT;
	tangles.h  = 0;
	tangles.b  = 0;

	done = 0;

	view_target = Objects[Players[Player_num].objnum].pos;

	t1 = entry_time = timer_get_fixed_seconds();
	t2 = t1;

	//Fill in Automap_visited from Objects[Players[Player_num].objnum].segnum
	Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
	SegmentLimit = Max_segments_away;

	adjust_segment_limit(SegmentLimit);

	while(!done)	{
		if ( leave_mode==0 && Controls.automap_state && (timer_get_fixed_seconds()-entry_time)>LEAVE_TIME)
			leave_mode = 1;

		if ( !Controls.automap_state && (leave_mode==1) )
			done=1;

		if (!pause_game)	{
			ushort old_wiggle;
			saved_control_info = Controls;				// Save controls so we can zero them
			memset(&Controls,0,sizeof(control_info));	// Clear everything...
			old_wiggle = ConsoleObject->mtype.phys_info.flags & PF_WIGGLE;	// Save old wiggle
			ConsoleObject->mtype.phys_info.flags &= ~PF_WIGGLE;		// Turn off wiggle
			#ifdef NETWORK
			if (multi_menu_poll())
				done = 1;
			#endif
//			GameLoop( 0, 0 );		// Do game loop with no rendering and no reading controls.
			ConsoleObject->mtype.phys_info.flags |= old_wiggle;	// Restore wiggle
			Controls = saved_control_info;
		} 

		controls_read_all();		
		if ( Controls.automap_down_count )	{
			if (leave_mode==0)
				done = 1;
			c = 0;
		}

		while( (c=key_inkey()) )	{
			switch( c ) {
			#ifndef NDEBUG
			case KEY_BACKSP: Int3(); break;
			#endif
	
			case KEY_PRINT_SCREEN: save_screen_shot(1); break;
	
			case KEY_ESC:
				if (leave_mode==0)
					done = 1;
				 break;
			case KEY_ALTED+KEY_F:		// Alt+F shows full map, if cheats enabled
				if (Cheats_enabled) 
				{
					uint t;	
					t = Players[Player_num].flags;
					Players[Player_num].flags |= PLAYER_FLAGS_MAP_ALL_CHEAT;
					automap_build_edge_list();
					Players[Player_num].flags=t;
			 	}
				break;
	
	#ifndef NDEBUG
		  	case KEY_DEBUGGED+KEY_F: 	{
				for (i=0; i<=Highest_segment_index; i++ )
					Automap_visited[i] = 1;
				automap_build_edge_list();
				Max_segments_away = set_segment_depths(Objects[Players[Player_num].objnum].segnum, Automap_visited);
				SegmentLimit = Max_segments_away;
				adjust_segment_limit(SegmentLimit);
				}
				break;
	#endif
			case KEY_MINUS:
				if (SegmentLimit > 1) 		{
					SegmentLimit--;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			case KEY_EQUAL:
				if (SegmentLimit < Max_segments_away) 	{
					SegmentLimit++;
					adjust_segment_limit(SegmentLimit);
				}
				break;
			}
		}

		if ( Controls.fire_primary_down_count )	{
			// Reset orientation
			ViewDist = ZOOM_DEFAULT;
			tangles.p = PITCH_DEFAULT;
			tangles.h  = 0;
			tangles.b  = 0;
			view_target = Objects[Players[Player_num].objnum].pos;
		}

		ViewDist -= Controls.forward_thrust_time*ZOOM_SPEED_FACTOR;

		tangles.p += fixdiv( Controls.pitch_time, ROT_SPEED_DIVISOR );
		tangles.h  += fixdiv( Controls.heading_time, ROT_SPEED_DIVISOR );
		tangles.b  += fixdiv( Controls.bank_time, ROT_SPEED_DIVISOR*2 );
		
		if ( Controls.vertical_thrust_time || Controls.sideways_thrust_time )	{
			vms_angvec	tangles1;
			vms_vector	old_vt;
			old_vt = view_target;
			tangles1 = tangles;
			vm_angles_2_matrix(&tempm,&tangles1);
			vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);
			vm_vec_scale_add2( &view_target, &ViewMatrix.uvec, Controls.vertical_thrust_time*SLIDE_SPEED );
			vm_vec_scale_add2( &view_target, &ViewMatrix.rvec, Controls.sideways_thrust_time*SLIDE_SPEED );
			if ( vm_vec_dist_quick( &view_target, &Objects[Players[Player_num].objnum].pos) > i2f(1000) )	{
				view_target = old_vt;
			}
		} 

		vm_angles_2_matrix(&tempm,&tangles);
		vm_matrix_x_matrix(&ViewMatrix,&Objects[Players[Player_num].objnum].orient,&tempm);

		if ( ViewDist < ZOOM_MIN_VALUE ) ViewDist = ZOOM_MIN_VALUE;
		if ( ViewDist > ZOOM_MAX_VALUE ) ViewDist = ZOOM_MAX_VALUE;

		draw_automap();

		if ( first_time )	{
			first_time = 0;
			gr_palette_load( gr_palette );
		}
		t2 = timer_get_fixed_seconds();
		while (t2-t1<F1_0/100){//ogl is fast enough that the automap can read the input too fast and you start to turn really slow.  So delay a bit (and free up some cpu :)
			if (nice_automap)
				d_delay(1);

			t2 = timer_get_fixed_seconds();
		}
		if (pause_game)
			FrameTime=t2-t1;
		t1 = t2;
	}

	//free(Edges);
	//free(DrawingListBright);
	gr_free_canvas(name_canv);  name_canv=NULL;
#ifdef AUTOMAP_NO_PAGING
	gr_free_canvas(OffscreenPage);
	OffscreenPage = NULL;
#endif

	mprintf( (0, "Automap memory freed\n" ));

	game_flush_inputs();

	if (pause_game)
		start_time();
}

void adjust_segment_limit(int SegmentLimit)
{
	int i,e1;
	Edge_info * e;

	mprintf(( 0, "Seglimit: %d\n", SegmentLimit ));
	
	for (i=0; i<=Highest_edge_index; i++ )	{
		e = &Edges[i];
		e->flags |= EF_TOO_FAR;
		for (e1=0; e1<e->num_faces; e1++ )	{
			if ( Automap_visited[e->segnum[e1]] <= SegmentLimit )	{
				e->flags &= (~EF_TOO_FAR);
				break;
			}
		}
	}
	
}