Skip to content

Commit 609ed4e

Browse files
Remove the fireball limit (#3224)
* Remove the fireball limit * Handle Feedback (Without the main PC, so really hoping I don't do any typos)
1 parent d716433 commit 609ed4e

File tree

5 files changed

+115
-110
lines changed

5 files changed

+115
-110
lines changed

code/fireball/fireballs.cpp

Lines changed: 86 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ int Knossos_warp_ani_used;
3131

3232
#define MAX_WARP_LOD 0
3333

34-
fireball Fireballs[MAX_FIREBALLS];
34+
constexpr int INTITIAL_FIREBALL_CONTAINTER_SIZE = 256;
35+
36+
SCP_vector<fireball> Fireballs;
37+
SCP_vector<int> Unused_fireball_indices;
3538

3639
fireball_info Fireball_info[MAX_FIREBALL_TYPES];
3740

3841
int fireball_used[MAX_FIREBALL_TYPES];
3942

40-
int Num_fireballs = 0;
4143
int Num_fireball_types = 0;
4244

4345
bool fireballs_inited = false;
@@ -435,8 +437,6 @@ void fireball_load_data()
435437
// This will get called at the start of each level.
436438
void fireball_init()
437439
{
438-
int i;
439-
440440
if ( !fireballs_inited ) {
441441
// Do all the processing that happens only once
442442
fireball_parse_tbl();
@@ -446,10 +446,10 @@ void fireball_init()
446446
}
447447

448448
// Reset everything between levels
449-
Num_fireballs = 0;
450-
for (i=0; i<MAX_FIREBALLS; i++ ) {
451-
Fireballs[i].objnum = -1;
452-
}
449+
Fireballs.clear();
450+
Fireballs.reserve(INTITIAL_FIREBALL_CONTAINTER_SIZE);
451+
Unused_fireball_indices.clear();
452+
Unused_fireball_indices.reserve(INTITIAL_FIREBALL_CONTAINTER_SIZE);
453453

454454
// Goober5000 - reset Knossos warp flag
455455
Knossos_warp_ani_used = 0;
@@ -467,27 +467,25 @@ void fireball_delete( object * obj )
467467
fireball *fb;
468468

469469
num = obj->instance;
470+
// Make sure the new system works fine.
471+
Assert(obj->instance > -1);
472+
Assert(static_cast<int>(Fireballs.size()) > obj->instance);
470473
fb = &Fireballs[num];
471474

472475
Assert( fb->objnum == OBJ_INDEX(obj));
473476

474477
Fireballs[num].objnum = -1;
475-
Num_fireballs--;
476-
Assert( Num_fireballs >= 0 );
478+
Unused_fireball_indices.push_back(num);
477479
}
478480

479481
/**
480482
* Delete all active fireballs, by calling obj_delete directly.
481483
*/
482484
void fireball_delete_all()
483485
{
484-
fireball *fb;
485-
int i;
486-
487-
for ( i = 0; i < MAX_FIREBALLS; i++ ) {
488-
fb = &Fireballs[i];
489-
if ( fb->objnum != -1 ) {
490-
obj_delete(fb->objnum);
486+
for (auto& current_fireball : Fireballs) {
487+
if ( current_fireball.objnum != -1 ) {
488+
obj_delete(current_fireball.objnum);
491489
}
492490
}
493491
}
@@ -499,6 +497,8 @@ void fireball_set_framenum(int num)
499497
fireball_info *fd;
500498
fireball_lod *fl;
501499

500+
Assert(static_cast<int>(Fireballs.size()) > num);
501+
502502
fb = &Fireballs[num];
503503
fd = &Fireball_info[Fireballs[num].fireball_info_index];
504504

@@ -537,6 +537,9 @@ int fireball_is_perishable(object * obj)
537537

538538
num = obj->instance;
539539
objnum = OBJ_INDEX(obj);
540+
// Make sure the new system works fine.
541+
Assert(obj->instance > -1);
542+
Assert((int)Fireballs.size() > obj->instance);
540543
Assert( Fireballs[num].objnum == objnum );
541544

542545
fb = &Fireballs[num];
@@ -553,50 +556,16 @@ int fireball_is_perishable(object * obj)
553556
return 0;
554557
}
555558

556-
557-
/**
558-
* There are too many fireballs, so delete the oldest small one
559-
* to free up a slot.
560-
*
561-
* @return The fireball slot freed.
562-
*/
563-
int fireball_free_one()
564-
{
565-
fireball *fb;
566-
int i;
567-
568-
int oldest_objnum = -1, oldest_slotnum = -1;
569-
float lifeleft, oldest_lifeleft = 0.0f;
570-
571-
for ( i = 0; i < MAX_FIREBALLS; i++ ) {
572-
fb = &Fireballs[i];
573-
574-
// only remove the ones that aren't warp effects
575-
if ( (fb->objnum >= 0) && fireball_is_perishable(&Objects[fb->objnum]) ) {
576-
577-
lifeleft = fb->total_time - fb->time_elapsed;
578-
if ( (oldest_objnum < 0) || (lifeleft < oldest_lifeleft) ) {
579-
oldest_slotnum = i;
580-
oldest_lifeleft = lifeleft;
581-
oldest_objnum = fb->objnum;
582-
}
583-
break;
584-
}
585-
}
586-
587-
if ( oldest_objnum > -1 ) {
588-
obj_delete(oldest_objnum);
589-
}
590-
return oldest_slotnum;
591-
}
592-
593559
int fireball_is_warp(object * obj)
594560
{
595561
int num, objnum;
596562
fireball *fb;
597563

598564
num = obj->instance;
599565
objnum = OBJ_INDEX(obj);
566+
// Make sure the new system works fine.
567+
Assert(obj->instance > -1);
568+
Assert(static_cast<int>(Fireballs.size()) > obj->instance);
600569
Assert( Fireballs[num].objnum == objnum );
601570

602571
fb = &Fireballs[num];
@@ -641,6 +610,9 @@ void fireball_process_post(object * obj, float frame_time)
641610

642611
num = obj->instance;
643612
objnum = OBJ_INDEX(obj);
613+
// Make sure the new system works fine.
614+
Assert(obj->instance > -1);
615+
Assert(static_cast<int>(Fireballs.size()) > obj->instance);
644616
Assert( Fireballs[num].objnum == objnum );
645617

646618
fb = &Fireballs[num];
@@ -665,6 +637,10 @@ float fireball_lifeleft( object *obj )
665637

666638
num = obj->instance;
667639
objnum = OBJ_INDEX(obj);
640+
// Make sure the new system works fine.
641+
Assert(obj->instance > -1);
642+
Assert(static_cast<int>(Fireballs.size()) > obj->instance);
643+
668644
Assert( Fireballs[num].objnum == objnum );
669645

670646
fb = &Fireballs[num];
@@ -680,6 +656,10 @@ float fireball_lifeleft_percent( object *obj )
680656
int num, objnum;
681657
fireball *fb;
682658

659+
// Make sure the new system works fine.
660+
Assert(obj->instance > -1);
661+
Assert(static_cast<int>(Fireballs.size()) > obj->instance);
662+
683663
num = obj->instance;
684664
objnum = OBJ_INDEX(obj);
685665
Assert( Fireballs[num].objnum == objnum );
@@ -781,10 +761,8 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
781761
{
782762
int n, objnum, fb_lod;
783763
object *obj;
784-
fireball *fb;
785764
fireball_info *fd;
786765
fireball_lod *fl;
787-
788766
Assert( fireball_type > -1 );
789767
Assert( fireball_type < Num_fireball_types );
790768

@@ -800,23 +778,21 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
800778
}
801779
}
802780

803-
if ( (Num_fireballs >= MAX_FIREBALLS) || (Num_objects >= MAX_OBJECTS) ) {
781+
if (Num_objects >= MAX_OBJECTS) {
782+
return -1;
783+
}
804784

805-
// out of slots, so free one up.
806-
n = fireball_free_one();
807-
if ( n < 0 ) {
808-
return -1;
809-
}
810-
} else {
811-
for ( n = 0; n < MAX_FIREBALLS; n++ ) {
812-
if ( Fireballs[n].objnum < 0 ) {
813-
break;
814-
}
815-
}
816-
Assert( n != MAX_FIREBALLS );
785+
786+
if (!Unused_fireball_indices.empty()) {
787+
n = Unused_fireball_indices.back();
788+
Unused_fireball_indices.pop_back();
789+
}
790+
else {
791+
n = static_cast<int>(Fireballs.size());
792+
Fireballs.emplace_back();
817793
}
818794

819-
fb = &Fireballs[n];
795+
fireball* new_fireball = &Fireballs[n];
820796

821797
// get an lod to use
822798
fb_lod = fireball_get_lod(pos, fd, size);
@@ -833,13 +809,13 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
833809
}
834810
fl = &fd->lod[fb_lod];
835811

836-
fb->lod = (char)fb_lod;
812+
new_fireball->lod = (char)fb_lod;
837813

838-
fb->flags = extra_flags;
839-
fb->warp_open_sound_index = warp_open_sound;
840-
fb->warp_close_sound_index = warp_close_sound;
841-
fb->warp_open_duration = (warp_open_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_open_duration;
842-
fb->warp_close_duration = (warp_close_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_close_duration;
814+
new_fireball->flags = extra_flags;
815+
new_fireball->warp_open_sound_index = warp_open_sound;
816+
new_fireball->warp_close_sound_index = warp_close_sound;
817+
new_fireball->warp_open_duration = (warp_open_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_open_duration;
818+
new_fireball->warp_close_duration = (warp_close_duration < 0.0f) ? WARPHOLE_GROW_TIME : warp_close_duration;
843819

844820
matrix orient;
845821
if(orient_override != NULL){
@@ -856,58 +832,53 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
856832
default_flags.set(Object::Object_Flags::Renders);
857833
objnum = obj_create(OBJ_FIREBALL, parent_obj, n, &orient, pos, size, default_flags);
858834

859-
if (objnum < 0) {
860-
Int3(); // Get John, we ran out of objects for fireballs
861-
return objnum;
862-
}
863-
864835
obj = &Objects[objnum];
865836

866-
fb->fireball_info_index = fireball_type;
867-
fb->fireball_render_type = render_type;
868-
fb->time_elapsed = 0.0f;
869-
fb->objnum = objnum;
870-
fb->current_bitmap = -1;
837+
new_fireball->fireball_info_index = fireball_type;
838+
new_fireball->fireball_render_type = render_type;
839+
new_fireball->time_elapsed = 0.0f;
840+
new_fireball->objnum = objnum;
841+
new_fireball->current_bitmap = -1;
871842

872-
switch( fb->fireball_render_type ) {
843+
switch( new_fireball->fireball_render_type ) {
873844

874845
case FIREBALL_MEDIUM_EXPLOSION:
875-
fb->orient = (myrand()>>8) & 7; // 0 - 7
846+
new_fireball->orient = (myrand()>>8) & 7; // 0 - 7
876847
break;
877848

878849
case FIREBALL_LARGE_EXPLOSION:
879-
fb->orient = (myrand()>>8) % 360; // 0 - 359
850+
new_fireball->orient = (myrand()>>8) % 360; // 0 - 359
880851
break;
881852

882853
case FIREBALL_WARP_EFFECT:
883854
// Play sound effect for warp hole opening up
884-
fireball_play_warphole_open_sound(ship_class, fb);
855+
fireball_play_warphole_open_sound(ship_class, new_fireball);
885856

886857
// warp in type
887858
if (reverse) {
888-
fb->orient = 1;
859+
new_fireball->orient = 1;
889860
// if warp out, then reverse the orientation
890861
vm_vec_scale( &obj->orient.vec.fvec, -1.0f ); // Reverse the forward vector
891862
vm_vec_scale( &obj->orient.vec.rvec, -1.0f ); // Reverse the right vector
892863
} else {
893-
fb->orient = 0;
864+
new_fireball->orient = 0;
894865
}
895866
break;
896867

897868
default:
898-
Int3();
869+
UNREACHABLE("Bad type set in fireball_create");
899870
break;
900871
}
901872

902-
if ( fb->fireball_render_type == FIREBALL_WARP_EFFECT ) {
873+
if ( new_fireball->fireball_render_type == FIREBALL_WARP_EFFECT ) {
903874
Assert( warp_lifetime >= 4.0f ); // Warp lifetime must be at least 4 seconds!
904875
if ( warp_lifetime < 4.0f )
905876
warp_lifetime = 4.0f;
906-
fb->total_time = warp_lifetime; // in seconds
877+
new_fireball->total_time = warp_lifetime; // in seconds
907878
} else {
908-
fb->total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
879+
new_fireball->total_time = i2fl(fl->num_frames) / fl->fps; // in seconds
909880
}
910-
881+
911882
fireball_set_framenum(n);
912883

913884
if ( velocity ) {
@@ -923,7 +894,6 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o
923894
vm_vec_zero(&obj->phys_info.max_rotvel);
924895
}
925896

926-
Num_fireballs++;
927897
return objnum;
928898
}
929899

@@ -1058,24 +1028,28 @@ void fireball_render(object* obj, model_draw_list *scene)
10581028

10591029
MONITOR_INC( NumFireballsRend, 1 );
10601030

1031+
// Make sure the new system works fine.
1032+
Assert(obj->instance > -1);
1033+
Assert(static_cast<int>(Fireballs.size()) > obj->instance);
1034+
10611035
num = obj->instance;
10621036
fb = &Fireballs[num];
10631037

1064-
if ( Fireballs[num].current_bitmap < 0 )
1038+
if ( fb->current_bitmap < 0 )
10651039
return;
10661040

10671041
g3_transfer_vertex(&p, &obj->pos);
10681042

10691043
switch ( fb->fireball_render_type ) {
10701044

10711045
case FIREBALL_MEDIUM_EXPLOSION: {
1072-
batching_add_volume_bitmap(Fireballs[num].current_bitmap, &p, fb->orient, obj->radius);
1046+
batching_add_volume_bitmap(fb->current_bitmap, &p, fb->orient, obj->radius);
10731047
}
10741048
break;
10751049

10761050
case FIREBALL_LARGE_EXPLOSION: {
10771051
// Make the big explosions rotate with the viewer.
1078-
batching_add_volume_bitmap_rotated(Fireballs[num].current_bitmap, &p, (i2fl(fb->orient)*PI) / 180.0f, obj->radius);
1052+
batching_add_volume_bitmap_rotated(fb->current_bitmap, &p, (i2fl(fb->orient)*PI) / 180.0f, obj->radius);
10791053
}
10801054
break;
10811055

@@ -1093,3 +1067,14 @@ void fireball_render(object* obj, model_draw_list *scene)
10931067
Int3();
10941068
}
10951069
}
1070+
1071+
// Because fireballs are only added and removed in two places, and Unused_fireball_indices is always updated in those places to contain unused indices,
1072+
// this very simple code will give you the correct count of currently existing fireballs in use.
1073+
int fireball_get_count()
1074+
{
1075+
int count = static_cast<int>(Fireballs.size()) - static_cast<int>(Unused_fireball_indices.size());
1076+
1077+
Assert (count >= 0);
1078+
1079+
return count;
1080+
}

code/fireball/fireballs.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ typedef struct fireball {
9595
} fireball;
9696
// end move
9797

98-
extern fireball Fireballs[MAX_FIREBALLS];
99-
extern int Num_fireballs;
98+
extern SCP_vector<fireball> Fireballs;
10099

101100
extern bool fireballs_inited;
102101

@@ -146,4 +145,7 @@ extern int Knossos_warp_ani_used;
146145

147146
extern bool Fireball_use_3d_warp;
148147

148+
// Cyborg - get a count of how many valid fireballs are in the mission.
149+
int fireball_get_count();
150+
149151
#endif /* _FIREBALLS_H */

0 commit comments

Comments
 (0)