View Issue Details

IDProjectCategoryView StatusLast Update
0002351FSSCPtablespublic2010-12-27 08:04
ReporterFUBAR-BDHR Assigned ToEchelon9  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Product Version3.6.13 
Fixed 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.

Activities

Echelon9

2010-12-26 10:44

developer   ~0012575

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.

2010-12-27 05:48

 

mantis-2351_proposed_patch_3.patch (15,843 bytes)   
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;
 				}
 
 			}

2010-12-27 07:32

 

mantis-2351_proposed_patch_4.patch (16,005 bytes)   
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;
 				}
 
 			}

Echelon9

2010-12-27 07:34

developer   ~0012577

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

Echelon9

2010-12-27 08:04

developer   ~0012578

Resolved in r6895.

Assistance from FUBAR.

Issue History

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