2019-10-19 11:57 EDT


View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0002351FSSCPtablespublic2010-12-27 03:04
ReporterFUBAR-BDHR 
Assigned ToEchelon9 
PrioritynormalSeverityminorReproducibilityalways
StatusresolvedResolutionfixed 
Product Version3.6.13 
Target VersionFixed in Version3.6.13 
Summary0002351: Animated subsystems not counted as rotating allowing max to be exceeded
DescriptionIt appears that subsystems with animation triggered count toward MAX_ROTATING_SUBMODELS but there is absolutely no checking for this. Strange things happen when rotating subsystems + animated ones exceed the max. In my testing turrets some multi-part turrets started firing 90 degrees off their normals.

No idea how to test this one with retail data.
TagsNo tags attached.
Attached Files
  • patch file icon mantis-2351_proposed_patch_3.patch (15,843 bytes) 2010-12-27 00:48 -
    Index: code/asteroid/asteroid.cpp
    ===================================================================
    --- code/asteroid/asteroid.cpp	(revision 6889)
    +++ code/asteroid/asteroid.cpp	(working copy)
    @@ -976,8 +976,7 @@
     		// first test against the sphere - if this fails then don't do any submodel tests
     		mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
     
    -		int submodel_list[MAX_ROTATING_SUBMODELS];
    -		int num_rotating_submodels = 0;
    +		SCP_vector<int> submodel_vector;
     		polymodel *pm;
     		polymodel_instance *pmi;
     
    @@ -989,7 +988,7 @@
     			// Do collision the cool new way
     			if ( asteroid_hit_info->collide_rotate ) {
     				// We collide with the sphere, find the list of rotating submodels and test one at a time
    -				model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, heavy_obj);
    +				model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
     
     				// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
     				pm = model_get(Ship_info[Ships[heavy_obj->instance].ship_info_index].model_num);
    @@ -997,8 +996,8 @@
     
     				// turn off all rotating submodels and test for collision
     				int i;
    -				for (i=0; i<num_rotating_submodels; i++) {
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +				for (i=0; i<submodel_vector.size(); i++) {
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     				// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
    @@ -1006,26 +1005,26 @@
     
     
     				// check each submodel in turn
    -				for (i=0; i<num_rotating_submodels; i++) {
    +				for (i=0; i<submodel_vector.size(); i++) {
     					// turn on submodel for collision test
    -					pmi->submodel[submodel_list[i]].collision_checked = false;
    +					pmi->submodel[submodel_vector[i]].collision_checked = false;
     
     					// set angles for last frame (need to set to prev to get p0)
    -					angles copy_angles = pmi->submodel[submodel_list[i]].angs;
    +					angles copy_angles = pmi->submodel[submodel_vector[i]].angs;
     
     					// find the start and end positions of the sphere in submodel RF
    -					pmi->submodel[submodel_list[i]].angs = pmi->submodel[submodel_list[i]].prev_angs;
    -					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_list[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
    +					pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
    +					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
     
    -					pmi->submodel[submodel_list[i]].angs = copy_angles;
    -					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
    +					pmi->submodel[submodel_vector[i]].angs = copy_angles;
    +					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
     
     					mc.p0 = &p0;
     					mc.p1 = &p1;
     					// mc.pos = zero	// in submodel RF
     
     					mc.orient = &vmd_identity_matrix;
    -					mc.submodel_num = submodel_list[i];
    +					mc.submodel_num = submodel_vector[i];
     
     					if ( model_collide(&mc) ) {
     						if ( mc.hit_dist < asteroid_hit_info->hit_time ) {
    @@ -1047,7 +1046,7 @@
     						}
     					}
     					// Don't look at this submodel again
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     			}
    Index: code/object/collideshipship.cpp
    ===================================================================
    --- code/object/collideshipship.cpp	(revision 6889)
    +++ code/object/collideshipship.cpp	(working copy)
    @@ -247,8 +247,7 @@
     	// first test against the sphere - if this fails then don't do any submodel tests
     	mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
     
    -	int submodel_list[MAX_ROTATING_SUBMODELS];
    -	int num_rotating_submodels = 0;
    +	SCP_vector<int> submodel_vector;
     	int valid_hit_occured = 0;
     	polymodel *pm;
     	polymodel_instance *pmi;
    @@ -261,41 +260,41 @@
     		// Do collision the cool new way
     		if ( ship_ship_hit_info->collide_rotate ) {
     
    -			model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, heavy_obj);
    +			model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
     
     			pm = model_get(Ship_info[heavy_shipp->ship_info_index].model_num);
     			pmi = model_get_instance(heavy_shipp->model_instance_num);
     
     			// turn off all rotating submodels and test for collision
     			int i;
    -			for (i=0; i<num_rotating_submodels; i++) {
    -				pmi->submodel[submodel_list[i]].collision_checked = true;
    +			for (i=0; i<submodel_vector.size(); i++) {
    +				pmi->submodel[submodel_vector[i]].collision_checked = true;
     			}
     
     			// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
     			mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
     
     			// check each submodel in turn
    -			for (i=0; i<num_rotating_submodels; i++) {
    +			for (i=0; i<submodel_vector.size(); i++) {
     				// turn on submodel for collision test
    -				pmi->submodel[submodel_list[i]].collision_checked = false;
    +				pmi->submodel[submodel_vector[i]].collision_checked = false;
     
     				// set angles for last frame
    -				angles copy_angles = pmi->submodel[submodel_list[i]].angs;
    +				angles copy_angles = pmi->submodel[submodel_vector[i]].angs;
     
     				// find the start and end positions of the sphere in submodel RF
    -				pmi->submodel[submodel_list[i]].angs = pmi->submodel[submodel_list[i]].prev_angs;
    -				world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_list[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
    +				pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
    +				world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
     
    -				pmi->submodel[submodel_list[i]].angs = copy_angles;
    -				world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
    +				pmi->submodel[submodel_vector[i]].angs = copy_angles;
    +				world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
     
     				mc.p0 = &p0;
     				mc.p1 = &p1;
     				// mc.pos = zero	// in submodel RF
     
     				mc.orient = &vmd_identity_matrix;
    -				mc.submodel_num = submodel_list[i];
    +				mc.submodel_num = submodel_vector[i];
     
     				if ( model_collide(&mc) ) {
     					if (mc.hit_dist < ship_ship_hit_info->hit_time ) {
    @@ -339,17 +338,17 @@
     						// set submodel angle at time of collision
     						// TODO: generalize... what happens when angle passes 0 or 2PI
     						angles temp_angs;
    -						vm_vec_sub(&diff, (vec3d*)&pm->submodel[submodel_list[i]].angs, (vec3d*)&pm->submodel[submodel_list[i]].sii->prev_angs);
    -						vm_vec_scale_add((vec3d*)&temp_angs, (vec3d *)&pm->submodel[submodel_list[i]].sii->prev_angs, &diff, mc.hit_dist);
    -						pm->submodel[submodel_list[i]].angs = temp_angs;
    +						vm_vec_sub(&diff, (vec3d*)&pm->submodel[submodel_vector[i]].angs, (vec3d*)&pm->submodel[submodel_vector[i]].sii->prev_angs);
    +						vm_vec_scale_add((vec3d*)&temp_angs, (vec3d *)&pm->submodel[submodel_vector[i]].sii->prev_angs, &diff, mc.hit_dist);
    +						pm->submodel[submodel_vector[i]].angs = temp_angs;
     
     						// find intersection point in submodel RF - THEN advance to end of frametime.
     						vec3d temp = int_light_pos;
    -						world_find_model_point(&int_submodel_pos, &int_light_pos, pm, submodel_list[i], &int_heavy_orient, &int_heavy_pos);
    +						world_find_model_point(&int_submodel_pos, &int_light_pos, pm, submodel_vector[i], &int_heavy_orient, &int_heavy_pos);
     						vec3d temp2;
     
     						// Advance to end of frametime
    -						pm->submodel[submodel_list[i]].angs = copy_angles;
    +						pm->submodel[submodel_vector[i]].angs = copy_angles;
     						model_find_world_point(&ship_ship_hit_info->light_collision_cm_pos, &int_submodel_pos, mc.model_num, mc.hit_submodel, mc.orient, &zero);
     						vm_vec_sub(&temp2, &ship_ship_hit_info->light_collision_cm_pos, &ship_ship_hit_info->hit_pos);
     		*/
    @@ -359,7 +358,7 @@
     					}
     				}
     				// Don't look at this submodel again
    -				pmi->submodel[submodel_list[i]].collision_checked = true;
    +				pmi->submodel[submodel_vector[i]].collision_checked = true;
     			}
     
     		}
    Index: code/model/model.h
    ===================================================================
    --- code/model/model.h	(revision 6889)
    +++ code/model/model.h	(working copy)
    @@ -41,8 +41,6 @@
     #define MOVEMENT_AXIS_Y		2
     #define MOVEMENT_AXIS_Z		1
     
    -#define MAX_ROTATING_SUBMODELS 50
    -
     // defines for special objects like gun and missile points, docking point, etc
     // Hoffoss: Please make sure that subsystem NONE is always index 0, and UNKNOWN is
     // always the last subsystem in the list.  Also, make sure that MAX is correct.
    @@ -130,6 +128,7 @@
     #define MSS_FLAG_NO_LIVE_DEBRIS		(1 << 25)		// sets the subsys not to release live debris
     #define MSS_FLAG_IGNORE_IF_DEAD		(1 << 26)		// tells homing missiles to ignore the subsys if its dead and home on to hull instead of earlier subsys pos
     #define MSS_FLAG_ALLOW_VANISHING	(1 << 27)		// allows subsystem to vanish (prevents explosions & sounds effects from being played)
    +#define MSS_FLAG_DAMAGE_AS_HULL		(1 << 28)		// applys armor damage to subsystem instead of subsystem damage - FUBAR
     
     // definition of stepped rotation struct
     typedef struct stepped_rotation {
    @@ -863,7 +862,7 @@
     void world_find_model_instance_point(vec3d *out, vec3d *world_pt, polymodel *pm, polymodel_instance *pmi, int submodel_num, matrix *orient, vec3d *pos);
     
     // Given a polygon model index, find a list of rotating submodels to be used for collision
    -void model_get_rotating_submodel_list(int *submodel_list, int *num_rotating_submodesl, object *objp);
    +void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *objp);
     
     // For a rotating submodel, find a point on the axis
     void model_init_submodel_axis_pt(submodel_instance_info *sii, int model_num, int submodel_num);
    Index: code/model/modelread.cpp
    ===================================================================
    --- code/model/modelread.cpp	(revision 6889)
    +++ code/model/modelread.cpp	(working copy)
    @@ -3866,16 +3866,15 @@
     	return found;
     }
     
    -void model_get_rotating_submodel_list(int *submodel_list, int *num_rotating_submodels, object *objp)
    +void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *objp)
     {
     	Assert(objp->type == OBJ_SHIP);
    -
    +	
     	// Check if not currently rotating - then treat as part of superstructure.
     	int modelnum = Ship_info[Ships[objp->instance].ship_info_index].model_num;
     	polymodel *pm = model_get(modelnum);
     	bsp_info *child_submodel;
    -
    -	*num_rotating_submodels = 0;
    +	
     	child_submodel = &pm->submodel[pm->detail[0]];
     
     	int i = child_submodel->first_child;
    @@ -3898,8 +3897,7 @@
     						// found the correct subsystem - now check delta rotation angle not too large
     						float delta_angle = get_submodel_delta_angle(&subsys->submodel_info_1);
     						if (delta_angle < MAX_SUBMODEL_COLLISION_ROT_ANGLE) {
    -							Assert(*num_rotating_submodels < MAX_ROTATING_SUBMODELS-1);
    -							submodel_list[(*num_rotating_submodels)++] = i;
    +							submodel_vector->push_back(i);
     						}
     						break;
     					}
    @@ -3913,14 +3911,14 @@
     //#define MODEL_CHECK
     #ifdef MODEL_CHECK
     	ship *pship = &Ships[objp->instance];
    -	for (int idx=0; idx<*num_rotating_submodels; idx++) {
    -		int valid = rotating_submodel_has_ship_subsys(submodel_list[idx], pship);
    +	for (int idx=0; idx<submodel_vector->size(); idx++) {
    +		int valid = rotating_submodel_has_ship_subsys(submodel_vector[idx], pship);
     //		Assert( valid );
     		if ( !valid ) {
     
    -			Warning( LOCATION, "Ship %s has rotating submodel [%s] without ship subsystem\n", pship->ship_name, pm->submodel[submodel_list[idx]].name );
    -			pm->submodel[submodel_list[idx]].movement_type &= ~MOVEMENT_TYPE_ROT;
    -			*num_rotating_submodels = 0;
    +			Warning( LOCATION, "Ship %s has rotating submodel [%s] without ship subsystem\n", pship->ship_name, pm->submodel[submodel_vector[idx]].name );
    +			pm->submodel[submodel_vector[idx]].movement_type &= ~MOVEMENT_TYPE_ROT;
    +			submodel_vector->erase(submodel_vector->begin()+i);
     		}
     	}
     #endif
    Index: code/debris/debris.cpp
    ===================================================================
    --- code/debris/debris.cpp	(revision 6889)
    +++ code/debris/debris.cpp	(working copy)
    @@ -920,8 +920,7 @@
     		// first test against the sphere - if this fails then don't do any submodel tests
     		mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
     
    -		int submodel_list[MAX_ROTATING_SUBMODELS];
    -		int num_rotating_submodels = 0;
    +		SCP_vector<int> submodel_vector;
     		polymodel *pm;
     		polymodel_instance *pmi;
     
    @@ -935,7 +934,7 @@
     			// Do collision the cool new way
     			if ( debris_hit_info->collide_rotate ) {
     				// We collide with the sphere, find the list of rotating submodels and test one at a time
    -				model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, heavy_obj);
    +				model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
     
     				// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
     				pm = model_get(Ship_info[Ships[heavy_obj->instance].ship_info_index].model_num);
    @@ -943,34 +942,34 @@
     
     				// turn off all rotating submodels and test for collision
     				int i;
    -				for (i=0; i<num_rotating_submodels; i++) {
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +				for (i=0; i<submodel_vector.size(); i++) {
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     				// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
     				mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
     
     				// check each submodel in turn
    -				for (i=0; i<num_rotating_submodels; i++) {
    +				for (i=0; i<submodel_vector.size(); i++) {
     					// turn on submodel for collision test
    -					pmi->submodel[submodel_list[i]].collision_checked = false;
    +					pmi->submodel[submodel_vector[i]].collision_checked = false;
     
     					// set angles for last frame (need to set to prev to get p0)
    -					angles copy_angles = pmi->submodel[submodel_list[i]].angs;
    +					angles copy_angles = pmi->submodel[submodel_vector[i]].angs;
     
     					// find the start and end positions of the sphere in submodel RF
    -					pmi->submodel[submodel_list[i]].angs = pmi->submodel[submodel_list[i]].prev_angs;
    -					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_list[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
    +					pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
    +					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
     
    -					pmi->submodel[submodel_list[i]].angs = copy_angles;
    -					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
    +					pmi->submodel[submodel_vector[i]].angs = copy_angles;
    +					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
     
     					mc.p0 = &p0;
     					mc.p1 = &p1;
     					// mc.pos = zero	// in submodel RF
     
     					mc.orient = &vmd_identity_matrix;
    -					mc.submodel_num = submodel_list[i];
    +					mc.submodel_num = submodel_vector[i];
     
     					if ( model_collide(&mc) ) {
     						if ( mc.hit_dist < debris_hit_info->hit_time ) {
    @@ -993,7 +992,7 @@
     						}
     					}
     					// Don't look at this submodel again
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     			}
    
    patch file icon mantis-2351_proposed_patch_3.patch (15,843 bytes) 2010-12-27 00:48 +
  • patch file icon mantis-2351_proposed_patch_4.patch (16,005 bytes) 2010-12-27 02:32 -
    Index: code/asteroid/asteroid.cpp
    ===================================================================
    --- code/asteroid/asteroid.cpp	(revision 6892)
    +++ code/asteroid/asteroid.cpp	(working copy)
    @@ -976,8 +976,7 @@
     		// first test against the sphere - if this fails then don't do any submodel tests
     		mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
     
    -		int submodel_list[MAX_ROTATING_SUBMODELS];
    -		int num_rotating_submodels = 0;
    +		SCP_vector<int> submodel_vector;
     		polymodel *pm;
     		polymodel_instance *pmi;
     
    @@ -989,16 +988,15 @@
     			// Do collision the cool new way
     			if ( asteroid_hit_info->collide_rotate ) {
     				// We collide with the sphere, find the list of rotating submodels and test one at a time
    -				model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, heavy_obj);
    +				model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
     
     				// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
     				pm = model_get(Ship_info[Ships[heavy_obj->instance].ship_info_index].model_num);
     				pmi = model_get_instance(Ships[ship_obj->instance].model_instance_num);
     
     				// turn off all rotating submodels and test for collision
    -				int i;
    -				for (i=0; i<num_rotating_submodels; i++) {
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +				for (size_t i=0; i<submodel_vector.size(); i++) {
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     				// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
    @@ -1006,26 +1004,26 @@
     
     
     				// check each submodel in turn
    -				for (i=0; i<num_rotating_submodels; i++) {
    +				for (size_t i=0; i<submodel_vector.size(); i++) {
     					// turn on submodel for collision test
    -					pmi->submodel[submodel_list[i]].collision_checked = false;
    +					pmi->submodel[submodel_vector[i]].collision_checked = false;
     
     					// set angles for last frame (need to set to prev to get p0)
    -					angles copy_angles = pmi->submodel[submodel_list[i]].angs;
    +					angles copy_angles = pmi->submodel[submodel_vector[i]].angs;
     
     					// find the start and end positions of the sphere in submodel RF
    -					pmi->submodel[submodel_list[i]].angs = pmi->submodel[submodel_list[i]].prev_angs;
    -					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_list[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
    +					pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
    +					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
     
    -					pmi->submodel[submodel_list[i]].angs = copy_angles;
    -					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
    +					pmi->submodel[submodel_vector[i]].angs = copy_angles;
    +					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
     
     					mc.p0 = &p0;
     					mc.p1 = &p1;
     					// mc.pos = zero	// in submodel RF
     
     					mc.orient = &vmd_identity_matrix;
    -					mc.submodel_num = submodel_list[i];
    +					mc.submodel_num = submodel_vector[i];
     
     					if ( model_collide(&mc) ) {
     						if ( mc.hit_dist < asteroid_hit_info->hit_time ) {
    @@ -1047,7 +1045,7 @@
     						}
     					}
     					// Don't look at this submodel again
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     			}
    Index: code/object/collideshipship.cpp
    ===================================================================
    --- code/object/collideshipship.cpp	(revision 6892)
    +++ code/object/collideshipship.cpp	(working copy)
    @@ -247,8 +247,7 @@
     	// first test against the sphere - if this fails then don't do any submodel tests
     	mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
     
    -	int submodel_list[MAX_ROTATING_SUBMODELS];
    -	int num_rotating_submodels = 0;
    +	SCP_vector<int> submodel_vector;
     	int valid_hit_occured = 0;
     	polymodel *pm;
     	polymodel_instance *pmi;
    @@ -261,41 +260,40 @@
     		// Do collision the cool new way
     		if ( ship_ship_hit_info->collide_rotate ) {
     
    -			model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, heavy_obj);
    +			model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
     
     			pm = model_get(Ship_info[heavy_shipp->ship_info_index].model_num);
     			pmi = model_get_instance(heavy_shipp->model_instance_num);
     
     			// turn off all rotating submodels and test for collision
    -			int i;
    -			for (i=0; i<num_rotating_submodels; i++) {
    -				pmi->submodel[submodel_list[i]].collision_checked = true;
    +			for (size_t i=0; i<submodel_vector.size(); i++) {
    +				pmi->submodel[submodel_vector[i]].collision_checked = true;
     			}
     
     			// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
     			mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
     
     			// check each submodel in turn
    -			for (i=0; i<num_rotating_submodels; i++) {
    +			for (size_t i=0; i<submodel_vector.size(); i++) {
     				// turn on submodel for collision test
    -				pmi->submodel[submodel_list[i]].collision_checked = false;
    +				pmi->submodel[submodel_vector[i]].collision_checked = false;
     
     				// set angles for last frame
    -				angles copy_angles = pmi->submodel[submodel_list[i]].angs;
    +				angles copy_angles = pmi->submodel[submodel_vector[i]].angs;
     
     				// find the start and end positions of the sphere in submodel RF
    -				pmi->submodel[submodel_list[i]].angs = pmi->submodel[submodel_list[i]].prev_angs;
    -				world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_list[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
    +				pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
    +				world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
     
    -				pmi->submodel[submodel_list[i]].angs = copy_angles;
    -				world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
    +				pmi->submodel[submodel_vector[i]].angs = copy_angles;
    +				world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
     
     				mc.p0 = &p0;
     				mc.p1 = &p1;
     				// mc.pos = zero	// in submodel RF
     
     				mc.orient = &vmd_identity_matrix;
    -				mc.submodel_num = submodel_list[i];
    +				mc.submodel_num = submodel_vector[i];
     
     				if ( model_collide(&mc) ) {
     					if (mc.hit_dist < ship_ship_hit_info->hit_time ) {
    @@ -339,17 +337,17 @@
     						// set submodel angle at time of collision
     						// TODO: generalize... what happens when angle passes 0 or 2PI
     						angles temp_angs;
    -						vm_vec_sub(&diff, (vec3d*)&pm->submodel[submodel_list[i]].angs, (vec3d*)&pm->submodel[submodel_list[i]].sii->prev_angs);
    -						vm_vec_scale_add((vec3d*)&temp_angs, (vec3d *)&pm->submodel[submodel_list[i]].sii->prev_angs, &diff, mc.hit_dist);
    -						pm->submodel[submodel_list[i]].angs = temp_angs;
    +						vm_vec_sub(&diff, (vec3d*)&pm->submodel[submodel_vector[i]].angs, (vec3d*)&pm->submodel[submodel_vector[i]].sii->prev_angs);
    +						vm_vec_scale_add((vec3d*)&temp_angs, (vec3d *)&pm->submodel[submodel_vector[i]].sii->prev_angs, &diff, mc.hit_dist);
    +						pm->submodel[submodel_vector[i]].angs = temp_angs;
     
     						// find intersection point in submodel RF - THEN advance to end of frametime.
     						vec3d temp = int_light_pos;
    -						world_find_model_point(&int_submodel_pos, &int_light_pos, pm, submodel_list[i], &int_heavy_orient, &int_heavy_pos);
    +						world_find_model_point(&int_submodel_pos, &int_light_pos, pm, submodel_vector[i], &int_heavy_orient, &int_heavy_pos);
     						vec3d temp2;
     
     						// Advance to end of frametime
    -						pm->submodel[submodel_list[i]].angs = copy_angles;
    +						pm->submodel[submodel_vector[i]].angs = copy_angles;
     						model_find_world_point(&ship_ship_hit_info->light_collision_cm_pos, &int_submodel_pos, mc.model_num, mc.hit_submodel, mc.orient, &zero);
     						vm_vec_sub(&temp2, &ship_ship_hit_info->light_collision_cm_pos, &ship_ship_hit_info->hit_pos);
     		*/
    @@ -359,7 +357,7 @@
     					}
     				}
     				// Don't look at this submodel again
    -				pmi->submodel[submodel_list[i]].collision_checked = true;
    +				pmi->submodel[submodel_vector[i]].collision_checked = true;
     			}
     
     		}
    Index: code/model/model.h
    ===================================================================
    --- code/model/model.h	(revision 6892)
    +++ code/model/model.h	(working copy)
    @@ -41,8 +41,6 @@
     #define MOVEMENT_AXIS_Y		2
     #define MOVEMENT_AXIS_Z		1
     
    -#define MAX_ROTATING_SUBMODELS 50
    -
     // defines for special objects like gun and missile points, docking point, etc
     // Hoffoss: Please make sure that subsystem NONE is always index 0, and UNKNOWN is
     // always the last subsystem in the list.  Also, make sure that MAX is correct.
    @@ -130,6 +128,7 @@
     #define MSS_FLAG_NO_LIVE_DEBRIS		(1 << 25)		// sets the subsys not to release live debris
     #define MSS_FLAG_IGNORE_IF_DEAD		(1 << 26)		// tells homing missiles to ignore the subsys if its dead and home on to hull instead of earlier subsys pos
     #define MSS_FLAG_ALLOW_VANISHING	(1 << 27)		// allows subsystem to vanish (prevents explosions & sounds effects from being played)
    +#define MSS_FLAG_DAMAGE_AS_HULL		(1 << 28)		// applys armor damage to subsystem instead of subsystem damage - FUBAR
     
     // definition of stepped rotation struct
     typedef struct stepped_rotation {
    @@ -863,7 +862,7 @@
     void world_find_model_instance_point(vec3d *out, vec3d *world_pt, polymodel *pm, polymodel_instance *pmi, int submodel_num, matrix *orient, vec3d *pos);
     
     // Given a polygon model index, find a list of rotating submodels to be used for collision
    -void model_get_rotating_submodel_list(int *submodel_list, int *num_rotating_submodesl, object *objp);
    +void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *objp);
     
     // For a rotating submodel, find a point on the axis
     void model_init_submodel_axis_pt(submodel_instance_info *sii, int model_num, int submodel_num);
    Index: code/model/modelread.cpp
    ===================================================================
    --- code/model/modelread.cpp	(revision 6892)
    +++ code/model/modelread.cpp	(working copy)
    @@ -3866,16 +3866,15 @@
     	return found;
     }
     
    -void model_get_rotating_submodel_list(int *submodel_list, int *num_rotating_submodels, object *objp)
    +void model_get_rotating_submodel_list(SCP_vector<int> *submodel_vector, object *objp)
     {
     	Assert(objp->type == OBJ_SHIP);
    -
    +	
     	// Check if not currently rotating - then treat as part of superstructure.
     	int modelnum = Ship_info[Ships[objp->instance].ship_info_index].model_num;
     	polymodel *pm = model_get(modelnum);
     	bsp_info *child_submodel;
    -
    -	*num_rotating_submodels = 0;
    +	
     	child_submodel = &pm->submodel[pm->detail[0]];
     
     	int i = child_submodel->first_child;
    @@ -3898,8 +3897,7 @@
     						// found the correct subsystem - now check delta rotation angle not too large
     						float delta_angle = get_submodel_delta_angle(&subsys->submodel_info_1);
     						if (delta_angle < MAX_SUBMODEL_COLLISION_ROT_ANGLE) {
    -							Assert(*num_rotating_submodels < MAX_ROTATING_SUBMODELS-1);
    -							submodel_list[(*num_rotating_submodels)++] = i;
    +							submodel_vector->push_back(i);
     						}
     						break;
     					}
    @@ -3913,14 +3911,14 @@
     //#define MODEL_CHECK
     #ifdef MODEL_CHECK
     	ship *pship = &Ships[objp->instance];
    -	for (int idx=0; idx<*num_rotating_submodels; idx++) {
    -		int valid = rotating_submodel_has_ship_subsys(submodel_list[idx], pship);
    +	for (size_t idx=0; idx<submodel_vector->size(); idx++) {
    +		int valid = rotating_submodel_has_ship_subsys(submodel_vector[idx], pship);
     //		Assert( valid );
     		if ( !valid ) {
     
    -			Warning( LOCATION, "Ship %s has rotating submodel [%s] without ship subsystem\n", pship->ship_name, pm->submodel[submodel_list[idx]].name );
    -			pm->submodel[submodel_list[idx]].movement_type &= ~MOVEMENT_TYPE_ROT;
    -			*num_rotating_submodels = 0;
    +			Warning( LOCATION, "Ship %s has rotating submodel [%s] without ship subsystem\n", pship->ship_name, pm->submodel[submodel_vector[idx]].name );
    +			pm->submodel[submodel_vector[idx]].movement_type &= ~MOVEMENT_TYPE_ROT;
    +			submodel_vector->erase(submodel_vector->begin()+i);
     		}
     	}
     #endif
    Index: code/debris/debris.cpp
    ===================================================================
    --- code/debris/debris.cpp	(revision 6892)
    +++ code/debris/debris.cpp	(working copy)
    @@ -920,8 +920,7 @@
     		// first test against the sphere - if this fails then don't do any submodel tests
     		mc.flags = MC_ONLY_SPHERE | MC_CHECK_SPHERELINE;
     
    -		int submodel_list[MAX_ROTATING_SUBMODELS];
    -		int num_rotating_submodels = 0;
    +		SCP_vector<int> submodel_vector;
     		polymodel *pm;
     		polymodel_instance *pmi;
     
    @@ -935,42 +934,41 @@
     			// Do collision the cool new way
     			if ( debris_hit_info->collide_rotate ) {
     				// We collide with the sphere, find the list of rotating submodels and test one at a time
    -				model_get_rotating_submodel_list(submodel_list, &num_rotating_submodels, heavy_obj);
    +				model_get_rotating_submodel_list(&submodel_vector, heavy_obj);
     
     				// Get polymodel and turn off all rotating submodels, collide against only 1 at a time.
     				pm = model_get(Ship_info[Ships[heavy_obj->instance].ship_info_index].model_num);
     				pmi = model_get_instance(Ships[heavy_obj->instance].model_instance_num);
     
     				// turn off all rotating submodels and test for collision
    -				int i;
    -				for (i=0; i<num_rotating_submodels; i++) {
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +				for (size_t i=0; i<submodel_vector.size(); i++) {
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     				// reset flags to check MC_CHECK_MODEL | MC_CHECK_SPHERELINE and maybe MC_CHECK_INVISIBLE_FACES and MC_SUBMODEL_INSTANCE
     				mc.flags = copy_flags | MC_SUBMODEL_INSTANCE;
     
     				// check each submodel in turn
    -				for (i=0; i<num_rotating_submodels; i++) {
    +				for (size_t i=0; i<submodel_vector.size(); i++) {
     					// turn on submodel for collision test
    -					pmi->submodel[submodel_list[i]].collision_checked = false;
    +					pmi->submodel[submodel_vector[i]].collision_checked = false;
     
     					// set angles for last frame (need to set to prev to get p0)
    -					angles copy_angles = pmi->submodel[submodel_list[i]].angs;
    +					angles copy_angles = pmi->submodel[submodel_vector[i]].angs;
     
     					// find the start and end positions of the sphere in submodel RF
    -					pmi->submodel[submodel_list[i]].angs = pmi->submodel[submodel_list[i]].prev_angs;
    -					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_list[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
    +					pmi->submodel[submodel_vector[i]].angs = pmi->submodel[submodel_vector[i]].prev_angs;
    +					world_find_model_instance_point(&p0, &light_obj->last_pos, pm, pmi, submodel_vector[i], &heavy_obj->last_orient, &heavy_obj->last_pos);
     
    -					pmi->submodel[submodel_list[i]].angs = copy_angles;
    -					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_list[i], &heavy_obj->orient, &heavy_obj->pos);
    +					pmi->submodel[submodel_vector[i]].angs = copy_angles;
    +					world_find_model_instance_point(&p1, &light_obj->pos, pm, pmi, submodel_vector[i], &heavy_obj->orient, &heavy_obj->pos);
     
     					mc.p0 = &p0;
     					mc.p1 = &p1;
     					// mc.pos = zero	// in submodel RF
     
     					mc.orient = &vmd_identity_matrix;
    -					mc.submodel_num = submodel_list[i];
    +					mc.submodel_num = submodel_vector[i];
     
     					if ( model_collide(&mc) ) {
     						if ( mc.hit_dist < debris_hit_info->hit_time ) {
    @@ -993,7 +991,7 @@
     						}
     					}
     					// Don't look at this submodel again
    -					pmi->submodel[submodel_list[i]].collision_checked = true;
    +					pmi->submodel[submodel_vector[i]].collision_checked = true;
     				}
     
     			}
    
    patch file icon mantis-2351_proposed_patch_4.patch (16,005 bytes) 2010-12-27 02:32 +

-Relationships
+Relationships

-Notes

~0012575

Echelon9 (developer)

FUBAR, can you test with the proposed patch attached. Thanks.

This converts submodel_list to an STL vector (and also renames it to submodel_vector to be accurate). No need to bump the limit in future.

~0012577

Echelon9 (developer)

New 4th version of patch, includes switch to size_t on for loops to address signedness.

~0012578

Echelon9 (developer)

Resolved in r6895.

Assistance from FUBAR.
+Notes

-Issue History
Date Modified Username Field Change
2010-12-13 20:47 FUBAR-BDHR New Issue
2010-12-26 05:43 Echelon9 File Added: mantis-2351_proposed_patch_2.patch
2010-12-26 05:43 Echelon9 Status new => assigned
2010-12-26 05:43 Echelon9 Assigned To => Echelon9
2010-12-26 05:44 Echelon9 Note Added: 0012575
2010-12-27 00:48 Echelon9 File Deleted: mantis-2351_proposed_patch_2.patch
2010-12-27 00:48 Echelon9 File Added: mantis-2351_proposed_patch_3.patch
2010-12-27 02:32 Echelon9 File Added: mantis-2351_proposed_patch_4.patch
2010-12-27 02:34 Echelon9 Note Added: 0012577
2010-12-27 03:04 Echelon9 Note Added: 0012578
2010-12-27 03:04 Echelon9 Status assigned => resolved
2010-12-27 03:04 Echelon9 Fixed in Version => 3.6.13
2010-12-27 03:04 Echelon9 Resolution open => fixed
+Issue History