Strangely enough, i've been working with this fairly recently. After searching around for ages, I came across a function. I cant remember where I found it, of who made it, but its fairly accurate. The Y coordinate is too high (appears below) around the sides of the screen, at least it is for me.
Btw, this is all client sided. You definitely should use the server to get positions
function worldToScreen(%posb)
{
%self = serverConnection.getControlObject(); //Replace with player
%posa = getMyEyePoint(); //Replace with player eyepos
%fv = %self.getMuzzleVector(0); //Replace with eye vector
%yp = getYawPitch(%fv,%posa,%posb);
%yaw = getWord(%yp,0);
%pitch = getWord(%yp,1);
%halfx = getWord($Pref::Video::Resolution,0) / 2;
%halfy = getWord($Pref::Video::Resolution,1) / 2;
%fovx = mDegToRad($CameraFov / 2);
%fovy = mATan(mTan(%fovx) * %halfy / %halfx,1);
if(%yaw > %fovx)
%yaw = %fovx;
if(%yaw < -%fovx)
%yaw = -%fovx;
if(%pitch > %fovy)
%pitch = %fovy;
if(%pitch < -%fovy)
%pitch = -%fovy;
%ratx = mTan(%yaw) * mCos(%fovx) / mSin(%fovx);
%raty = mTan(%pitch) * mCos(%fovy) / mSin(%fovy);
%x = mFloatLength(%ratx * %halfx + %halfx - getWord(%gui.extent,0) / 2,0);
%y = mFloatLength(%raty * %halfy + %halfy - getWord(%gui.extent,1) / 2,0);
%y -= (%x-getWord(%gui.extent, 0))/100;
return %x SPC %y;
}
function mRound(%num)
{
return mFloatLength(%num, 0);
}
function getYawPitch(%fv,%posa,%posb)
{
%x = getWord(%fv,0);
%y = getWord(%fv,1);
%vv = vectorNormalize(vectorSub(%posb,getWords(%posa,0,2)));
%xx = getWord(%vv,0);
%yy = getWord(%vv,1);
%yaw = mATan(%xx,%yy) - mATan(%x,%y);
%pitch = mATan(getWord(%fv,2),mSqrt(%x * %x + %y * %y )) -
mATan(getWord(%vv,2),mSqrt(%xx * %xx + %yy * %yy));
if(%yaw > 3.14159) %yaw = -6.28318 + %yaw;
if(%yaw < -3.14159) %yaw = 6.28318 + %yaw;
if(%pitch > 3.14159) %pitch = -6.28318 + %pitch;
if(%pitch < -3.14159) %pitch = 6.28318 + %pitch;
return %yaw SPC %pitch;
}