I'm using the basic Linden gunscript "Pop Gun" and to make debugging easier have left the bullet rezzing section in so I can see that the standard bullets do indeed hit their target.
The problem is that as I walk around the target in MouseLook the gun becomes even more inacccurate - its as if I have messed up the calculation with direction and rotation vectors.
The algorithm to fire an imaginary bullet is quite simple - the gun just generates a series of points on a line in the direction the gun is pointed towards. At each point on this path a check is made to see whether the imaginary bullet is inside the target's bounding box - if the imaginary bullet's path intersects the target bounding box then a hit is registered.
Main bullet path test loop
1) The shooter coords and direction are stored
2) Add offset of 0.1m to shooter coords to give next point
3) If point is inside target bounding box then it is hit so exit loop
4) If distance from target is larger than old distance then exit loop
5) Goto step 2
The script is shown below but as it is part of a multi-targeting system some parts have been removed. Also the parts for the MouseLook controls have been removed.
I hope that anyone famillar with the Linden gunscript can easily follow this.
====================================================
CODE
rotation rotationG; // Used to store rotation of arrow to be shot
vector forwardG; // Used to store velocity of arrow to be shot
vector positionG; // Used to store position of arrow to be shot
vector shooterPos;
list targetList; // stride = 4, name, x y z
FireAttempt()
{
// +++++ Fire Gun Init +++++
rotationG = llGetRot(); // Get current avatar mouselook direction
forwardG = llRot2Fwd(rotationG); // Convert rotation to a direction vector
shooterPos=llGetPos();
shooterPos.z += 0.75; // set for eye level
// +++++ Start Scan +++++
ScanPlayers(); // this returns the coords of the targets
TimerStart(); // delay so target list is aquired
// +++++ Fire real bullet and Sound +++++
float SPEED = 20.0; // Speed of arrow in meters/sec
integer LIFETIME = 7; // How many seconds will bullets live
// before deleting themselves
vector vel; // Used to store velocity of arrow to be shot
vector pos; // Used to store position of arrow to be shot
vel = llRot2Fwd(rotationG); // Convert rotation to a direction vector
pos = llGetPos(); // Get position of avatar to create arrow
pos = pos + vel; // Create arrow slightly in direction of travel
pos.z += 0.75; // Correct creation point upward to eye point
// from hips, so that in mouselook we see arrow
// travelling away from the camera.
vel = vel * SPEED; // Multiply normalized vector by speed
llTriggerSound("shoot", 1.0); // Make the sound of the arrow being shot
llRezObject("bullet", pos, vel, rotationG, LIFETIME);
}
}
string s2CH;
CheckIfHit2()
// generates a path for the imaginary bullet and checks each
// point to see if bullet enters target's bounding box
{ vector tpos; // target postion vector
vector box; // bounding box dimensions
integer ptr;
float dist; // distance from imaginary bullet to target center
float z_diff;// differences between target centre and imaginary bullet
float x_diff;
float y_diff;
s2CH=""; // key of identified target
do
{ ptr=idx*4; // Targets aquired are stored in a list
tpos.x=(float)llList2String(targetList,ptr+1);
tpos.y=(float)llList2String(targetList,ptr+2);
tpos.z=(float)llList2String(targetList,ptr+3);
box=<0.3,0.3,1.25>; // size of target's bounding box
// +++++ Follow gunsight vector along its line +++++
vector stepsize = <0.1,0.0,0.0>;
vector coords; // bullet postion
vector tg;
float distnow; // current distance from target
float distlast; // previous distance from target
integer done; // target found so loop finished
integer step; // step counter to limit number of steps
float distmax; // max distance bullet should travel
// +++ Set start +++
coords=shooterPos;
// +++ Find Target +++
distmax=llVecDist(coords,tpos);
llOwnerSay("Dist Max = "+(string)distmax);
distnow=distmax;
// +++++++ Path Loop +++++++
done=0;
step=0;
do
{ // +++ Find distance +++
distlast=distnow;
distnow=llVecDist(coords,tpos);
// +++ Check bounding box using IF-THENS
x_diff = llFabs(coords.x-tpos.x);
y_diff = llFabs(coords.y-tpos.y);
z_diff = llFabs(coords.z-tpos.z);
if ((x_diff>0.0000001) && (x_diff<= 0.3))
{ if ((y_diff>0.0000001) && (y_diff<= 0.3))
{ if ((z_diff>0.0000001) && (z_diff<= 1.25))
{ s2CH="*";
done=1;
}
}
}
if (x_diff<= 0.3) // debug check
{ if (y_diff<= 0.3)
{ if (z_diff<= 1.25)
{ s2CH="*";
done=1;
}
}
}
llOwnerSay("Range "+(string)distnow+" x_diff=" + (string)x_diff+" y_diff "+(string)y_diff+", z_diff=" + (string)z_diff);
// +++ Gen Next Coord +++
coords=coords+(stepsize*rotationG);
step=step+1;
}
while ((done==0) && (step<70) && (distnow<=distlast)); // ++++ END LOOP ++++
llOwnerSay("x_diff=" + (string)x_diff+" y_diff "+(string)y_diff+", z_diff=" + (string)z_diff);
}
if (s2CH=="")
{ llOwnerSay("Missed\n");
}
else
{ llOwnerSay("Hit");
}
}
// ******************* EVENTS *******************
default
{
timer()
{
// After timer expires, allow user to shoot again
// if (timerMode==TIMER_MODE_FIRE)
// { TimerCancel();
// armed = TRUE;
// }
// else
// { if (timerMode==TIMER_MODE_SCAN)
// {
TimerCancel();
scanEnabled=0;
CheckIfHit2();
// }
// }
}