My Rant About the "shoot" Command
I wrote a few functions in the hope that I could use strings to keep track of all the information for a projectile shot using the "shoot" command.
But something went wrong.  When you're done reading what I did here, skip down to the bottom to see what I did to fix this problem ;)
//Projectile Tracking This is used to track the x,y,z cords of projectiles shot using the "shoot" command.  (Keeps track of multiple projectiles)
function Initialize(){
  this.za=3.14/4;
  this.p=1.2;
  this.hs=cos(this.za)*this.p;
  this.time=(sin(this.za)*this.p)*2;
  if (playerdir==0)this.a=3.14/2;
  if (playerdir==1)this.a=3.14;
  if (playerdir==2)this.a=3.14*1.5;
  if (playerdir==3)this.a=0;
  insertstring trackaxyt,this.ti,#v(this.time);
  insertstring trackaxyt,this.ti+1,#v(playerx);
  insertstring trackaxyt,this.ti+2,#v(playery);
  insertstring trackaxyt,this.ti+3,#v(this.a);
  this.ti+=4;
  setshootparams #p(0),#p(1);
  shoot playerx,playery,playerz,this.a,3.14/4,1.2,gralats,0;
}
//End of Function
This function needs to be called when you want the projectile to be shot (as a matter of fact, it contains the "shoot command"); most commonly this should be put in a if(weaponfired) thingy.  This function will prepare the necessary string and variables needed to track the values of a shot projectile.
Define
this.za = This is the "zangle" the projectile is fired at.  3.14/2 makes the projectile shoot straight up, 0 makes it horizontal, and you can put anything in between those values for "zangle".  For those of you unfamiliar with Trig, 3.14/4 will yeild a 45° angle, which will make the projectile fly the furthest with minimal power.
this.p = This is the power used to shoot the projectile.  0 makes it travel like an old-model arrow, but values larger than that will make the projectile fall, eventually.
I assigned "this.a" (which is the angle the projectile is shot at) based on the direction the player is facing, you may want to do it slightly differently for your own needs.
Other than that, those are the only two vars YOU need to define, but you will need to change the parameters in setshootparams.

//Deleting a Tracked Projectile Function
function DeleteProjectile(){
  this.c=0;
  for (i=i;this.c<4;this.c++){
    deletestring trackaxyt,i;
  }
  this.ti-=4;
  i-=4;
}
//End of Script
This function exists merely to make the NPC discontinue tracking a projectile it was already tracking.
Define
n/a

