Heres the trimmed down version ready to run. It LOOKS to produce
objects that behave exactly the same to me. But its your baby.

Ive ditched the custom struct as it made things really messy, and
Ive implemented a #define based replacement that I would use.

It does all the same things as before, just all driven from the
Code:
...
var idx;   for(idx=0; idx<Top_obj; idx++)
...
loop in the main function loop,so it get run as close
to once per frame as the 3DGS engine will allow.

The separate new_bomb and new_fragment(was new_sprite) are only run once
per new object,
in-between frames and close when completed. So no memory wastage there.

The key "F" will spew out Fragments manually, like you had the "E" key doing,
and Ive added a "B" key to spew out Bombs the same way, just a bit slower.

Just beware,
thres no check to see if you go over 10,000 objects (bombs + fragments), and
it WILL crash if you over as thats how big the storage array is. But if you
ever hit it, I would be surprised.

Any questions, fire away.

Code:
#include <acknex.h>
#include <default.c>

var num_boxes = 0;
var num_fragments = 0;

d3d_alpharef = 180;


ENTITY* Objects[10000];
#define otype       skill20      //0=bomb 1=fragment
#define velx        skill21
#define vely        skill22
#define velz        skill23
#define lifetime    skill25      
//#define ????????  skill26      
//#define ????????  skill27      
var Top_obj=1;      //'current' highest used index for optimising main-loop check



PANEL* panDisplay =
{
   digits(535, 10, "boxes = %0.f", "Courier#18", 1, num_boxes);
   digits(535, 40, "fragments = %0.f", "Courier#18", 1, num_fragments);
   flags = VISIBLE;
}

 
function new_fragment(VECTOR* pos )
{
   var c1;   for(c1=0; c1<35; c1++)
   {
      var idx;   for(idx=0; idx<1000; idx++)   if(Objects[idx]==NULL)   break;
      Objects[idx] = ent_create("bluspark.bmp",vector(pos.x,pos.y,pos.z),NULL);
      if(idx>Top_obj)   Top_obj=idx;   //raise Top_obj if this is highest
      Objects[idx].otype = 1;    //set to "fragment" type
      Objects[idx].lifetime = 200+random(500);
      //Objects[idx].pan = 180 - angle1;
      vec_scale(Objects[idx].scale_x,1.925);
      Objects[idx].roll = 1;
      vec_set(Objects[idx].velx,vector((random(25)-12.5)/2,(random(25)-12.5)/2,(-5+random(25))*5));
      Objects[idx].skill26 = 180 - random(100);
      set(Objects[idx],BRIGHT|OVERLAY|TRANSLUCENT|PASSABLE|MOVE);
      Objects[idx].alpha = 50;
      //do_sprite(Objects[idx],Objects[idx].velx,Objects[idx].vely,Objects[idx].velz);
      num_fragments += 1;
   }
}


function new_bomb()
{
   wait(1);
   var idx;   for(idx=0; idx<1000; idx++)   if(Objects[idx]==NULL)   break;
   Objects[idx] = ent_create("cube_smaller.mdl",vector(0,0,800),NULL);
   if(idx>Top_obj)   Top_obj=idx;   //raise Top_obj if this is highest
   Objects[idx].otype = 0;    //set to "bomb" type
   vec_scale(Objects[idx].scale_x,16.925);
   Objects[idx].lifetime = 500 + random(1000);
   wait(1);
   c_setminmax(Objects[idx]);
   phent_settype (Objects[idx], PH_RIGID, PH_SPHERE); // set the physics entity type
   phent_setmass (Objects[idx], 200, PH_SPHERE); // and its mass
   phent_setfriction (Objects[idx], 68); // set the friction
   phent_setdamping (Objects[idx], 5, 5); // set the damping
   phent_setelasticity (Objects[idx], 62, 12); // set the elasticity
   var dampener = 0.285;
   phent_addvelglobal(Objects[idx], vector((-50+random(100))*dampener,(-50+random(100))*dampener,(-5+random(10))*dampener), vector(100,0,0) );
   num_boxes += 1;
}


