Looked at the math. It seems ok, but I had some trouble wrapping my brain around it. I tried a bunch of different things and kept asking "why is the rotation changing when I get past a certain angle?" Then it dawned on me. The order of rotations is very important.
Put this line at the top of your function:
set object rotation zyx object_num
Should fix the problem! Here's some example code with the addition:
sync on
sync rate 60
autocam off
make object box 1,1,1,20
make matrix 1,1000,1000,25,25
do
gosub _move_camera
weapon_control(1,5,0,10)
sync
loop
_move_camera:
xang#=wrapvalue(xang#+mousemovey())
yang#=wrapvalue(yang#+mousemovex())
if upkey()=1 then move camera 3
if downkey()=1 then move camera -3
xrotate camera xang#
yrotate camera yang#
return
end
FUNCTION weapon_control(object_num,xOffset,yOffset,zOffset)
set object rotation zyx object_num
camAngleX#=camera angle x()
camAngleY#=camera angle y()
camAngleZ#=camera angle z()
camPosX#=camera position x()
camPosY#=camera position y()
camPosZ#=camera position z()
sx# = sin(camAngleX#) : cx# = cos(camAngleX#)
sy# = sin(camAngleY#) : cy# = cos(camAngleY#)
sz# = sin(camAngleZ#) : cz# = cos(camAngleZ#)
xPos# = camPosX# + xOffset*(cy#*cz#) + yOffset*(sx#*sy#*cz#-cx#*sz#) + zOffset*(cx#*sy#*cz#+sx#*sz#)
yPos# = camPosY# + xOffset*(cy#*sz#) + yOffset*(cx#*cz#+sx#*sy#*sz#) + zOffset*(cx#*sy#*sz#-sx#*cz#)
zPos# = camPosZ# + xOffset*(-1*sy#) + yOffset*(sx#*cy#) + zOffset*(cx#*cy#)
position object object_num,xPos#,yPos#,zPos#
set object to camera orientation object_num
ENDFUNCTION
Enjoy your day.