function StringTracking(){
  for (i=0;i<this.ti;i+=4){
    this.temp=strtofloat(#I(trackaxyt,i))-.1;
    if(this.temp<0){
      DeleteProjectile();
    }
    }else if (this.temp>0){
      replacestring trackaxyt,i,#v(this.temp);
      this.temp=strtofloat(#I(trackaxyt,i+1))+(cos(strtofloat(#I(trackaxyt,i+3)))*this.hs);
      replacestring trackaxyt,i+1,#v(this.temp);
      this.temp=strtofloat(#I(trackaxyt,i+2))-(sin(strtofloat(#I(trackaxyt,i+3)))*this.hs);
      replacestring trackaxyt,i+2,#v(this.temp);
    }
    if (!this.ti<0)timeout=.05;
  }
}
//End of Function
This function needs to be called within a timeout, the timeout does not have to be looped, since this function automatically takes care of that, however the Initialize() function does not initialize the timeout, so you will have to do that yourself.  What this does is every timeout it will get the z value of the projectile (which starts the same as the "this.time" constant) and if the projectile is still moving on the z plane (it will still be moving on the z plane so long as the projectile has NOT struck anything) then it will update the value of the projectile's x,y, and z cords.  If the projectile has struck the ground (z has returned to 0) then it will erase all the tracking info for that particular projectile, and continue tracking the others.
Define
There is nothing to define in this function, however there is plenty of room for expansion.

The "betterthanshoot" Function
So even after all of that script, you can make the projectile do something when it lands, it can test for walls, compus, players, npc, etc.  But if it does make a collision, and my functions do an action to get rid of the tracked projectile, the image drawn by the Graal engine continues to make, and continues to check for NPC to call "actionprojectile" on.  My solution was to just put a NPC right where the projectile landed to sort of :absorb" the projectile, and to stop the default one from moving.

But after I realized that, I figured I might as well use all the functions I just wrote, and make my own shoot command, with more options, and on top of that, is fully compatible with the old shoot command.  Since I do not have an upgraded server, the only thing MY shoot command needs to do to be compatible with the old one is to "triggeraction projectile" on all players and NPCs that it hits... which isn't difficult at all.

The following functions are the same three function that appear above... only different.

//Function for Deleting the Projectile
function DeleteString(){
  this.c=0;
  for (i=i;this.c<5;this.c++){
    deletestring trackaxyt,i;
  }
  this.ti-=5;
  i-=5;
}
//End of Script

This one happens to be the exact same, except the counters go up to 5 now.

//Tracking the Projectiles
function StringTracking(){
  for (i=0;i<this.ti;i+=5){
    this.px=strtofloat(#I(trackaxyt,i+2));
    this.py=strtofloat(#I(trackaxyt,i+3));
    this.pz=strtofloat(#I(trackaxyt,i+4));
    this.time=strtofloat(#I(trackaxyt,i));
    if(this.pz<0||this.px<-5||this.px>70||this.py<-5||this.py>70){
      for (i2=0;i2<this.ti;i2++)hideimg i2;
      DeleteString();
    }else{
      if (!this.time==-1)this.time-=.1;
      else this.time=0;
      this.px+=cos(strtofloat(#I(trackaxyt,i+1)))*this.hs;
      this.py-=sin(strtofloat(#I(trackaxyt,i+1)))*this.hs;
      this.pz+=this.time;
      if (!this.time==0)replacestring trackaxyt,i,#v(this.time);
      replacestring trackaxyt,i+2,#v(this.px);
      replacestring trackaxyt,i+3,#v(this.py);
      replacestring trackaxyt,i+4,#v(this.pz);
      showimg2 i,Image,this.px,this.py,this.pz;
    }
  }
  if (this.ti>0)timeout=.05;
}
//End of Script
The main differences here are: the inclusion of another string (necessary now that I'm shooting my own projectiles), another for loop just for hiding images (necessary to remove those pesky images that just don't want to go away), and the incluse of some "this.time" checks.  I added the "this.time" stuff so that the user of these functions may make the "zangle" 0 and have it work like the old "shoot" command worked (where 0 for a zangle made the projectile shot horizontally without falling to the ground).  Be sure to change "Image" in the "showimg2" command with the filename of your image.

//Initializing the Vars
function Initialize(){
  this.za=0;
  this.p=1.2;
  this.hs=cos(this.za)*this.p;
  if (!this.za==0)this.vs=sin(this.za)*this.p;
  else this.vs=-1;
  if (keydown(0)&&keydown(1))this.a=3.14*.75;
  else if (keydown(0)&&keydown(3))this.a=3.14*.25;
  else if (keydown(2)&&keydown(1))this.a=3.14*1.25;
  else if (keydown(2)&&keydown(3))this.a=3.14*1.75;
  else if (playerdir==0)this.a=3.14/2;
  else if (playerdir==1)this.a=3.14;
  else if (playerdir==2)this.a=3.14*1.5;
  else if (playerdir==3)this.a=0;
  insertstring trackaxyt,this.ti,#v(this.vs);
  insertstring trackaxyt,this.ti+1,#v(this.a);
  insertstring trackaxyt,this.ti+2,#v(playerx);
  insertstring trackaxyt,this.ti+3,#v(playery);
  insertstring trackaxyt,this.ti+4,#v(playerz);
  hideimg this.ti;
  showimg2 this.ti,Image,playerx,playery,playerz;
  this.ti+=5;
  hideimg this.ti;
}
//End of Script
This is really the same as the other one too, as far as the variables you can define go.  Notice that I did include a few "keydown" checks, I did this so the player can shoot the projectile at angles as well as Left, Right, Up, and Down.  Also, the main difference here is that I replaced the "shoot" command with a "showimg" command, so you ought to replace "Image" with the correct filename of the image you want to use for your projectile.

Example Usage of My Shoot Functions
Here is a real simple way to see these functions work, just be sure to include the aformentioned functions within the script of the NPC.
//GraalScript
if (playertouchsme){
  toweapons ProjectileWep;
  hide;
}
if (weaponfired){
  Initialize();
  timeout=.05;
}
if (timeout){
  StringTracking();
}
//End of Script

This of course would make a weapon that when shot, will shoot a projectile =)