@@ -17,7 +17,7 @@ bool Props_inited = false;
1717
1818SCP_vector<prop_info> Prop_info;
1919
20- SCP_vector<prop> Props;
20+ SCP_vector<std::optional< prop> > Props;
2121
2222static SCP_vector<SCP_string> Removed_props;
2323
@@ -40,9 +40,13 @@ int prop_name_lookup(const char *name)
4040 Assertion (name != nullptr , " NULL name passed to prop_name_lookup" );
4141
4242 for (int i=0 ; i<static_cast <int >(Props.size ()); i++){
43- if (Props[i].objnum >= 0 ){
44- if (Objects[Props[i].objnum ].type == OBJ_PROP){
45- if (!stricmp (name, Props[i].prop_name )){
43+ auto prop = Props[i] ? &Props[i].value () : nullptr ;
44+ if (prop == nullptr ) {
45+ continue ;
46+ }
47+ if (prop->objnum >= 0 ){
48+ if (Objects[prop->objnum ].type == OBJ_PROP) {
49+ if (!stricmp (name, prop->prop_name )) {
4650 return i;
4751 }
4852 }
@@ -53,6 +57,15 @@ int prop_name_lookup(const char *name)
5357 return -1 ;
5458}
5559
60+ prop* prop_id_lookup (int id)
61+ {
62+ if (id < 0 || id >= static_cast <int >(Props.size ()) || !Props[id].has_value ()) {
63+ Assertion (false , " Could not find prop for id %d" , id);
64+ return nullptr ;
65+ }
66+ return &Props[id].value ();
67+ }
68+
5669void parse_prop_table (const char * filename)
5770{
5871 read_file_text (filename, CF_TYPE_TABLES);
@@ -257,7 +270,10 @@ int prop_create(matrix* orient, vec3d* pos, int prop_type, const char* name)
257270 pip = &(Prop_info[prop_type]);
258271
259272 Props.emplace_back (prop ());
260- propp = &Props.back ();
273+ int new_id = static_cast <int >(Props.size ()) - 1 ;
274+ propp = prop_id_lookup (new_id);
275+ Assertion (propp != nullptr , " Could not create prop!" );
276+
261277 propp->prop_info_index = prop_type;
262278
263279 if ((name == nullptr ) || (prop_name_lookup (name) >= 0 )) {
@@ -321,7 +337,7 @@ int prop_create(matrix* orient, vec3d* pos, int prop_type, const char* name)
321337
322338 int objnum = obj_create (OBJ_PROP,
323339 -1 ,
324- static_cast < int >(Props. size () - 1 ) ,
340+ new_id ,
325341 orient,
326342 pos,
327343 model_get_radius (pip->model_num ),
@@ -389,23 +405,25 @@ int prop_create(matrix* orient, vec3d* pos, int prop_type, const char* name)
389405void prop_delete (object* obj)
390406{
391407 int num = obj->instance ;
392- Assert (num >= 0 && num <= static_cast <int >(Props.size ()));
393408
394409 int objnum = OBJ_INDEX (obj);
395- Assert (Props[num].objnum == objnum );
410+ Assertion (Props[num].has_value (), " Props[%d] is already nullopt! " , num );
396411
397- prop* propp = &Props[num];
412+ prop& propp = *Props[num];
413+ Assertion (propp.objnum == objnum, " Prop object id does not match passed object!" );
398414
399- propp-> objnum = -1 ;
415+ propp. objnum = -1 ;
400416
401417 // animation::ModelAnimationSet::stopAnimations(model_get_instance(propp->model_instance_num));
402418
403419 // glow point banks
404- propp-> glow_point_bank_active .clear ();
420+ propp. glow_point_bank_active .clear ();
405421
406- model_delete_instance (propp-> model_instance_num );
422+ model_delete_instance (propp. model_instance_num );
407423
408- Props.erase (Props.begin () + num);
424+ // Leave the slot empty for the duration of the scene
425+ // The Props array will be compacted at the end of the level
426+ Props[num] = std::nullopt ;
409427}
410428
411429/* *
@@ -416,8 +434,7 @@ void prop_delete(object* obj)
416434 */
417435static void prop_model_change (int n, int prop_type)
418436{
419- Assert ( n >= 0 && n < MAX_PROPS );
420- prop* sp = &Props[n];
437+ prop* sp = prop_id_lookup (n);
421438 prop_info* sip = &(Prop_info[prop_type]);
422439 object* objp = &Objects[sp->objnum ];
423440 polymodel_instance* pmi = model_get_instance (sp->model_instance_num );
@@ -497,8 +514,7 @@ static void prop_model_change(int n, int prop_type)
497514 */
498515void change_prop_type (int n, int prop_type)
499516{
500- Assert ( n >= 0 && n < MAX_PROPS );
501- prop* sp = &Props[n];
517+ prop* sp = prop_id_lookup (n);
502518
503519 // do a quick out if we're already using the new ship class
504520 if (sp->prop_info_index == prop_type)
@@ -515,10 +531,6 @@ void change_prop_type(int n, int prop_type)
515531 prop_model_change (n, prop_type);
516532 sp->prop_info_index = prop_type;
517533
518- // get the before and after models (the new model may have only been loaded in ship_model_change)
519- auto pm = model_get (sip->model_num );
520- auto pm_orig = model_get (sip_orig->model_num );
521-
522534 // check class-specific flags
523535
524536 if (sip->flags [Prop::Info_Flags::No_collide]) // changing TO a no-collision ship class
@@ -530,10 +542,10 @@ void change_prop_type(int n, int prop_type)
530542void prop_render (object* obj, model_draw_list* scene)
531543{
532544 int num = obj->instance ;
533- Assert (num >= 0 && num <= static_cast <int >(Props.size ()));
534545
535- prop* propp = &Props[num];
536- prop_info* pip = &Prop_info[Props[num].prop_info_index ];
546+ prop* propp = prop_id_lookup (num);
547+
548+ prop_info* pip = &Prop_info[propp->prop_info_index ];
537549
538550 MONITOR_INC (NumPropsRend, 1 );
539551
@@ -637,9 +649,14 @@ void spawn_test_prop()
637649
638650void props_level_close ()
639651{
640- while (!Props.empty ()) {
641- prop_delete (&Objects[Props.back ().objnum ]);
652+ for (auto & opt_prop : Props) {
653+ if (opt_prop.has_value ()) {
654+ prop_delete (&Objects[opt_prop->objnum ]);
655+ }
642656 }
657+
658+ // Clear all props and empty prop slots
659+ Props.clear ();
643660}
644661
645662
@@ -648,14 +665,13 @@ int prop_check_collision(object* prop_obj, object* other_obj, vec3d* hitpos, col
648665{
649666 mc_info mc;
650667
651- Assert (prop_obj->type == OBJ_PROP);
668+ Assertion (prop_obj->type == OBJ_PROP, " Object is not a prop! " );
652669
653670 int num = prop_obj->instance ;
654671
655- Assert (num >= 0 && num < (int )Props.size ());
656- Assert (Props[num].objnum == OBJ_INDEX (prop_obj));
657-
658- prop* propp = &Props[num];
672+ prop* propp = prop_id_lookup (num);
673+ Assertion (propp->objnum == OBJ_INDEX (prop_obj), " Prop object id does not match passed object!" );
674+
659675 prop_info* prinfo = &Prop_info[propp->prop_info_index ];
660676
661677 // debris_hit_info NULL - so debris-weapon collision
@@ -839,7 +855,7 @@ int prop_check_collision(object* prop_obj, object* other_obj, vec3d* hitpos, col
839855 asteroid* astp = &Asteroids[instance];
840856 mc.model_instance_num = astp->model_instance_num ;
841857 mc.model_num = Asteroid_info[astp->asteroid_type ].subtypes [astp->asteroid_subtype ].model_number ;
842- mc.submodel_num - 1 ;
858+ mc.submodel_num - 1 ; // Typo from asteroth?
843859 }
844860
845861 mc.orient = &heavy_obj->orient ; // The object's orient
@@ -862,7 +878,7 @@ int prop_check_collision(object* prop_obj, object* other_obj, vec3d* hitpos, col
862878 }
863879 } else { // prop is the heavy object
864880 mc.flags = (MC_CHECK_MODEL | MC_CHECK_SPHERELINE);
865- int instance = heavy_obj->instance ;
881+ // int instance = heavy_obj->instance;
866882
867883 // fill the appropriate model data
868884 mc.model_instance_num = propp->model_instance_num ;
0 commit comments