function main()
{
   var idx;   for(idx=0; idx<1000; idx++)   Objects[idx]=NULL;   // initialise object array
   video_mode=9;
   fps_max = 60;
   max_entities = 15000;
   max_nexus = 100000;
   vec_set(screen_color,vector(0,0,0));
   level_load("");
   wait(1);
   ph_setautodisable(0.00001, 0.0002, 4, 41); // turn on and set default values

   ENTITY* FLOOR = ent_create ("plain3d1.mdl", vector(-400, 0, -50), NULL); // create the floor
   FLOOR.scale_x=5000;
   FLOOR.scale_y=5000;
   FLOOR.scale_z=30;
   vec_set(FLOOR.blue,nullvector);
   FLOOR.ambient = 25;
   set(FLOOR,LIGHT);

   vec_set(camera.x,vector(5500,20,250));
   camera.arc = 110;
   camera.pan = 180;
   camera.ambient = -92; 

   ph_setgravity (vector(0, 0, -886)); // set the gravity
   
   var new_ball_delay = 0;
   while (1)
   {
      new_ball_delay -= 1;
      
      // CONTROLS
      mouse_pos.x = mouse_cursor.x;
      mouse_pos.y = mouse_cursor.y;
      camera.pan -= mouse_force.x * 26;
      camera.tilt += mouse_force.y * 26;
      mouse_pos.x = 160;
      mouse_pos.y = 120;
      if(key_cuu) camera.x -= 52 * time_step; 
      if(key_cud) camera.x += 52 * time_step; 
      if(key_cul) camera.y += 52 * time_step;
      if(key_cur) camera.y -= 52 * time_step;   
      if(key_ins) camera.z -= 52 * time_step;
      if(key_del) camera.z += 52 * time_step;
      if(mouse_left)      camera.ambient += 1;
      if(mouse_right)     camera.ambient -= 1;
      if((key_f)&&(new_ball_delay<0))
      {
         new_fragment(vector(0,0,800));
         new_ball_delay = 1;
      }
      if((key_b)&&(new_ball_delay<0))
      {
         new_bomb();
         new_ball_delay = 5;
      }
      //
      if (random(100)>97)   new_bomb();
      //
      var idx;   for(idx=0; idx<Top_obj; idx++)   //check all possible objects
      {   if(Objects[idx]!=NULL)      //if not empty,  then check it
         {   if(Objects[idx].otype==0)   //if its a bomb,  do this
            {   Objects[idx].lifetime -= 2;   //reduce bomb counter   
               if(Objects[idx].lifetime<=0)
               {   new_fragment(Objects[idx].x);   //trigger explosion
                  phent_settype(Objects[idx], NULL, NULL);    //remove object from physics
                  ent_remove(Objects[idx]);      //remove timed-out bomb
                  Objects[idx] = NULL;            //cleanup empty pointer
                  if(Top_obj==idx)   Top_obj--;   //lower Top_obj if it was this one.
                  num_boxes -= 1;
               }
            }
            else if(Objects[idx].otype==1)      //if its a fragment,  do this
            {   Objects[idx].lifetime -= 15;   //reduce counter
               if (random(100)>97)      Objects[idx].lifetime += 150;   //boost counter
               vec_add(Objects[idx].x, Objects[idx].velx);
               Objects[idx].z -= Objects[idx].skill27/8;
               Objects[idx].skill27 += 1;
               if (Objects[idx].lifetime>Objects[idx].skill26)
               {   Objects[idx].scale_x = (Objects[idx].lifetime * Objects[idx].lifetime)/14000;
                  Objects[idx].scale_y = (Objects[idx].lifetime * Objects[idx].lifetime)/14000;
               }
               if (Objects[idx].lifetime<10)      Objects[idx].alpha = Objects[idx].lifetime * 0.01;
               if(Objects[idx].lifetime<=0)
               {   ent_remove(Objects[idx]);      //remove timed-out fragment
                  Objects[idx] = NULL;            //cleanup empty pointer
                  if(Top_obj==idx)   Top_obj--;   //lower Top_obj if it was this one.
                  num_fragments -= 1;
               }
            }
         }
      }   
      //
      wait(1);
   }
}


PS If you REALLLY want to go back to using your custom struct, ask away
and I'll look into it but it may be too much work. For me anyway.


"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial