Exemple #1
0
/* ----- [ check_pc ] ------------------------------------------------------- */
int check_pc(struct Var_conf *config,
	     struct model *model,
	     enum Color **piece,
	     SDL_Rect pos)
{
    int i = 0,j = 0;
    // Getting high left corner position
    int x = pos.x;
    int y = pos.y;
    // Check
    for(i = 0;i < PC_NB_HBLC;i++)
    {
    	for(j = 0;j < PC_NB_LBLC;j++)
    	{
	    // if the current bloc is not empty and
	    // not on the panel, then the position is not good
	    if(piece[i][j] != CL_MPT		&&
	       (x + j < 0 || x + j >= PNL_LB	||
	        y + i < 0 || y + i >= model_height(model))	 )
		return 0;
	    // if the current bloc is not empty
	    // the bloc is on the panel
	    // and the bloc of the model is not empty,
	    // then it is no valable position
	    if(piece[i][j] != CL_MPT	 	&& 
	       x + j >= 0			&&
	       x + j < PNL_LB 			&&
	       y + i >= 0			&&
	       y + i < model_height(model) 			&&
	       model_get(model,y + i,x + j) != CL_MPT	 )
		return 0;
	}
    }
    return 1;
}
/**
 * Page in debris bitmaps at level load
 */
