Along with the tome of battle scripts, this function is sufficient to fire arrows and can easily be modified for other projectiles.
float ShootArrow(object oPC, object oTarget, object oWeapon, int bDoAttack = TRUE, int bBallistic = FALSE, int nDMG = 0, int nATTACK = 0) {
int nLauncherBaseItemType = GetBaseItemType(oWeapon);
if (nLauncherBaseItemType != BASE_ITEM_LONGBOW && nLauncherBaseItemType != BASE_ITEM_SHORTBOW) nLauncherBaseItemType = BASE_ITEM_SHORTBOW;
float fDist = 0.0;
float fDelay = 0.0;
location lAttacker = GetLocation(oPC);
location lTarget = GetLocation(oTarget);
int nHit = 1;
if (bDoAttack) nHit = StrikeAttackRoll(oWeapon,oTarget,nATTACK);
int nPathType = PROJECTILE_PATH_TYPE_BALLISTIC_LAUNCHED;
if (bBallistic) nPathType = PROJECTILE_PATH_TYPE_BALLISTIC;
float fTravelTime = GetProjectileTravelTime(lAttacker,lTarget,nPathType);
SpawnItemProjectile(oPC,oTarget,lAttacker,lTarget,nLauncherBaseItemType,nPathType,nHit,0);
if (bDoAttack) DelayCommand(fTravelTime,StrikeWeaponDamage(oWeapon,nHit,oTarget,nDMG));
if (nHit == 0) return 0.0;
return fTravelTime;
}