void debris_page_in()
{
	uint i;

	Debris_model = model_load( NOX("debris01.pof"), 0, NULL );
	if (Debris_model >= 0)	{
		polymodel * pm;
		pm = model_get(Debris_model);
		Debris_num_submodels = pm->n_models;
	}

	Debris_vaporize_model = model_load( NOX("debris02.pof"), 0, NULL );

	for (i=0; i<Species_info.size(); i++ )
	{
		species_info *species = &Species_info[i];

		nprintf(( "Paging", "Paging in debris texture '%s'\n", species->debris_texture.filename));

		species->debris_texture.bitmap_id = bm_load(species->debris_texture.filename);
		if (species->debris_texture.bitmap_id < 0)
		{
			Warning( LOCATION, "Couldn't load species %s debris\ntexture, '%s'\n", species->species_name, species->debris_texture.filename);
		}

		bm_page_in_texture(species->debris_texture.bitmap_id);
	}
	
}
/**
 * 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);
	}
}
Exemple #4
0
// Returns which octant point pnt is in. This might return
// -1 if the point isn't in any octant.
// If model_orient and/or model_pos are NULL, pnt is assumed to already 
// be rotated into the model's local coordinates.
// If oct is not null, it will be filled in with a pointer to the octant
// data.  Or NULL if the pnt isn't in the octant.
int model_which_octant(vec3d* pnt, int model_num, matrix* model_orient, vec3d* model_pos, model_octant** oct)
{
	polymodel* pm;
	vec3d tempv, rotpnt;

	pm = model_get(model_num);

	if (model_orient && model_pos)
	{
		// First, rotate pnt into the model's frame of reference.
		vm_vec_sub(&tempv, pnt, model_pos);
		vm_vec_rotate(&rotpnt, &tempv, model_orient);
	}
	else
	{
		rotpnt = *pnt;
	}

	vec3d center;
	vm_vec_avg(&center, &pm->mins, &pm->maxs);
	int i, x, y, z;

	if (rotpnt.xyz.x > center.xyz.x)
		x = 1;
	else
		x = 0;
	if (rotpnt.xyz.y > center.xyz.y)
		y = 1;
	else
		y = 0;
	if (rotpnt.xyz.z > center.xyz.z)
		z = 1;
	else
		z = 0;

	i = (x << 2) | (y << 1) | z;

	if (point_in_octant(pm, &pm->octants[i], &rotpnt))
	{
		if (oct)
			*oct = &pm->octants[i];
		return i;
	}

	if (oct)
		*oct = NULL;

	return -1;
}
void model_collide_preprocess(matrix *orient, int model_instance_num)
{
	polymodel_instance	*pmi;
	polymodel *pm;

	pmi = model_get_instance(model_instance_num);
	pm = model_get(pmi->model_num);

	matrix current_orient = *orient;
	vec3d current_pos;

	vm_vec_zero(&current_pos);

	model_collide_preprocess_subobj(&current_pos, &current_orient, pm, pmi, pm->detail[0]);
}
// What we're doing here is projecting each object extent onto the directrix, calculating the distance between the
// projected point and the origin, and then taking the maximum distance as the semilatus rectum.  We're actually
// maintaining the square of the distance rather than the actual distance, as it's faster to calculate and it gives
// the same result in a greater-than or less-than comparison.  When we're done calculating everything for all
// objects (i.e. when we return to the parent function) we take the square root of the final value.
void dock_calc_max_semilatus_rectum_squared_parallel_to_directrix_helper(object *objp, dock_function_info *infop)
{
	vec3d world_point, local_point[6], nearest;
	polymodel *pm;
	int i;
	float temp, dist_squared;

	// line parameters
	vec3d *line_start = infop->parameter_variables.vecp_value;
	vec3d *line_end = infop->parameter_variables.vecp_value2;

	// We must find world coordinates for each of the six endpoints on the three axes of the object.  I looked up
	// which axis is front/back, left/right, and up/down, as well as which endpoint is which.  It doesn't really
	// matter, though, as all we need are the distances.

	// grab our model
	Assert(objp->type == OBJ_SHIP);
	pm = model_get(Ship_info[Ships[objp->instance].ship_info_index].model_num);

	// set up the points we want to check
	memset(local_point, 0, sizeof(vec3d) * 6);
	local_point[0].xyz.x = pm->maxs.xyz.x;	// right point (max x)
	local_point[1].xyz.x = pm->mins.xyz.x;	// left point (min x)
	local_point[2].xyz.y = pm->maxs.xyz.y;	// top point (max y)
	local_point[3].xyz.y = pm->mins.xyz.y;	// bottom point (min y)
	local_point[4].xyz.z = pm->maxs.xyz.z;	// front point (max z)
	local_point[5].xyz.z = pm->mins.xyz.z;	// rear point (min z)

	// check points
	for (i = 0; i < 6; i++)
	{
		// calculate position of point
		vm_vec_rotate(&world_point, &local_point[i], &objp->orient);
		vm_vec_add2(&world_point, &objp->pos);

		// find the nearest point along the line
		vm_vec_dist_squared_to_line(&world_point, line_start, line_end, &nearest, &temp);

		// find the distance squared between the origin of the line and the point on the line
		dist_squared = vm_vec_dist_squared(line_start, &nearest);
	
		// update with farthest distance squared
		if (dist_squared > infop->maintained_variables.float_value)
			infop->maintained_variables.float_value = dist_squared;
	}
}
Exemple #7
0
// Returns which octant point pnt is closet to. This will always return 
// a valid octant (0-7) since the point doesn't have to be in an octant.
// If model_orient and/or model_pos are NULL, pnt is assumed to already 
// be rotated into the model's local coordinates.
// If oct is not null, it will be filled in with a pointer to the octant
// data.
int model_which_octant_distant_many(vec3d* pnt, int model_num, matrix* model_orient, vec3d* model_pos, polymodel** pm,
									int* octs)
{
	vec3d tempv, rotpnt;

	*pm = model_get(model_num);

	if (model_orient && model_pos)
	{
		// First, rotate pnt into the model's frame of reference.
		vm_vec_sub(&tempv, pnt, model_pos);
		vm_vec_rotate(&rotpnt, &tempv, model_orient);
	}
	else
	{
		rotpnt = *pnt;
	}

	vec3d center;
	vm_vec_avg(&center, &((*pm)->mins), &((*pm)->maxs));
	int i, x, y, z;

	if (rotpnt.xyz.x > center.xyz.x)
		x = 1;
	else
		x = 0;
	if (rotpnt.xyz.y > center.xyz.y)
		y = 1;
	else
		y = 0;
	if (rotpnt.xyz.z > center.xyz.z)
		z = 1;
	else
		z = 0;

	i = ((x << 2) | (y << 1) | z);

	octs[0] = i;
	octs[1] = i ^ 4;	//	Adjacent octant in x dimension
	octs[2] = i ^ 2;	//	Adjacent octant in y dimension
	octs[3] = i ^ 1;	//	Adjacent octant in z dimension

	return i;
}
Exemple #8
0
void create_shield_explosion(int objnum, int model_num, matrix *orient, vec3d *centerp, vec3d *tcp, int tr0)
{
    matrix	tom;		//	Texture Orientation Matrix
    shield_info	*shieldp;
    polymodel	*pm;
    int		i;

    if (Objects[objnum].flags & OF_NO_SHIELDS)
        return;

    pm = model_get(model_num);
    Num_tris = pm->shield.ntris;
    shieldp = &pm->shield;

    if (Num_tris == 0)
        return;

    if ( (Detail.shield_effects == 1) || (Detail.shield_effects == 2) ) {
        create_shield_low_detail(objnum, model_num, orient, centerp, tcp, tr0, shieldp);
        return;
    }

    for (i=0; i<Num_tris; i++)
        shieldp->tris[i].used = 0;

    //	Compute orientation matrix from normal of surface hit.
    //	Note, this will cause the shape of the bitmap to change abruptly
    //	as the impact point moves to another triangle.  To prevent this,
    //	you could average the normals at the vertices, then interpolate the
    //	normals from the vertices to get a smoothly changing normal across the face.
    //	I had tried using the vector from the impact point to the center, which
    //	changes smoothly, but this looked surprisingly bad.
    vm_vector_2_matrix(&tom, &shieldp->tris[tr0].norm, NULL, NULL);

    //	Create the shield from the current triangle, as well as its neighbors.
    create_shield_from_triangle(tr0, orient, shieldp, tcp, centerp, Objects[objnum].radius, &tom.vec.rvec, &tom.vec.uvec);

    for (i=0; i<3; i++)
        create_shield_from_triangle(shieldp->tris[tr0].neighbors[i], orient, shieldp, tcp, centerp, Objects[objnum].radius, &tom.vec.rvec, &tom.vec.uvec);

    copy_shield_to_globals(objnum, shieldp);
}
void prevent_spawning_collision(object *new_obj)
{
	int collided;
	ship_obj *moveup;
	object *hit_check;
	ship *s_check;

	do {
		collided = 0;

		for (moveup = GET_FIRST(&Ship_obj_list); moveup != END_OF_LIST(&Ship_obj_list); moveup = GET_NEXT(moveup))
		{
			// don't check the new object itself!!
			if (moveup->objnum == OBJ_INDEX(new_obj))
				continue;

			hit_check = &Objects[moveup->objnum];

			Assert(hit_check->type == OBJ_SHIP);
			Assert(hit_check->instance >= 0);
			if ((hit_check->type != OBJ_SHIP) || (hit_check->instance < 0))
				continue;

			s_check = &Ships[hit_check->instance];
							
			// just to make sure we don't get any strange magnitude errors
			if (vm_vec_same(&hit_check->pos, &new_obj->pos))
				new_obj->pos.xyz.x += 1.0f;
							
			polymodel *pm = model_get(Ship_info[s_check->ship_info_index].model_num);
			WITHIN_BBOX();				
			if (collided)
			{
				MOVE_AWAY_BBOX();
				break;
			}
		}
	} while (collided);
}
Exemple #10
0
/* ----- [ undo_load ] ------------------------------------------------------ */
void undo_load(struct Var_conf *config, struct Undo *undo_historic)
{
    int i = 0, j = 0;
    struct Undo_i *del = NULL;

    if(undo_historic->counter > 0)
    {
	// Get historic
	del = undo_historic->first;

        // Copy model
	for(i = 0;i < PNL_HB;i++)
	    for(j = 0;j < PNL_LB;j++)
	        model_set(config->model,i,j,model_get(del->model,i,j));

	// Copy piece
        config->pc_next_id = config->pc_cur_id;
	config->pc_cur_id = del->piece;

	// Copy level and score
	config->level = del->level;
	config->score = del->score;
	config->lines = del->lines;

        // Restart position
	config->piece_pos.x = (PNL_LB / 2) - (PC_NB_LBLC / 2);
        config->piece_pos.y = 1;

	// Update references
        undo_historic->first = del->prev;
        if(--(undo_historic->counter) > 0)
	    del->prev->next = NULL;

	// Free historic
        undo_free_historic(config,del);
    }
}
Exemple #11
0
void multi_respawn_place(object *new_obj, int team)
{
	ship_obj *moveup;
	ship *s_check;
	ship *pri = NULL;
	object *pri_obj = NULL;
	object *hit_check;
	int collided, idx, lookup;

	// first determine if there are any appropriate priority ships to use
	pri = NULL;
	pri_obj = NULL;
	for(idx=0; idx<Multi_respawn_priority_count; idx++){
		// all relevant ships
		if((Multi_respawn_priority_ships[idx].team == team) || !(Netgame.type_flags & NG_TYPE_TEAM)){

			lookup = ship_name_lookup(Multi_respawn_priority_ships[idx].ship_name);
			if( (lookup >= 0) && ((pri == NULL) || (Ships[lookup].respawn_priority > pri->respawn_priority)) && (Ships[lookup].objnum >= 0) && (Ships[lookup].objnum < MAX_OBJECTS)){
				pri = &Ships[lookup];
				pri_obj = &Objects[Ships[lookup].objnum];
			}
		}
	}
	
	// if we have a relevant respawn ship
	if((pri != NULL) && (pri_obj != NULL)){
		// pick a point just outside his bounding box
		polymodel *pm = model_get(pri->modelnum); 

		// hmm, ugly. Pick a point 2000 meters to the y direction
		if(pm == NULL){			
			vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.rvec, 2000.0f);
		} else {
			// pick a random direction
			int d = (int)frand_range(0.0f, 5.9f);
			switch(d){
			case 0:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.rvec, (pm->maxs.xyz.x - pm->mins.xyz.x)); 
				break;

			case 1:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.rvec, -(pm->maxs.xyz.x - pm->mins.xyz.x));
				break;

			case 2:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.uvec, (pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 3:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 4:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.fvec, (pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			case 5:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.fvec, -(pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			default:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.v.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;
			}
		}
	}
	// otherwise, resort to plain respawn points
	else {
		Assert(Multi_respawn_point_count > 0);
		
		// get the next appropriate respawn point by team
		lookup = 0;		
		int count = 0;
		while(!lookup && (count < 13)){
			if((team == TEAM_TRAITOR) || (team == Multi_respawn_points[Multi_next_respawn_point].team)){
				lookup = 1;
			}			

			// next item
			if(!lookup){
				if(Multi_next_respawn_point >= (Multi_respawn_point_count-1)){
					Multi_next_respawn_point = 0;
				} else {
					Multi_next_respawn_point++;
				}				
			}

			count++;
		}

		// set respawn info
		new_obj->pos = Multi_respawn_points[Multi_next_respawn_point].pos;		
	}

	// now make sure we're not colliding with anyone		
	do {
		collided = 0;
		moveup = GET_FIRST(&Ship_obj_list);
		while(moveup!=END_OF_LIST(&Ship_obj_list)){
			// don't check the new_obj itself!!
			if(Objects[moveup->objnum].net_signature != new_obj->net_signature){
				hit_check = &Objects[moveup->objnum];
				Assert(hit_check->type == OBJ_SHIP);
				Assert(hit_check->instance >= 0);
				if((hit_check->type != OBJ_SHIP) || (hit_check->instance < 0)){
					continue;
				}
				s_check = &Ships[hit_check->instance];
				
				// just to make sure we don't get any strange magnitude errors
				if(vm_vec_same(&hit_check->pos, &new_obj->pos)){
					new_obj->pos.xyz.x += 1.0f;
				}
				
				WITHIN_BBOX();				
				if(collided){						
					MOVE_AWAY_BBOX();
					break;
				} 
				collided = 0;
			}
			moveup = GET_NEXT(moveup);
		}
	} while(collided);   		
}
Exemple #12
0
BOOL CShipTexturesDlg::OnInitDialog() 
{	
	int i, j, k, z, duplicate;
	char *p = NULL;
	char texture_file[MAX_FILENAME_LEN];
	CComboBox *box;

	// get our model
	polymodel *pm = model_get(Ship_info[Ships[self_ship].ship_info_index].model_num);

	// empty old and new fields
	texture_count = 0;
	for (i=0; i<MAX_REPLACEMENT_TEXTURES; i++)
	{
		*old_texture_name[i] = 0;
		*new_texture_name[i] = 0;
	}

	// set up pointer to combo box
	box = (CComboBox *) GetDlgItem(IDC_OLD_TEXTURE_LIST);
	box->ResetContent();

	// look for textures to populate the combo box
	for (i=0; i<pm->n_textures; i++)
	{
		for(j = 0; j < TM_NUM_TYPES; j++)
		{
			// get texture file name
			bm_get_filename(pm->maps[i].textures[j].GetOriginalTexture(), texture_file);

			// skip blank textures
			if (!strlen(texture_file))
				continue;

			// get rid of file extension
			p = strchr( texture_file, '.' );
			if ( p )
			{
				//mprintf(( "ignoring extension on file '%s'\n", texture_file ));
				*p = 0;
			}

			// check for duplicate textures in list
			duplicate = -1;
			for (k=0; k<texture_count; k++)
			{
				if (!stricmp(old_texture_name[k], texture_file))
				{
					duplicate = k;
					break;
				}
			}

			if (duplicate >= 0)
				continue;

			// make old texture lowercase
			strlwr(texture_file);

			// now add it to the box
			z = box->AddString(texture_file);

			// and add it to the field as well
			strcpy_s(old_texture_name[texture_count], texture_file);

			// increment
			texture_count++;

			// sort
			sort_textures();
		}
	}

	// now look for new textures
	k=0;
	while (k < Fred_num_texture_replacements)
	{
		if (!stricmp(Ships[self_ship].ship_name, Fred_texture_replacements[k].ship_name))
		{
			// look for corresponding old texture
			for (i=0; i<texture_count; i++)
			{
				// if match
				if (!stricmp(old_texture_name[i], Fred_texture_replacements[k].old_texture))
				{
					// assign new texture
					strcpy_s(new_texture_name[i], Fred_texture_replacements[k].new_texture);

					// we found one, so no more to check
					break;
				}
			}
		}

		k++;	// increment down the list of texture replacements
	}
	// end of new texture check

	// set indexes and flags
	m_old_texture_list = 0;
	active_texture_index = 0;
	modified = 0;

	// display new texture, if we have one
	m_new_texture = CString(new_texture_name[0]);

	CDialog::OnInitDialog();
	UpdateData(FALSE);
 
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}
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->flags & SF_ARRIVING ) return 0;

	// if one object is a capital, only check player and player weapons with
	// the capital -- too slow for now otherwise.
//	if ( Polygon_models[Ships[num].modelnum].use_grid && !( (other_objp == Player_obj) || (&Objects[other_objp->parent] == Player_obj)) )
//		return 0;

	//	If either of these objects doesn't get collision checks, abort.
	if (Ship_info[shipp->ship_info_index].flags & SIF_NO_COLLIDE)
		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);
	}
	
	ship_model_start(ship_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

	// set up collision structs
	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;
	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.

	// set flags
	mc_shield.flags = MC_CHECK_SHIELD;
	mc_hull.flags = MC_CHECK_MODEL;

	// check both kinds of collisions
	int shield_collision = (pm->shield.ntris > 0) ? model_collide(&mc_shield) : 0;
	int hull_collision = model_collide(&mc_hull);

	// check shields for impact
	if (!(ship_objp->flags & OF_NO_SHIELDS))
	{
		// pick out the shield quadrant
		if (shield_collision)
			quadrant_num = get_quadrant(&mc_shield.hit_point);
		else if (hull_collision && (sip->flags2 & SIF2_SURFACE_SHIELDS))
			quadrant_num = get_quadrant(&mc_hull.hit_point);

		// make sure that the shield is active in that quadrant
		if ((quadrant_num >= 0) && ((shipp->flags & SF_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 (shield_collision)
				add_shield_point(OBJ_INDEX(ship_objp), mc_shield.shield_hit_tri, &mc_shield.hit_point);
			else
				/* TODO */;

			// 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_flags2 & WIF2_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;
	}


	//nprintf(("AI", "Frame %i, Hit tri = %i\n", Framecount, mc.shield_hit_tri));
	ship_model_stop(ship_objp);

	// 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 )
	{
		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) {
			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);

		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");
		/*
		if(!Script_system.IsOverride(wip->sc_collide_ship)) {
			ship_weapon_do_hit_stuff(ship_objp, weapon_objp, &mc.hit_point_world, &mc.hit_point, quadrant_num, mc.hit_submodel, mc.hit_normal);
		}

		if(wip->sc_collide_ship.IsValid()) {
			ade_odata lua_self_obj = l_Weapon.Set(object_h(weapon_objp));
			ade_odata lua_ship_obj = l_Ship.Set(object_h(ship_objp));
			
			Script_system.SetHookVar("Self", 'o', &lua_self_obj);
			Script_system.SetHookVar("Ship", 'o', &lua_ship_obj);

			Script_system.RunBytecode(wip->sc_collide_ship);

			Script_system.RemHookVar("Self");
			Script_system.RemHookVar("Ship");
		}*/
	}
	else if ((Missiontime - wp->creation_time > F1_0/2) && (wip->wi_flags & WIF_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->flags2 & SF2_DONT_COLLIDE_INVIS)) {
					wp->lifeleft = 0.001f;
					if (ship_objp == Player_obj)
						nprintf(("Jim", "Frame %i: Weapon %i set to detonate, dist = %7.3f.\n", Framecount, OBJ_INDEX(weapon_objp), dist));
					valid_hit_occurred = 1;
				}
			}

		}
	}

	return valid_hit_occurred;
}
Exemple #14
0
/* ----- [ ai_score_pos ] --------------------------------------------------- */
int ai_score_pos(struct Var_conf *config,
				 struct model *model,
				 enum Piece_bloc piece_id,
				 SDL_Rect position)
{
    int score = 0;
    int k = 0, l = 0;
    int sum = 0, lines = 0;
    SDL_Rect pos;
    pos.x = position.x;
    pos.y = position.y;

    // Check if position is right
    if(!check_pc(config,model,config->pieces[piece_id],pos))
    {
	score -= 16*PNL_LB;
	return score;
    }
    // Get dropped position
    while(check_pc(config,model,config->pieces[piece_id],pos)
	  && pos.y != PNL_HB)
	pos.y++;
    pos.y--;
    // Check holes
    for(k = 0;k < PC_NB_LBLC;k++)
    {
	l = PC_NB_HBLC-1;
	while(l >= 0 && config->pieces[piece_id][l][k] == CL_MPT) l--;
	if(l <= -1) continue;
	else
	{
	    // Holes
	    if((pos.x+k >= 0 && pos.x+k < PNL_LB &&
		pos.y+l+1 >= 0 && pos.y+l+1 < PNL_HB)
	       && (model_get(model,pos.y+l+1,pos.x+k) == CL_MPT))
		score -= 72;
	}
    }
    // Check lines
    lines = 0;
    for(k = 0;k < PC_NB_HBLC;k++)
    {
	sum = 0;
	for(l = 0;l < PNL_LB;l++)
	    if((pos.y+k >= 0 && pos.y+k < PNL_HB) &&
		(model_get(model,pos.y+k,l) != CL_MPT
	     || (l-pos.x >= 0 && l-pos.x < PC_NB_LBLC 
			 && config->pieces[piece_id][k][l-pos.x] != CL_MPT)))
		sum++;
	// Lines
	if(sum >= PNL_LB) lines++;
    }
    score += lines*lines*PNL_LB;
    // Height is very bad
    score += 4*pos.y;

	// Try to reduce height variance
	int i = 0, j = 0;
	int min_height = -1;
	int max_height = PNL_HB + 1;
	int sum_height = 0;
	int mean_height = 0;
	int heights[(int)PNL_LB];
	// Compute mean
	for(i = 0;i < PNL_LB;i++) {
		for(j = 0;j < PNL_HB;j++) {
			if(	model_get(model,i,j) != CL_MPT
				|| (pos.y <= j && j < pos.y + PC_NB_HBLC &&
					pos.x <= i && i < pos.x + PC_NB_LBLC &&
					config->pieces[piece_id][j - pos.y][i - pos.x] != CL_MPT)) {
				heights[i] = j;
				sum_height += j;
				break;
			}
		}
		// If end reached, current height not yet taken into account
		if(j == PNL_HB) {
			heights[i] = j;
			sum_height += PNL_HB;
		}
	}
	mean_height = sum_height / PNL_LB;
	// Compute variance
	int var_height = 0;
	for(i = 0;i < PNL_LB;i++) {
		var_height += (heights[i] - mean_height) * (heights[i] - mean_height);
	}
	score -= 4 * var_height;

    return score;
}
Exemple #15
0
/* ----- [ ai_best_pos ] ---------------------------------------------------- */
void ai_best_pos(struct Var_conf *config,struct model *model_tmp,
				 SDL_Rect *position, int *turning)
{
    enum Piece_bloc piece_id = config->pc_cur_id;
    enum Piece_bloc piece_next_id = config->pc_next_id;
    SDL_Rect pos;
    SDL_Rect next_pos;
    int score_tmp;
    int i = 0, j = 0, k = 0, l = 0;
    int sum = 0;
    int max_score = 0;
    // Init table of scores
    int scores[4*4][((int)PNL_LB+4)*((int)PNL_LB+4)];
    for(i = 0;i < 4*4;i++)
		for(j = 0;j < (PNL_LB+4)*(PNL_LB+4);j++)
	    	scores[i][j] = 0;
    // Init position
    pos.x = 0;
    pos.y = config->piece_pos.y;

    // Checking each configuration
    //	    checking each position
    //		checking holes
    //		checking lines
    //	    checking each rotation
    //		checking holes
    //		checking lines
    for(i = 0;i < 4;i++)
    {
	for(j = 0;j < PNL_LB+4;j++)
	{
	    // Update position
	    pos.x = j-4;
	    pos.y = config->piece_pos.y;

	    score_tmp = ai_score_pos(config,model_tmp,piece_id,pos);

	    for(k = 0;k < 4;k++)
		for(l = 0;l < PNL_LB+4;l++)
		    scores[i*4+k][(int)(j*(PNL_LB+4)+l)] = score_tmp;

	    // Get dropped position
	    if(check_pc(config,model_tmp,config->pieces[piece_id],pos))
	    {
		while(check_pc(config,model_tmp,config->pieces[piece_id],pos)
		      && pos.y != PNL_HB)
		    pos.y++;
		    pos.y--;

		// Take off piece in temporary model
		takeoff(config,model_tmp,&piece_id,pos,0);

		// Remove lines
		remove_lines(config,model_tmp,0);

		// Get next piece
		piece_next_id = config->pc_next_id;

		// For all turns
		for(k = 0;k < 4;k++)
		{
		    // For all positions
		    for(l = 0;l < (PNL_LB+4);l++)
		    {
			// Get new position
			next_pos.x = l-4;
			next_pos.y = 1;

			// Calculate score for new piece position
			score_tmp = ai_score_pos(config,model_tmp,
						 piece_next_id,next_pos);
			scores[i*4+k][(int)(j*(PNL_LB+4)+l)] += score_tmp;
		    }
		    // Turn new piece
		    next_pos.x = config->piece_pos.x;
		    turn(config,model_tmp,&piece_next_id,&next_pos,HORLO,0,0);
		}

		// Copy model
		for(k = 0;k < PNL_HB;k++)
		    for(l = 0;l < PNL_LB;l++)
		    model_set(model_tmp,k,l,model_get(config->model,k,l));
	    }
	}

	// Turn
	turn(config,model_tmp,&piece_id,&(config->piece_pos),
	     HORLO,0,0);    
    }

    // Get best position
    pos.x = 0;
    *turning = 0;
    max_score = scores[0][0];
    for(i = 0;i < 4;i++)
    {
	for(j = 0;j < PNL_LB+4;j++)
	{
	    for(k = 0;k < 4;k++)
		for(l = 0;l < (PNL_LB+4);l++)
		//printf("%d ",scores[i][j]);
		if(scores[i*4+k][(int)(j*(PNL_LB+4)+l)] > max_score)
		{
		    max_score = scores[i*4+k][(int)(j*(PNL_LB+4)+l)];
		    pos.x = j-4;
		    *turning = i;
		}
	}
	//printf("\n");
    }

    // Print scores table
    /*for(i = 0;i < 4;i++)
    {
	for(j = 0;j < PNL_LB+4;j++)
	{
	    for(k = 0;k < 4;k++)
	    {
		for(l = 0;l < PNL_LB+4;l++)
		{
		    if( 3 < j & j < 10) printf("%d ",scores[i*4+k][(int)(j*(PNL_LB+4)+l)]);
		}
		if( 3 < j & j < 10) printf("\n");
	    }
	    if( 3 < j & j < 10) printf("\n\n");
	}
	if( 3 < j & j < 10) printf("\n\n");
    }*/
    position->x = pos.x;
    //printf("i = %d j = %d \n",pos->x,*turning);
}
Exemple #16
0
void camera::get_info(vec3d *position, matrix *orientation)
{
	if(position == NULL && orientation == NULL)
		return;
	
	eye* eyep = NULL;
	vec3d host_normal;
	//POSITION
	if(!(flags & CAM_STATIONARY_POS) || object_host.IsValid())
	{
		c_pos = vmd_zero_vector;

		vec3d pt;
		pos_x.get(&pt.xyz.x, NULL);
		pos_y.get(&pt.xyz.y, NULL);
		pos_z.get(&pt.xyz.z, NULL);

		if(object_host.IsValid())
		{
			object *objp = object_host.objp;
			int model_num = object_get_model(objp);
			polymodel *pm = NULL;
			
			if(model_num > -1)
			{
				pm = model_get(model_num);
			}

			if(object_host_submodel < 0 || pm == NULL)
			{
				vm_vec_unrotate(&c_pos, &pt, &object_host.objp->orient);
				vm_vec_add2(&c_pos, &object_host.objp->pos);
			}
			else
			{
				eyep = get_submodel_eye(pm, object_host_submodel);
				if(eyep)
				{
					vec3d c_pos_in;
					find_submodel_instance_point_normal( &c_pos_in, &host_normal, objp, eyep->parent, &eyep->pnt, &eyep->norm);
					vm_vec_unrotate(&c_pos, &c_pos_in, &objp->orient);
					vm_vec_add2(&c_pos, &objp->pos);
				}
				else
				{
					model_find_world_point( &c_pos, &pt, pm->id, object_host_submodel, &objp->orient, &objp->pos );
				}
			}
		}
		else
		{
			c_pos = pt;
		}

		//Do custom position stuff, if needed
		if(func_custom_position != NULL && !eyep)
		{
			func_custom_position(this, &c_pos);
		}
	}

	if(position != NULL)
		*position = c_pos;

	//ORIENTATION
	if(orientation != NULL)
	{
		bool target_set = false;
		if(!(flags & CAM_STATIONARY_ORI) || object_target.IsValid() || object_host.IsValid())
		{
			if(object_target.IsValid())
			{
				object *objp = object_target.objp;
				int model_num = object_get_model(objp);
				polymodel *pm = NULL;
				vec3d target_pos = vmd_zero_vector;
				
				//See if we can get the model
				if(model_num > -1)
				{
					pm = model_get(model_num);
				}

				//If we don't have a submodel or don't have the model use object pos
				//Otherwise, find the submodel pos as it is rotated
				if(object_target_submodel < 0 || pm == NULL)
				{
					target_pos = objp->pos;
				}
				else
				{
					model_find_world_point( &target_pos, &vmd_zero_vector, pm->id, object_target_submodel, &objp->orient, &objp->pos );
				}

				vec3d targetvec;
				vm_vec_normalized_dir(&targetvec, &target_pos, &c_pos);
				vm_vector_2_matrix(&c_ori, &targetvec, NULL, NULL);
				target_set = true;
			}
			else if(object_host.IsValid())
			{
				if(eyep)
				{
					vm_vector_2_matrix(&c_ori, &host_normal, vm_vec_same(&host_normal, &object_host.objp->orient.vec.uvec)?NULL:&object_host.objp->orient.vec.uvec, NULL);
					target_set = true;
				}
				else
				{
					c_ori = object_host.objp->orient;
				}
			}
			else
			{
				c_ori = vmd_identity_matrix;
			}

			matrix mtxA = c_ori;
			matrix mtxB = IDENTITY_MATRIX;
			float pos = 0.0f;
			for(int i = 0; i < 9; i++)
			{
				ori[i].get(&pos, NULL);
				mtxB.a1d[i] = pos;
			}
			vm_matrix_x_matrix(&c_ori, &mtxA, &mtxB);

			vm_orthogonalize_matrix(&c_ori);
		}
		//Do custom orientation stuff, if needed
		if(func_custom_orientation != NULL && !target_set)
		{
			func_custom_orientation(this, &c_ori);
		}
		*orientation = c_ori;
	}
}
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;
}
// See model.h for usage.   I don't want to put the
// usage here because you need to see the #defines and structures
// this uses while reading the help.   
int model_collide(mc_info *mc_info_obj)
{
	Mc = mc_info_obj;

	MONITOR_INC(NumFVI,1);

	Mc->num_hits = 0;				// How many collisions were found
	Mc->shield_hit_tri = -1;	// Assume we won't hit any shield polygons
	Mc->hit_bitmap = -1;
	Mc->edge_hit = 0;

	if ( (Mc->flags & MC_CHECK_SHIELD) && (Mc->flags & MC_CHECK_MODEL) )	{
		Error( LOCATION, "Checking both shield and model!\n" );
		return 0;
	}

	//Fill in some global variables that all the model collide routines need internally.
	Mc_pm = model_get(Mc->model_num);
	Mc_orient = *Mc->orient;
	Mc_base = *Mc->pos;
	Mc_mag = vm_vec_dist( Mc->p0, Mc->p1 );
	Mc_edge_time = FLT_MAX;

	if ( Mc->model_instance_num >= 0 ) {
		Mc_pmi = model_get_instance(Mc->model_instance_num);
	} else {
		Mc_pmi = NULL;
	}

	// DA 11/19/98 - disable this check for rotating submodels
	// Don't do check if for very small movement
//	if (Mc_mag < 0.01f) {
//		return 0;
//	}

	float model_radius;		// How big is the model we're checking against
	int first_submodel;		// Which submodel gets returned as hit if MC_ONLY_SPHERE specified

	if ( (Mc->flags & MC_SUBMODEL) || (Mc->flags & MC_SUBMODEL_INSTANCE) )	{
		first_submodel = Mc->submodel_num;
		model_radius = Mc_pm->submodel[first_submodel].rad;
	} else {
		first_submodel = Mc_pm->detail[0];
		model_radius = Mc_pm->rad;
	}

	if ( Mc->flags & MC_CHECK_SPHERELINE ) {
		if ( Mc->radius <= 0.0f ) {
			Warning(LOCATION, "Attempting to collide with a sphere, but the sphere's radius is <= 0.0f!\n\n(model file is %s; submodel is %d, mc_flags are %d)", Mc_pm->filename, first_submodel, Mc->flags);
			return 0;
		}

		// Do a quick check on the Bounding Sphere
		if (fvi_segment_sphere(&Mc->hit_point_world, Mc->p0, Mc->p1, Mc->pos, model_radius+Mc->radius) )	{
			if ( Mc->flags & MC_ONLY_SPHERE )	{
				Mc->hit_point = Mc->hit_point_world;
				Mc->hit_submodel = first_submodel;
				Mc->num_hits++;
				return (Mc->num_hits > 0);
			}
			// continue checking polygons.
		} else {
			return 0;
		}
	} else {
		int r;

		// Do a quick check on the Bounding Sphere
		if ( Mc->flags & MC_CHECK_RAY ) {
			r = fvi_ray_sphere(&Mc->hit_point_world, Mc->p0, Mc->p1, Mc->pos, model_radius);
		} else {
			r = fvi_segment_sphere(&Mc->hit_point_world, Mc->p0, Mc->p1, Mc->pos, model_radius);
		}
		if (r) {
			if ( Mc->flags & MC_ONLY_SPHERE ) {
				Mc->hit_point = Mc->hit_point_world;
				Mc->hit_submodel = first_submodel;
				Mc->num_hits++;
				return (Mc->num_hits > 0);
			}
			// continue checking polygons.
		} else {
			return 0;
		}

	}

	if ( Mc->flags & MC_SUBMODEL )	{
		// Check only one subobject
		mc_check_subobj( Mc->submodel_num );
		// Check submodel and any children
	} else if (Mc->flags & MC_SUBMODEL_INSTANCE) {
		mc_check_subobj(Mc->submodel_num);
	} else {
		// Check all the the highest detail model polygons and subobjects for intersections

		// Don't check it or its children if it is destroyed
		if (!Mc_pm->submodel[Mc_pm->detail[0]].blown_off)	{	
			mc_check_subobj( Mc_pm->detail[0] );
		}
	}


	//If we found a hit, then rotate it into world coordinates	
	if ( Mc->num_hits )	{
		if ( Mc->flags & MC_SUBMODEL )	{
			// If we're just checking one submodel, don't use normal instancing to find world points
			vm_vec_unrotate(&Mc->hit_point_world, &Mc->hit_point, Mc->orient);
			vm_vec_add2(&Mc->hit_point_world, Mc->pos);
		} else {
			if ( Mc_pmi ) {
				model_instance_find_world_point(&Mc->hit_point_world, &Mc->hit_point, Mc->model_instance_num, Mc->hit_submodel, Mc->orient, Mc->pos);
			} else {
				model_find_world_point(&Mc->hit_point_world, &Mc->hit_point, Mc->model_num, Mc->hit_submodel, Mc->orient, Mc->pos);
			}
		}
	}


	return Mc->num_hits;

}
Exemple #19
0
void ship_draw_shield( object *objp)
{
    int		model_num;
    int		i;
    vec3d	pnt;
    polymodel * pm;

    if (objp->flags & OF_NO_SHIELDS)
        return;

    Assert(objp->instance >= 0);

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

    if ( Fred_running ) return;

    pm = model_get(model_num);

    if (pm->shield.ntris<1) return;

    //	Scan all the triangles in the mesh.
    for (i=0; i<pm->shield.ntris; i++ )	{
        int		j;
        vec3d	gnorm, v2f, tri_point;
        vertex prev_pnt, pnt0;
        shield_tri *tri;

        tri = &pm->shield.tris[i];

        if (i == Break_value)
            Int3();

        //	Hack! Only works for object in identity orientation.
        //	Need to rotate eye position into object's reference frame.
        //	Only draw facing triangles.
        vm_vec_rotate(&tri_point, &pm->shield.verts[tri->verts[0]].pos, &Eye_matrix);
        vm_vec_add2(&tri_point, &objp->pos);

        vm_vec_sub(&v2f, &tri_point, &Eye_position);
        vm_vec_unrotate(&gnorm, &tri->norm, &objp->orient);

        if (vm_vec_dot(&gnorm, &v2f) < 0.0f) {
            int	intensity;

            intensity = (int) (Ships[objp->instance].shield_integrity[i] * 255);

            if (intensity < 0)
                intensity = 0;
            else if (intensity > 255)
                intensity = 255;

            gr_set_color(0, 0, intensity);

            //	Process the vertices.
            //	Note this rotates each vertex each time it's needed, very dumb.
            for (j=0; j<3; j++ )	{
                vertex tmp;

                // Rotate point into world coordinates
                vm_vec_unrotate(&pnt, &pm->shield.verts[tri->verts[j]].pos, &objp->orient);
                vm_vec_add2(&pnt, &objp->pos);

                // Pnt is now the x,y,z world coordinates of this vert.
                // For this example, I am just drawing a sphere at that
                // point.
                g3_rotate_vertex(&tmp, &pnt);

                if (j)
                    g3_draw_line(&prev_pnt, &tmp);
                else
                    pnt0 = tmp;
                prev_pnt = tmp;
            }

            g3_draw_line(&pnt0, &prev_pnt);
        }
    }
}
Exemple #20
0
/* ----- [ remove_lines ] --------------------------------------------------- */
int remove_lines(struct Var_conf *config,struct model *model, int blink)
{
	int height = model_height(model);
    int *lines = malloc(sizeof(int) * height);
    int i = 0, j = 0, k = 0, sum = 0;

    for(i = 0;i < height;i++)
	lines[i] = 0;

    // Check full lines
    for(i = 0;i < height;i++)
    {
	sum = 0;
	for(j = 0;j < PNL_LB;j++)
	    if(model_get(model,i,j) != CL_MPT) sum++;
	if(sum == PNL_LB) lines[i] = 1;
    }

    // Count lines to remove
    sum = 0;
    for(i = 0;i < height;i++) if(lines[i]) sum++;

    if(blink)
    {
	// Blink lines
	for(k = 0;k < LN_NBCLIC * 2;k++)
	{
	    for(i = 0;i < height;i++)
	    {
		for(j = 0;j < PNL_LB;j++)
		{
		    if(lines[i])
			model_set(model,i,j,((model_get(model,i,j) != CL_MPT) ?
						    CL_MPT : CL_GREY1));
		}
		
		SDL_Delay(LN_DELAY);
	    }
	    disp_gamepanel(config);
	}
    }

    // Delete lines
    for(i = 0;i < height;i++)
    {
        if(lines[i])
        {
			for(j = 0;j < PNL_LB;j++)
			{
				for(k = i;k > 0;k--)
				{
					model_set(model,k,j,model_get(model,k - 1,j));
				}
				model_set(model,0,j,CL_MPT);
			}
		}
    }
    free(lines);

	if(ENABLE_DYNPNL)
	{
		int r = 0;
		for(r = 0;r < sum && model_height(config->model) > PNL_HB;r++)
			model_remove_first(config->model,CL_MPT);
	}

    return sum;
}
void multi_respawn_place(object *new_obj, int team)
{
	ship *pri = NULL;
	object *pri_obj = NULL;
	int idx, lookup;

	// first determine if there are any appropriate priority ships to use
	pri = NULL;
	pri_obj = NULL;
	for(idx=0; idx<Multi_respawn_priority_count; idx++){
		// all relevant ships
		if((Multi_respawn_priority_ships[idx].team == team) || !(Netgame.type_flags & NG_TYPE_TEAM)){

			lookup = ship_name_lookup(Multi_respawn_priority_ships[idx].ship_name);
			if( (lookup >= 0) && ((pri == NULL) || (Ships[lookup].respawn_priority > pri->respawn_priority)) && (Ships[lookup].objnum >= 0) && (Ships[lookup].objnum < MAX_OBJECTS)){
				pri = &Ships[lookup];
				pri_obj = &Objects[Ships[lookup].objnum];
			}
		}
	}
	
	// if we have a relevant respawn ship
	if((pri != NULL) && (pri_obj != NULL)){
		// pick a point just outside his bounding box
		polymodel *pm = model_get(Ship_info[pri->ship_info_index].model_num); 

		// hmm, ugly. Pick a point 2000 meters to the y direction
		if(pm == NULL){			
			vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.rvec, 2000.0f);
		} else {
			// pick a random direction
			int d = (int)frand_range(0.0f, 5.9f);
			switch(d){
			case 0:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.rvec, (pm->maxs.xyz.x - pm->mins.xyz.x)); 
				break;

			case 1:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.rvec, -(pm->maxs.xyz.x - pm->mins.xyz.x)); 
				break;

			case 2:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.uvec, (pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 3:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;

			case 4:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.fvec, (pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			case 5:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.fvec, -(pm->maxs.xyz.z - pm->mins.xyz.z)); 
				break;

			default:
				vm_vec_scale_add(&new_obj->pos, &pri_obj->pos, &pri_obj->orient.vec.uvec, -(pm->maxs.xyz.y - pm->mins.xyz.y)); 
				break;
			}
		}
	}
	// otherwise, resort to plain respawn points
	else {
		Assert(Multi_respawn_point_count > 0);
		
		// get the next appropriate respawn point by team
		lookup = 0;		
		int count = 0;
		while(!lookup && (count < 13)){
			if((team == Iff_traitor) || (team == Multi_respawn_points[Multi_next_respawn_point].team)){
				lookup = 1;
			}			

			// next item
			if(!lookup){
				if(Multi_next_respawn_point >= (Multi_respawn_point_count-1)){
					Multi_next_respawn_point = 0;
				} else {
					Multi_next_respawn_point++;
				}				
			}

			count++;
		}

		// set respawn info
		new_obj->pos = Multi_respawn_points[Multi_next_respawn_point].pos;		
	}

	// now make sure we're not colliding with anyone
	prevent_spawning_collision(new_obj);
}
void HudGaugeReticle::getFirepointStatus() {
	//First, get the player ship
	ship_info* sip;
	ship* shipp;
	polymodel* pm;

	Assert(Objects[Player->objnum].type == OBJ_SHIP);

	if (Objects[Player->objnum].type == OBJ_SHIP) {
		shipp = &Ships[Objects[Player->objnum].instance];
		sip = &Ship_info[shipp->ship_info_index];
	
		//Get the player eyepoint
		pm = model_get(sip->model_num);

		if (pm->n_view_positions == 0) {
			mprintf(("Model %s does not have a defined eyepoint. Firepoint display could not be generated\n", pm->filename));
		} else  {
			if (pm->n_guns > 0) {
				eye eyepoint = pm->view_positions[shipp->current_viewpoint];
				vec2d ep = { eyepoint.pnt.xyz.x, eyepoint.pnt.xyz.y };

				for (int i = 0; i < pm->n_guns; i++) {
					int bankactive = 0;
					ship_weapon *swp = &shipp->weapons;

					if (!timestamp_elapsed(shipp->weapons.next_primary_fire_stamp[i]))
						bankactive = 1;
					else if (timestamp_elapsed(shipp->weapons.primary_animation_done_time[i]))
						bankactive = 1;
					else if (i == shipp->weapons.current_primary_bank || shipp->flags[Ship::Ship_Flags::Primary_linked])
						bankactive = 2;

					int num_slots = pm->gun_banks[i].num_slots;
					for (int j = 0; j < num_slots; j++) {
						int fpactive = bankactive;

						if (sip->flags[Ship::Info_Flags::Dyn_primary_linking]) {
							// If this firepoint is not among the next shot(s) to be fired, dim it one step
							if ( !( (j >= (shipp->last_fired_point[i]+1) % num_slots) && (j <= (shipp->last_fired_point[i]+swp->primary_bank_slot_count[i]) % num_slots) ) ) {
								fpactive--;
							}
						} else if (Weapon_info[swp->primary_bank_weapons[i]].wi_flags[Weapon::Info_Flags::Cycle]) {
							// If this firepoint is not the next one to be fired, dim it one step
							if (j != (shipp->last_fired_point[i]+1) % num_slots) {
								fpactive--;
							}
						}

						vec3d fpfromeye;

						matrix eye_orient, player_transpose;

						vm_copy_transpose(&player_transpose, &Objects[Player->objnum].orient);
						vm_matrix_x_matrix(&eye_orient, &player_transpose, &Eye_matrix);
						vm_vec_rotate(&fpfromeye, &pm->gun_banks[i].pnt[j], &eye_orient);

						firepoint tmp = { { fpfromeye.xyz.x - ep.x, ep.y - fpfromeye.xyz.y }, fpactive };
						fp.push_back(tmp);
					}
				}
			}
		}
	}
}
void techroom_ships_render(float frametime)
{
	// render all the common stuff
	tech_common_render();
	
	if(Cur_entry_index == -1)
		return;

	// now render the trackball ship, which is unique to the ships tab
	float rev_rate = REVOLUTION_RATE;
	angles rot_angles, view_angles;
	int z, i, j;
	ship_info *sip = &Ship_info[Cur_entry_index];
	model_render_params render_info;

	if (sip->uses_team_colors) {
		render_info.set_team_color(sip->default_team_name, "none", 0, 0);
	}

	// get correct revolution rate
	z = sip->flags;
	if (z & SIF_BIG_SHIP) {
		rev_rate *= 1.7f;
	}
	if (z & SIF_HUGE_SHIP) {
		rev_rate *= 3.0f;
	}

	// rotate the ship as much as required for this frame
	Techroom_ship_rot += PI2 * frametime / rev_rate;
	while (Techroom_ship_rot > PI2){
		Techroom_ship_rot -= PI2;	
	}

	//	reorient ship
	if (Trackball_active) {
		int dx, dy;
		matrix mat1, mat2;

		if (Trackball_active) {
			mouse_get_delta(&dx, &dy);
			if (dx || dy) {
				vm_trackball(-dx, -dy, &mat1);
				vm_matrix_x_matrix(&mat2, &mat1, &Techroom_ship_orient);
				Techroom_ship_orient = mat2;
			}
		}

	} else {
		// setup stuff needed to render the ship
		view_angles.p = -0.6f;
		view_angles.b = 0.0f;
		view_angles.h = 0.0f;
		vm_angles_2_matrix(&Techroom_ship_orient, &view_angles);

		rot_angles.p = 0.0f;
		rot_angles.b = 0.0f;
		rot_angles.h = Techroom_ship_rot;
		vm_rotate_matrix_by_angles(&Techroom_ship_orient, &rot_angles);
	}

	gr_set_clip(Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_W_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_H_COORD], GR_RESIZE_MENU);	

	// render the ship
	g3_start_frame(1);
	g3_set_view_matrix(&sip->closeup_pos, &vmd_identity_matrix, sip->closeup_zoom * 1.3f);

	

	// lighting for techroom
	light_reset();
	vec3d light_dir = vmd_zero_vector;
	light_dir.xyz.y = 1.0f;	
	light_dir.xyz.x = 0.0000001f;	
	light_add_directional(&light_dir, 0.85f, 1.0f, 1.0f, 1.0f);
	light_rotate_all();
	// lighting for techroom

	Glowpoint_use_depth_buffer = false;

	model_clear_instance(Techroom_ship_modelnum);
	render_info.set_detail_level_lock(0);

	polymodel *pm = model_get(Techroom_ship_modelnum);
	
	for (i = 0; i < sip->n_subsystems; i++) {
		model_subsystem *msp = &sip->subsystems[i];
		if (msp->type == SUBSYSTEM_TURRET) {

			float p = 0.0f;
			float h = 0.0f;

			for (j = 0; j < msp->n_triggers; j++) {

				// special case for turrets
				p = msp->triggers[j].angle.xyz.x;
				h = msp->triggers[j].angle.xyz.y;
			}
			if ( msp->subobj_num >= 0 )	{
				model_set_instance_techroom(Techroom_ship_modelnum, msp->subobj_num, 0.0f, h );
			}
			if ( (msp->subobj_num != msp->turret_gun_sobj) && (msp->turret_gun_sobj >= 0) )		{
				model_set_instance_techroom(Techroom_ship_modelnum, msp->turret_gun_sobj, p, 0.0f );
			}
		}
	}

    if(Cmdline_shadow_quality)
    {
        gr_reset_clip();

		shadows_start_render(&Eye_matrix, &Eye_position, Proj_fov, gr_screen.clip_aspect, -sip->closeup_pos.xyz.z + pm->rad, -sip->closeup_pos.xyz.z + pm->rad + 200.0f, -sip->closeup_pos.xyz.z + pm->rad + 2000.0f, -sip->closeup_pos.xyz.z + pm->rad + 10000.0f);
        render_info.set_flags(MR_NO_TEXTURING | MR_NO_LIGHTING | MR_AUTOCENTER);
		
		model_render_immediate(&render_info, Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector);
        shadows_end_render();

		gr_set_clip(Tech_ship_display_coords[gr_screen.res][SHIP_X_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_Y_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_W_COORD], Tech_ship_display_coords[gr_screen.res][SHIP_H_COORD], GR_RESIZE_MENU);
    }
	
	if (!Cmdline_nohtl) {
		gr_set_proj_matrix(Proj_fov, gr_screen.clip_aspect, Min_draw_distance, Max_draw_distance);
		gr_set_view_matrix(&Eye_position, &Eye_matrix);
	}

	uint render_flags = MR_AUTOCENTER;

	if(sip->flags2 & SIF2_NO_LIGHTING)
		render_flags |= MR_NO_LIGHTING;

	render_info.set_flags(render_flags);

	model_render_immediate(&render_info, Techroom_ship_modelnum, &Techroom_ship_orient, &vmd_zero_vector);

	Glowpoint_use_depth_buffer = true;

	batch_render_all();

	if (!Cmdline_nohtl)
	{
		gr_end_view_matrix();
		gr_end_proj_matrix();
	}

	g3_end_frame();

	gr_reset_clip();
}
Exemple #24
0
/* ----- [ add ] ------------------------------------------------------------ */
void add(struct Var_conf *config)
{
    int timer = 1; // Fix bug of timer
    int random = 0;
    SDL_Rect pos;
    // Pieces id's
    enum Piece_bloc pieces[PC_NB] = {	SQR1,SQR1,SQR1,SQR1,
    					BAR1,BAR1,BAR2,BAR2,
					L1,L2,L3,L4,
					LINV1,LINV2,LINV3,LINV4,
					S1,S1,S2,S2,
					SINV1,SINV1,SINV2,SINV2,
					DP1,DP2,DP3,DP4 };

    // Disable timer
    config->state = J_PAUSE;
    if(!config->dropping && !config->down_pressed && !SDL_RemoveTimer(config->timer))
    {
	fprintf(stderr,
		"[ERROR] Cannot remove timer in %s at line %d.\n",
		__FILE__,__LINE__);
	timer = 0;
    }

    // Get a random piece
    random = rand() % PC_NB + 1;

    // Copy next piece in current piece
    config->pc_cur_id = config->pc_next_id;
    
    // Copy random piece in next piece
    config->pc_next_id = pieces[random - 1];

    // Check position
    pos.x = (PNL_LB / 2) - (PC_NB_LBLC / 2);
    pos.y = 1;

	// Dynamic height panel management
	if(ENABLE_DYNPNL)
	{
		// Empty lines check
		int r = 0;
		int s = 0;
		int empty = 1;

		// Check if half the panel is empty
		for(r = 0;r < 2 * PC_NB_HBLC && empty;r++)
		{
			for(s = 0;s < model_width(config->model) && empty;s++)
			{
				if(model_get(config->model,r,s) != CL_MPT)
					empty = 0;
			}
		}

		// If a quarter of the panel is not empty, add a quarter of empty lines
		if(!empty)
			for(r = 0;r < 2 * PC_NB_HBLC;r++)
				model_add_first(config->model,CL_MPT);

	}	

    // Position is good
    if(check_pc(config,config->model,config->pieces[config->pc_cur_id],pos))
    {
    	config->piece_pos.x = pos.x;
		config->piece_pos.y = pos.y;

		// Piece ghost
		pos.x = config->piece_pos.x;
		pos.y = config->piece_pos.y;
		while(check_pc(config,
				   config->model,
				   config->pieces[config->pc_cur_id],
				   pos)
			  && pos.y != model_height(config->model))
			pos.y++;
		pos.y--;
		config->ghost_pos.x = config->piece_pos.x;
		config->ghost_pos.y = pos.y;
		
		// Display next piece
		disp_next_pc(config);

		// Trigger AI if launched
		if(config->ai_started)
			config->ai_trigger = 1;

		// Enable timer
		config->state = J_PLAY;
		if(timer)
			if(!config->dropping && !config->down_pressed 
			   && (config->timer = SDL_AddTimer(config->interv,
							step,config)) == NULL)
			fprintf(stderr,
				"[ERROR] Cannot initialize timer in %s at line %d.\n",
				__FILE__,__LINE__);

		return;
    }
    // Game Over
    else
    {
    	config->pc_cur_id = PCMPTY;
		lost(config);
		return;
    }
}