Torque3D Documentation / _generateds / turretShape.cpp

turretShape.cpp

Engine/source/T3D/turret/turretShape.cpp

More...

Public Functions

ConsoleDocClass(TurretShape , "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n</a>" )
ConsoleDocClass(TurretShapeData , "@brief Defines properties <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classturretshape/">TurretShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretShape\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretShapeData\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n</a>" )
DefineEngineMethod(TurretShape , doRespawn , bool , () , "@brief Does the turret respawn after it has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">destroyed.\n\n</a>" "@returns True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">respawns.\n</a>" )
DefineEngineMethod(TurretShape , getAllowManualFire , bool , () , "@brief Get <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fire through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fire through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )
DefineEngineMethod(TurretShape , getAllowManualRotation , bool , () , "@brief Get <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> rotate through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> rotate through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )
DefineEngineMethod(TurretShape , getState , const char * , () , "@brief Get the name of the turret's current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state.\n\n</a>" "The state is one of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">following:\n\n</a><ul>" "<li>Dead - The <a href="/coding/class/classturretshape/">TurretShape</a> is destroyed.</li>" "<li>Mounted - The <a href="/coding/class/classturretshape/">TurretShape</a> is mounted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an object such as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> vehicle.</li>" "<li>Ready - The <a href="/coding/class/classturretshape/">TurretShape</a> is free <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move. The usual state.</li></ul>\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return The current state; one of: \"Dead\" , \"Mounted\" , \"Ready\"\n" )
DefineEngineMethod(TurretShape , getTurretEulerRotation , Point3F , () , "@brief Get Euler rotation of this turret's heading and pitch <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n\n</a>" "@return the orientation of the turret's heading and pitch nodes in the " "form of rotations around the X, Y and Z axes in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">degrees.\n</a>" )
DefineEngineMethod(TurretShape , setAllowManualFire , void , (bool allow) , "@brief Set <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fire through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@param allow If true then the turret may be fired through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )
DefineEngineMethod(TurretShape , setAllowManualRotation , void , (bool allow) , "@brief Set <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> rotate through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@param allow If true then the turret may be rotated through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )
DefineEngineMethod(TurretShape , setTurretEulerRotation , void , (Point3F rot) , "@brief Set Euler rotation of this turret's heading and pitch nodes in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">degrees.\n\n</a>" "@param rot The rotation in degrees. The pitch is the X component and the " "heading is the Z component. The Y component is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ignored.\n</a>" )
IMPLEMENT_CALLBACK(TurretShapeData , onMountObject , void , (SceneObject *turret, SceneObject *obj, S32 node) , (turret, obj, node) , "@brief Informs the <a href="/coding/class/classturretshapedata/">TurretShapeData</a> object that <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> player is mounting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "@param turret The <a href="/coding/class/classturretshape/">TurretShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param obj The player that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mounting.\n</a>" "@param node The node the player is mounting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@note Server side <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n</a>" )
IMPLEMENT_CALLBACK(TurretShapeData , onStickyCollision , void , (TurretShape *obj) , (obj) , "@brief Informs the TurretData object that it is now sticking <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> another <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "This callback is only called <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the TurretData::sticky property <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this Turret is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">true.\n</a>" "@param obj The Turret object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">colliding.\n</a>" "@note Server side <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n</a>" "@see TurretShape, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretData\n</a>" )
IMPLEMENT_CALLBACK(TurretShapeData , onUnmountObject , void , (SceneObject *turret, SceneObject *obj) , (turret, obj) , "@brief Informs the <a href="/coding/class/classturretshapedata/">TurretShapeData</a> object that <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> player is unmounting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "@param turret The <a href="/coding/class/classturretshape/">TurretShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param obj The player that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">unmounting.\n</a>" "@note Server side <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n</a>" )
ImplementEnumType(TurretShapeFireLinkType , "@brief How the weapons are linked <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> triggers <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretShape.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n\n</a>" )

Detailed Description

Public Variables

 EndImplementEnumType 
U32 sTriggerMask 

Public Functions

ConsoleDocClass(TurretShape , "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n</a>" )

ConsoleDocClass(TurretShapeData , "@brief Defines properties <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classturretshape/">TurretShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretShape\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretShapeData\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n</a>" )

DefineEngineMethod(TurretShape , doRespawn , bool , () , "@brief Does the turret respawn after it has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">destroyed.\n\n</a>" "@returns True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">respawns.\n</a>" )

DefineEngineMethod(TurretShape , getAllowManualFire , bool , () , "@brief Get <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fire through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fire through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )

DefineEngineMethod(TurretShape , getAllowManualRotation , bool , () , "@brief Get <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> rotate through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> rotate through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )

DefineEngineMethod(TurretShape , getState , const char * , () , "@brief Get the name of the turret's current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state.\n\n</a>" "The state is one of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">following:\n\n</a><ul>" "<li>Dead - The <a href="/coding/class/classturretshape/">TurretShape</a> is destroyed.</li>" "<li>Mounted - The <a href="/coding/class/classturretshape/">TurretShape</a> is mounted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> an object such as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> vehicle.</li>" "<li>Ready - The <a href="/coding/class/classturretshape/">TurretShape</a> is free <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> move. The usual state.</li></ul>\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@return The current state; one of: \"Dead\" , \"Mounted\" , \"Ready\"\n" )

DefineEngineMethod(TurretShape , getTurretEulerRotation , Point3F , () , "@brief Get Euler rotation of this turret's heading and pitch <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">nodes.\n\n</a>" "@return the orientation of the turret's heading and pitch nodes in the " "form of rotations around the X, Y and Z axes in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">degrees.\n</a>" )

DefineEngineMethod(TurretShape , setAllowManualFire , void , (bool allow) , "@brief Set <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fire through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@param allow If true then the turret may be fired through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )

DefineEngineMethod(TurretShape , setAllowManualRotation , void , (bool allow) , "@brief Set <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the turret is allowed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> rotate through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n\n</a>" "@param allow If true then the turret may be rotated through <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">moves.\n</a>" )

DefineEngineMethod(TurretShape , setTurretEulerRotation , void , (Point3F rot) , "@brief Set Euler rotation of this turret's heading and pitch nodes in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">degrees.\n\n</a>" "@param rot The rotation in degrees. The pitch is the X component and the " "heading is the Z component. The Y component is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ignored.\n</a>" )

IMPLEMENT_CALLBACK(TurretShapeData , onMountObject , void , (SceneObject *turret, SceneObject *obj, S32 node) , (turret, obj, node) , "@brief Informs the <a href="/coding/class/classturretshapedata/">TurretShapeData</a> object that <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> player is mounting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "@param turret The <a href="/coding/class/classturretshape/">TurretShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param obj The player that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">mounting.\n</a>" "@param node The node the player is mounting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@note Server side <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n</a>" )

IMPLEMENT_CALLBACK(TurretShapeData , onStickyCollision , void , (TurretShape *obj) , (obj) , "@brief Informs the TurretData object that it is now sticking <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> another <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "This callback is only called <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the TurretData::sticky property <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this Turret is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">true.\n</a>" "@param obj The Turret object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">colliding.\n</a>" "@note Server side <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n</a>" "@see TurretShape, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretData\n</a>" )

IMPLEMENT_CALLBACK(TurretShapeData , onUnmountObject , void , (SceneObject *turret, SceneObject *obj) , (turret, obj) , "@brief Informs the <a href="/coding/class/classturretshapedata/">TurretShapeData</a> object that <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> player is unmounting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">it.\n\n</a>" "@param turret The <a href="/coding/class/classturretshape/">TurretShape</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param obj The player that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">unmounting.\n</a>" "@note Server side <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n</a>" )

IMPLEMENT_CO_DATABLOCK_V1(TurretShapeData )

IMPLEMENT_CO_NETOBJECT_V1(TurretShape )

ImplementEnumType(TurretShapeFireLinkType , "@brief How the weapons are linked <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> triggers <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TurretShape.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">gameObjects\n\n</a>" )

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "T3D/turret/turretShape.h"
  25
  26#include "console/console.h"
  27#include "console/consoleTypes.h"
  28#include "console/engineAPI.h"
  29#include "core/stream/bitStream.h"
  30#include "math/mMath.h"
  31#include "math/mathIO.h"
  32#include "ts/tsShapeInstance.h"
  33#include "T3D/fx/cameraFXMgr.h"
  34#include "T3D/gameBase/gameConnection.h"
  35#include "T3D/physics/physicsBody.h"
  36
  37//----------------------------------------------------------------------------
  38
  39// Client prediction
  40// Trigger objects that are not normally collided with.
  41static U32 sTriggerMask = ItemObjectType     |
  42                          TriggerObjectType  |
  43                          CorpseObjectType;
  44
  45//----------------------------------------------------------------------------
  46
  47ImplementEnumType( TurretShapeFireLinkType,
  48   "@brief How the weapons are linked to triggers for this TurretShape.\n\n"
  49   "@ingroup gameObjects\n\n")
  50   { TurretShapeData::FireTogether,    "FireTogether",   "All weapons fire under trigger 0.\n" },
  51   { TurretShapeData::GroupedFire,     "GroupedFire",    "Weapon mounts 0,2 fire under trigger 0, mounts 1,3 fire under trigger 1.\n" },
  52   { TurretShapeData::IndividualFire,  "IndividualFire", "Each weapon mount fires under its own trigger 0-3.\n" },
  53EndImplementEnumType;
  54
  55IMPLEMENT_CO_DATABLOCK_V1(TurretShapeData);
  56
  57ConsoleDocClass( TurretShapeData,
  58   "@brief Defines properties for a TurretShape object.\n\n"
  59   "@see TurretShape\n"
  60   "@see TurretShapeData\n"
  61   "@ingroup gameObjects\n"
  62);
  63
  64IMPLEMENT_CALLBACK( TurretShapeData, onMountObject, void, ( SceneObject* turret, SceneObject* obj, S32 node ),( turret, obj, node ),
  65   "@brief Informs the TurretShapeData object that a player is mounting it.\n\n"
  66   "@param turret The TurretShape object.\n"
  67   "@param obj The player that is mounting.\n"
  68   "@param node The node the player is mounting to.\n"
  69   "@note Server side only.\n"
  70);
  71
  72IMPLEMENT_CALLBACK( TurretShapeData, onUnmountObject, void, ( SceneObject* turret, SceneObject* obj ),( turret, obj ),
  73   "@brief Informs the TurretShapeData object that a player is unmounting it.\n\n"
  74   "@param turret The TurretShape object.\n"
  75   "@param obj The player that is unmounting.\n"
  76   "@note Server side only.\n"
  77);
  78
  79IMPLEMENT_CALLBACK( TurretShapeData, onStickyCollision, void, ( TurretShape* obj ),( obj ),
  80   "@brief Informs the TurretData object that it is now sticking to another object.\n\n"
  81   "This callback is only called if the TurretData::sticky property for this Turret is true.\n"
  82   "@param obj The Turret object that is colliding.\n"
  83   "@note Server side only.\n"
  84   "@see TurretShape, TurretData\n"
  85);
  86
  87TurretShapeData::TurretShapeData()
  88{
  89   weaponLinkType = FireTogether;
  90
  91   shadowEnable = true;
  92
  93   zRotOnly = false;
  94
  95   startLoaded = true;
  96
  97   friction = 0;
  98   elasticity = 0;
  99
 100   sticky = false;
 101   gravityMod = 1.0;
 102   maxVelocity = 25.0f;
 103
 104   density = 2;
 105   drag = 0.5;
 106
 107   cameraOffset = 0;
 108
 109   maxHeading = 180.0f;
 110   minPitch = 90.0f;
 111   maxPitch = 90.0f;
 112
 113   headingRate = -1;
 114   pitchRate = -1;
 115
 116   headingNode = -1;
 117   pitchNode = -1;
 118   U32 i = 0;
 119   for (i=0; i<NumMirrorDirectionNodes; ++i)
 120   {
 121      pitchNodes[i] = -1;
 122      headingNodes[i] = -1;
 123   }
 124
 125   for (i=0; i<ShapeBase::MaxMountedImages; ++i)
 126   {
 127      weaponMountNode[i] = -1;
 128   }
 129   for (i = 0; i < NumRecoilSequences;i++)
 130      recoilSequence[i] = -1;
 131   pitchSequence = -1;
 132   headingSequence = -1;
 133}
 134
 135void TurretShapeData::initPersistFields()
 136{
 137   addField("zRotOnly",       TypeBool,         Offset(zRotOnly,       TurretShapeData),
 138      "@brief Should the turret allow only z rotations.\n\n"
 139      "True indicates that the turret may only be rotated on its z axis, just like the Item class.  "
 140      "This keeps the turret always upright regardless of the surface it lands on.\n");
 141
 142   addField( "weaponLinkType", TYPEID< TurretShapeData::FireLinkType >(), Offset(weaponLinkType, TurretShapeData),
 143      "@brief Set how the mounted weapons are linked and triggered.\n\n"
 144      "<ul><li>FireTogether: All weapons fire under trigger 0.</li>"
 145      "<li>GroupedFire: Weapon mounts 0,2 fire under trigger 0, mounts 1,3 fire under trigger 1.</li>"
 146      "<li>IndividualFire: Each weapon mount fires under its own trigger 0-3.</li></ul>\n"
 147      "@see TurretShapeFireLinkType");
 148
 149   addField("startLoaded",       TypeBool,       Offset(startLoaded,       TurretShapeData),
 150      "@brief Does the turret's mounted weapon(s) start in a loaded state.\n\n"
 151      "True indicates that all mounted weapons start in a loaded state.\n"
 152      "@see ShapeBase::setImageLoaded()");
 153
 154   addField("cameraOffset",      TypeF32,       Offset(cameraOffset,       TurretShapeData),
 155      "Vertical (Z axis) height of the camera above the turret." );
 156
 157   addField("maxHeading",        TypeF32,       Offset(maxHeading,         TurretShapeData),
 158      "@brief Maximum number of degrees to rotate from center.\n\n"
 159      "A value of 180 or more degrees indicates the turret may rotate completely around.\n");
 160   addField("minPitch",          TypeF32,       Offset(minPitch,           TurretShapeData),
 161      "@brief Minimum number of degrees to rotate down from straight ahead.\n\n");
 162   addField("maxPitch",          TypeF32,       Offset(maxPitch,           TurretShapeData),
 163      "@brief Maximum number of degrees to rotate up from straight ahead.\n\n");
 164
 165   addField("headingRate",       TypeF32,       Offset(headingRate,        TurretShapeData),
 166      "@brief Degrees per second rotation.\n\n"
 167      "A value of 0 means no rotation is allowed.  A value less than 0 means the rotation is instantaneous.\n");
 168   addField("pitchRate",         TypeF32,       Offset(pitchRate,          TurretShapeData),
 169      "@brief Degrees per second rotation.\n\n"
 170      "A value of 0 means no rotation is allowed.  A value less than 0 means the rotation is instantaneous.\n");
 171
 172   Parent::initPersistFields();
 173}
 174
 175void TurretShapeData::packData(BitStream* stream)
 176{
 177   Parent::packData(stream);
 178
 179   stream->writeFlag(zRotOnly);
 180
 181   stream->writeInt(weaponLinkType,NumFireLinkTypeBits);
 182
 183   stream->write(cameraOffset);
 184
 185   stream->write(maxHeading);
 186   stream->write(minPitch);
 187   stream->write(maxPitch);
 188
 189   stream->write(headingRate);
 190   stream->write(pitchRate);
 191}
 192
 193void TurretShapeData::unpackData(BitStream* stream)
 194{
 195   Parent::unpackData(stream);
 196
 197   zRotOnly = stream->readFlag();
 198
 199   weaponLinkType = (FireLinkType)stream->readInt(NumFireLinkTypeBits);
 200
 201   stream->read(&cameraOffset);
 202
 203   stream->read(&maxHeading);
 204   stream->read(&minPitch);
 205   stream->read(&maxPitch);
 206
 207   stream->read(&headingRate);
 208   stream->read(&pitchRate);
 209}
 210
 211bool TurretShapeData::preload(bool server, String &errorStr)
 212{
 213   if (!Parent::preload(server, errorStr))
 214      return false;
 215
 216   // We have mShape at this point.  Resolve nodes.
 217   headingNode = mShape->findNode("heading");
 218   pitchNode = mShape->findNode("pitch");
 219
 220   // Find any mirror pitch nodes
 221   for (U32 i = 0; i < NumMirrorDirectionNodes; ++i)
 222   {
 223      char name[32];
 224      dSprintf(name, 31, "pitch%d", i+1);
 225      pitchNodes[i] = mShape->findNode(name);
 226
 227      dSprintf(name, 31, "heading%d", i+1);
 228      headingNodes[i] = mShape->findNode(name);
 229   }
 230
 231   // Resolve weapon mount point node indexes
 232   for (U32 i = 0; i < ShapeBase::MaxMountedImages; i++) {
 233      char fullName[256];
 234      dSprintf(fullName,sizeof(fullName),"weaponMount%d",i);
 235      weaponMountNode[i] = mShape->findNode(fullName);
 236   }
 237
 238   // Recoil animations
 239   recoilSequence[0] = mShape->findSequence("light_recoil");
 240   recoilSequence[1] = mShape->findSequence("medium_recoil");
 241   recoilSequence[2] = mShape->findSequence("heavy_recoil");
 242
 243   // Optional sequences used when the turret rotates
 244   pitchSequence = mShape->findSequence("pitch");
 245   headingSequence = mShape->findSequence("heading");
 246
 247   return true;
 248}
 249
 250
 251//----------------------------------------------------------------------------
 252
 253IMPLEMENT_CO_NETOBJECT_V1(TurretShape);
 254
 255ConsoleDocClass( TurretShape,
 256   "@ingroup gameObjects\n"
 257);
 258
 259TurretShape::TurretShape()
 260{
 261   mTypeMask |= VehicleObjectType | DynamicShapeObjectType;
 262   mDataBlock = 0;
 263
 264   allowManualRotation = true;
 265   allowManualFire = true;
 266
 267   mTurretDelta.rot = Point3F(0.0f, 0.0f, 0.0f);
 268   mTurretDelta.rotVec = VectorF(0.0f, 0.0f, 0.0f);
 269   mTurretDelta.dt = 1;
 270
 271   mRot = mTurretDelta.rot;
 272
 273   mPitchAllowed = true;
 274   mHeadingAllowed = true;
 275
 276   mPitchRate = -1;
 277   mHeadingRate = -1;
 278
 279   mPitchUp = 0;
 280   mPitchDown = 0;
 281   mHeadingMax = mDegToRad(180.0f);
 282
 283   mRespawn = false;
 284
 285   mPitchThread = 0;
 286   mHeadingThread = 0;
 287
 288   mSubclassTurretShapeHandlesScene = false;
 289
 290   // For the Item class
 291   mSubclassItemHandlesScene = true;
 292   mRecoilThread = NULL;
 293   mImageStateThread = NULL;
 294}
 295
 296TurretShape::~TurretShape()
 297{
 298}
 299
 300//----------------------------------------------------------------------------
 301
 302void TurretShape::initPersistFields()
 303{
 304   addField("respawn",        TypeBool,      Offset(mRespawn,      TurretShape),
 305      "@brief Respawn the turret after it has been destroyed.\n\n"
 306      "If true, the turret will respawn after it is destroyed.\n");
 307
 308   Parent::initPersistFields();
 309}
 310
 311bool TurretShape::onAdd()
 312{
 313   if( !Parent::onAdd() )
 314      return false;
 315
 316   // Add this object to the scene
 317   if (!mSubclassTurretShapeHandlesScene)
 318   {
 319      addToScene();
 320   }
 321
 322   if (isServerObject() && !mSubclassTurretShapeHandlesScene)
 323   {
 324      scriptOnAdd();
 325   }
 326
 327   return true;
 328}
 329
 330void TurretShape::onRemove()
 331{
 332   Parent::onRemove();
 333
 334   if (!mSubclassTurretShapeHandlesScene)
 335   {
 336      scriptOnRemove();
 337
 338      // Remove this object from the scene
 339      removeFromScene();
 340   }
 341}
 342
 343bool TurretShape::onNewDataBlock(GameBaseData* dptr, bool reload)
 344{
 345   mDataBlock = dynamic_cast<TurretShapeData*>(dptr);
 346   if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload))
 347      return false;
 348
 349   // Mark these nodes for control by code only (will not animate in a sequence)
 350   if (mDataBlock->headingNode != -1)
 351      mShapeInstance->setNodeAnimationState(mDataBlock->headingNode, TSShapeInstance::MaskNodeHandsOff);
 352   if (mDataBlock->pitchNode != -1)
 353      mShapeInstance->setNodeAnimationState(mDataBlock->pitchNode, TSShapeInstance::MaskNodeHandsOff);
 354   for (U32 i=0; i<TurretShapeData::NumMirrorDirectionNodes; ++i)
 355   {
 356      if (mDataBlock->pitchNodes[i] != -1)
 357      {
 358         mShapeInstance->setNodeAnimationState(mDataBlock->pitchNodes[i], TSShapeInstance::MaskNodeHandsOff);
 359      }
 360
 361      if (mDataBlock->headingNodes[i] != -1)
 362      {
 363         mShapeInstance->setNodeAnimationState(mDataBlock->headingNodes[i], TSShapeInstance::MaskNodeHandsOff);
 364      }
 365   }
 366
 367   if (mIsZero(mDataBlock->pitchRate))
 368   {
 369      mPitchAllowed = false;
 370   }
 371   else
 372   {
 373      mPitchAllowed = true;
 374      if (mDataBlock->pitchRate > 0)
 375      {
 376         mPitchRate = mDegToRad(mDataBlock->pitchRate);
 377      }
 378      else
 379      {
 380         mPitchRate = -1;
 381      }
 382   }
 383
 384   if (mIsZero(mDataBlock->headingRate))
 385   {
 386      mHeadingAllowed = false;
 387   }
 388   else
 389   {
 390      mHeadingAllowed = true;
 391      if (mDataBlock->headingRate > 0)
 392      {
 393         mHeadingRate = mDegToRad(mDataBlock->headingRate);
 394      }
 395      else
 396      {
 397         mHeadingRate = -1;
 398      }
 399   }
 400
 401   mPitchUp = -mDegToRad(mDataBlock->maxPitch);
 402   mPitchDown = mDegToRad(mDataBlock->minPitch);
 403   mHeadingMax = mDegToRad(mDataBlock->maxHeading);
 404
 405   // Create Recoil thread if any recoil sequences are specified.
 406   // Note that the server player does not play this animation.
 407   mRecoilThread = 0;
 408   if (isGhost())
 409      for (U32 s = 0; s < TurretShapeData::NumRecoilSequences; s++)
 410         if (mDataBlock->recoilSequence[s] != -1) {
 411            mRecoilThread = mShapeInstance->addThread();
 412            mShapeInstance->setSequence(mRecoilThread, mDataBlock->recoilSequence[s], 0);
 413            mShapeInstance->setTimeScale(mRecoilThread, 0);
 414            break;
 415         }
 416
 417   // Reset the image state driven animation thread.  This will be properly built
 418   // in onImageStateAnimation() when needed.
 419   mImageStateThread = 0;
 420
 421   // Optional rotation threads.  These only play on the client.
 422   mPitchThread = 0;
 423   mHeadingThread = 0;
 424   if (isGhost())
 425   {
 426      if (mDataBlock->pitchSequence != -1)
 427      {
 428         mPitchThread = mShapeInstance->addThread();
 429         mShapeInstance->setSequence(mPitchThread, mDataBlock->pitchSequence, 0);
 430         mShapeInstance->setTimeScale(mPitchThread, 0);
 431      }
 432      if (mDataBlock->headingSequence != -1)
 433      {
 434         mHeadingThread = mShapeInstance->addThread();
 435         mShapeInstance->setSequence(mHeadingThread, mDataBlock->headingSequence, 0);
 436         mShapeInstance->setTimeScale(mHeadingThread, 0);
 437      }
 438   }
 439
 440   if (!mSubclassTurretShapeHandlesScene)
 441   {
 442      scriptOnNewDataBlock();
 443   }
 444
 445   return true;
 446}
 447
 448//----------------------------------------------------------------------------
 449
 450void TurretShape::updateAnimation(F32 dt)
 451{
 452   if (mRecoilThread)
 453      mShapeInstance->advanceTime(dt,mRecoilThread);
 454   if (mImageStateThread)
 455      mShapeInstance->advanceTime(dt,mImageStateThread);
 456
 457   // Update any pitch and heading threads
 458   if (mPitchThread)
 459   {
 460      F32 d = mPitchDown - mPitchUp;
 461      if (!mIsZero(d))
 462      {
 463         F32 pos = (mRot.x - mPitchUp) / d;
 464         mShapeInstance->setPos(mPitchThread, mClampF(pos, 0.0f, 1.0f));
 465      }
 466   }
 467   if (mHeadingThread)
 468   {
 469      F32 pos = 0.0f;
 470      if (mHeadingMax < mDegToRad(180.0f))
 471      {
 472         F32 d = mHeadingMax * 2.0f;
 473         if (!mIsZero(d))
 474         {
 475            pos = (mRot.z + mHeadingMax) / d;
 476         }
 477      }
 478      else
 479      {
 480         pos = mRot.z / M_2PI;
 481         if (pos < 0.0f)
 482         {
 483            // We don't want negative rotations to simply mirror the
 484            // positive rotations but to animate into them as if -0.0
 485            // is equivalent to 1.0.
 486            pos = mFmod(pos, 1.0f) + 1.0f;
 487         }
 488         if (pos > 1.0f)
 489         {
 490            pos = mFmod(pos, 1.0f);
 491         }
 492      }
 493      mShapeInstance->setPos(mHeadingThread, mClampF(pos, 0.0f, 1.0f));
 494   }
 495}
 496
 497//----------------------------------------------------------------------------
 498
 499void TurretShape::onImage(U32 imageSlot, bool unmount)
 500{
 501   // Clear out any previous image state animation
 502   if (mImageStateThread)
 503   {
 504      mShapeInstance->destroyThread(mImageStateThread);
 505      mImageStateThread = 0;
 506   }
 507}
 508
 509void TurretShape::onImageRecoil( U32, ShapeBaseImageData::StateData::RecoilState state )
 510{
 511   if ( mRecoilThread )
 512   {
 513      if ( state != ShapeBaseImageData::StateData::NoRecoil )
 514      {
 515         S32 stateIndex = state - ShapeBaseImageData::StateData::LightRecoil;
 516         if ( mDataBlock->recoilSequence[stateIndex] != -1 )
 517         {
 518            mShapeInstance->setSequence( mRecoilThread, mDataBlock->recoilSequence[stateIndex], 0 );
 519            mShapeInstance->setTimeScale( mRecoilThread, 1 );
 520         }
 521      }
 522   }
 523}
 524
 525void TurretShape::onImageStateAnimation(U32 imageSlot, const char* seqName, bool direction, bool scaleToState, F32 stateTimeOutValue)
 526{
 527   if (isGhost())
 528   {
 529      S32 seqIndex = mShapeInstance->getShape()->findSequence(seqName);
 530
 531      if (seqIndex != -1)
 532      {
 533         if (!mImageStateThread)
 534         {
 535            mImageStateThread = mShapeInstance->addThread();
 536         }
 537
 538         mShapeInstance->setSequence( mImageStateThread, seqIndex, 0 );
 539
 540         F32 timeScale = (scaleToState && stateTimeOutValue) ?
 541            mShapeInstance->getDuration(mImageStateThread) / stateTimeOutValue : 1.0f;
 542
 543         mShapeInstance->setTimeScale( mImageStateThread, direction ? timeScale : -timeScale );
 544      }
 545   }
 546}
 547
 548//----------------------------------------------------------------------------
 549
 550const char* TurretShape::getStateName()
 551{
 552   if (mDamageState != Enabled)
 553      return "Dead";
 554   if (isMounted())
 555      return "Mounted";
 556   return "Ready";
 557}
 558
 559void TurretShape::updateDamageLevel()
 560{
 561   if (!isGhost())
 562      setDamageState((mDamage >= mDataBlock->maxDamage)? Destroyed: Enabled);
 563   if (mDamageThread)
 564      mShapeInstance->setPos(mDamageThread, mDamage / mDataBlock->destroyedLevel);
 565}
 566
 567//----------------------------------------------------------------------------
 568
 569void TurretShape::processTick(const Move* move)
 570{
 571   // Image Triggers
 572   if (getAllowManualFire() && move && mDamageState == Enabled)
 573   {
 574      switch(mDataBlock->weaponLinkType)
 575      {
 576         case TurretShapeData::FireTogether:
 577         {
 578            setImageTriggerState(0,move->trigger[0]);
 579            setImageTriggerState(1,move->trigger[0]);
 580            setImageTriggerState(2,move->trigger[0]);
 581            setImageTriggerState(3,move->trigger[0]);
 582
 583            setImageAltTriggerState(0,move->trigger[1]);
 584            setImageAltTriggerState(1,move->trigger[1]);
 585            setImageAltTriggerState(2,move->trigger[1]);
 586            setImageAltTriggerState(3,move->trigger[1]);
 587
 588            break;
 589         }
 590
 591         case TurretShapeData::GroupedFire:
 592         {
 593            setImageTriggerState(0,move->trigger[0]);
 594            setImageTriggerState(1,move->trigger[1]);
 595            setImageTriggerState(2,move->trigger[0]);
 596            setImageTriggerState(3,move->trigger[1]);
 597
 598            break;
 599         }
 600
 601         case TurretShapeData::IndividualFire:
 602         {
 603            setImageTriggerState(0,move->trigger[0]);
 604            setImageTriggerState(1,move->trigger[1]);
 605            setImageTriggerState(2,move->trigger[2]);
 606            setImageTriggerState(3,move->trigger[3]);
 607
 608            break;
 609         }
 610      }
 611   }
 612
 613   Parent::processTick(move);
 614
 615   // Change our type based on our rest state
 616   if (mAtRest)
 617   {
 618      // At rest so we're static
 619      mTypeMask &= ~<a href="/coding/file/objecttypes_8h/#objecttypes_8h_1ac18d4a11e9446825e48fd474d7529084aae78d764ab9171d8c9d82b09cb376192">DynamicShapeObjectType</a>;
 620      mTypeMask |= StaticObjectType | StaticShapeObjectType;
 621   }
 622   else
 623   {
 624      // Not at rest so we're dynamic
 625      mTypeMask &= ~<a href="/coding/file/objecttypes_8h/#objecttypes_8h_1ac18d4a11e9446825e48fd474d7529084a38f2a997e7e1d6c416cf1a761979a690">StaticObjectType</a>;
 626      mTypeMask &= ~<a href="/coding/file/objecttypes_8h/#objecttypes_8h_1ac18d4a11e9446825e48fd474d7529084ac4dfaa39d1def366730d03f409c0fd98">StaticShapeObjectType</a>;
 627      mTypeMask |= DynamicShapeObjectType;
 628   }
 629
 630   if (!isGhost())
 631      updateAnimation(TickSec);
 632
 633   updateMove(move);
 634}
 635
 636void TurretShape::interpolateTick(F32 dt)
 637{
 638   Parent::interpolateTick(dt);
 639
 640   if (isMounted()) {
 641      MatrixF mat;
 642      mMount.object->getRenderMountTransform( dt, mMount.node, mMount.xfm, &mat );
 643      ShapeBase::setRenderTransform(mat);
 644   }
 645
 646   // Orientation
 647   Point3F rot = mTurretDelta.rot + mTurretDelta.rotVec * dt;
 648
 649   // Make sure we don't interpolate past the limits
 650   _applyLimits(rot);
 651
 652   _setRotation(rot);
 653}
 654
 655void TurretShape::advanceTime(F32 dt)
 656{
 657   // If there were any ShapeBase script threads that
 658   // have played, then we need to update all code
 659   // controlled nodes.  This is done before the Parent
 660   // call as script threads may play and be destroyed
 661   // before our code is called.
 662   bool updateNodes = false;
 663   for (U32 i = 0; i < MaxScriptThreads; i++)
 664   {
 665      Thread& st = mScriptThread[i];
 666      if (st.thread)
 667      {
 668         updateNodes = true;
 669         break;
 670      }
 671   }
 672
 673   Parent::advanceTime(dt);
 674
 675   updateAnimation(dt);
 676
 677   _setRotation(mRot);
 678}
 679
 680void TurretShape::setTransform( const MatrixF& mat )
 681{
 682   if (mDataBlock && mDataBlock->zRotOnly)
 683   {
 684      // Allow Item::setTransform() to do the work
 685      Parent::setTransform( mat );
 686   }
 687   else
 688   {
 689      // Do the transform work here to avoid Item's restriction on rotation
 690      ShapeBase::setTransform( mat );
 691
 692      if ( !mStatic )
 693      {
 694         mAtRest = false;
 695         mAtRestCounter = 0;
 696      }
 697
 698      if ( mPhysicsRep )
 699         mPhysicsRep->setTransform( getTransform() );
 700
 701      setMaskBits( Item::RotationMask | Item::PositionMask | Item::NoWarpMask );
 702   }
 703}
 704
 705void TurretShape::updateMove(const Move* move)
 706{
 707   PROFILE_SCOPE( TurretShape_UpdateMove );
 708
 709   if (!move)
 710      return;
 711
 712   Point3F vec, pos;
 713
 714   // Update orientation
 715   mTurretDelta.rotVec = mRot;
 716
 717   VectorF rotVec(0, 0, 0);
 718   if (getAllowManualRotation())
 719   {
 720      if (mPitchAllowed)
 721      {
 722         rotVec.x = move->pitch * 2.0f;   // Assume that our -2PI to 2PI range was clamped to -PI to PI in script;
 723         if (mPitchRate > 0)
 724         {
 725            rotVec.x *= mPitchRate * TickSec;
 726         }
 727      }
 728      if (mHeadingAllowed)
 729      {
 730         rotVec.z = move->yaw * 2.0f;     // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
 731         if (mHeadingRate > 0)
 732         {
 733            rotVec.z *= mHeadingRate * TickSec;
 734         }
 735      }
 736   }
 737
 738   mRot.x += rotVec.x;
 739   mRot.z += rotVec.z;
 740   _applyLimits(mRot);
 741
 742   if (isServerObject())
 743   {
 744      // As this ends up animating shape nodes, we have no sense of a transform and
 745      // render transform.  Therefore we treat this as the true transform and leave the
 746      // client shape node changes to interpolateTick() as the render transform.  Otherwise
 747      // on the client we'll have this node change from processTick() and then backstepping
 748      // and catching up to the true node change in interpolateTick(), which causes the
 749      // turret to stutter.
 750      _setRotation( mRot );
 751   }
 752   else
 753   {
 754      // If on the client, calc delta for backstepping
 755      mTurretDelta.rot = mRot;
 756      mTurretDelta.rotVec = mTurretDelta.rotVec - mTurretDelta.rot;
 757   }
 758
 759   setMaskBits(TurretUpdateMask);
 760}
 761
 762bool TurretShape::getNodeTransform(S32 node, MatrixF& mat)
 763{
 764   if (node == -1)
 765      return false;
 766
 767   MatrixF nodeTransform = mShapeInstance->mNodeTransforms[node];
 768   const Point3F& scale = getScale();
 769
 770   // The position of the node needs to be scaled.
 771   Point3F position = nodeTransform.getPosition();
 772   position.convolve( scale );
 773   nodeTransform.setPosition( position );
 774
 775   mat.mul(mObjToWorld, nodeTransform);
 776   return true;
 777}
 778
 779bool TurretShape::getWorldNodeTransform(S32 node, MatrixF& mat)
 780{
 781   MatrixF nodeMat;
 782   if (!getNodeTransform(node, nodeMat))
 783      return false;
 784
 785   nodeMat.affineInverse();
 786   mat = nodeMat;
 787   return true;
 788}
 789
 790void TurretShape::_setRotation(const Point3F& rot)
 791{
 792   _updateNodes(rot);
 793
 794   mShapeInstance->animate();
 795
 796   mRot = rot;
 797}
 798
 799void TurretShape::_updateNodes(const Point3F& rot)
 800{
 801   EulerF xRot(rot.x, 0.0f, 0.0f);
 802   EulerF zRot(0.0f, 0.0f, rot.z);
 803
 804   // Set heading
 805   S32 node = mDataBlock->headingNode;
 806   if (node != -1)
 807   {
 808      MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
 809      Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
 810      Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];
 811
 812      QuatF qrot(zRot);
 813      qrot *= defaultRot.getQuatF();
 814      qrot.setMatrix( mat );      
 815      mat->setColumn(3, defaultPos);
 816   }
 817
 818   // Set pitch
 819   node = mDataBlock->pitchNode;
 820   if (node != -1)
 821   {
 822      MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
 823      Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
 824      Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];
 825
 826      QuatF qrot(xRot);
 827      qrot *= defaultRot.getQuatF();
 828      qrot.setMatrix( mat );    
 829      mat->setColumn(3, defaultPos);
 830   }
 831
 832   // Now the mirror direction nodes, if any
 833   for (U32 i=0; i<TurretShapeData::NumMirrorDirectionNodes; ++i)
 834   {
 835      node = mDataBlock->pitchNodes[i];
 836      if (node != -1)
 837      {
 838         MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
 839         Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
 840         Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];         
 841
 842         QuatF qrot(xRot);
 843         qrot *= defaultRot.getQuatF();
 844         qrot.setMatrix( mat );    
 845         mat->setColumn(3, defaultPos);
 846      }
 847
 848      node = mDataBlock->headingNodes[i];
 849      if (node != -1)
 850      {
 851         MatrixF* mat = &mShapeInstance->mNodeTransforms[node];
 852         Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node];
 853         Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node];
 854
 855         QuatF qrot(zRot);
 856         qrot *= defaultRot.getQuatF();
 857         qrot.setMatrix( mat );      
 858         mat->setColumn(3, defaultPos);
 859      }
 860   }
 861
 862   mShapeInstance->setDirty(TSShapeInstance::TransformDirty);
 863}
 864
 865void TurretShape::_applyLimits(Point3F& rot)
 866{
 867   rot.x = mClampF(rot.x, mPitchUp, mPitchDown);
 868   if (mHeadingMax < mDegToRad(180.0f))
 869   {
 870      rot.z = mClampF(rot.z, -mHeadingMax, mHeadingMax);
 871   }
 872}
 873
 874bool TurretShape::_outsideLimits(Point3F& rot)
 875{
 876   if (rot.x < mPitchUp || rot.x > mPitchDown)
 877      return true;
 878
 879   if (mHeadingMax < mDegToRad(180.0f))
 880   {
 881      if (rot.z < -mHeadingMax || rot.z > mHeadingMax)
 882         return true;
 883   }
 884
 885   return false;
 886}
 887
 888//----------------------------------------------------------------------------
 889
 890void TurretShape::mountObject( SceneObject *obj, S32 node, const MatrixF &xfm )
 891{
 892   Parent::mountObject(obj, node, xfm);
 893
 894   if (isClientObject())
 895   {
 896      if (obj)
 897      {
 898         GameConnection* conn = obj->getControllingClient();
 899         if (conn)
 900         {
 901            // Allow the client to set up any action maps, HUD, etc.
 902            Con::executef("turretMountCallback", Con::getIntArg(getId()), Con::getIntArg(obj->getId()), Con::getIntArg(true));
 903         }
 904      }
 905   }
 906   else
 907   {
 908      mDataBlock->onMountObject_callback( this, obj, node );
 909   }
 910}
 911
 912void TurretShape::unmountObject( SceneObject *obj )
 913{
 914   Parent::unmountObject(obj);
 915
 916   if (isClientObject())
 917   {
 918      if (obj)
 919      {
 920         GameConnection* conn = obj->getControllingClient();
 921         if (conn)
 922         {
 923            // Allow the client to set up any action maps, HUD, etc.
 924            Con::executef("turretMountCallback", Con::getIntArg(getId()), Con::getIntArg(obj->getId()), Con::getIntArg(false));
 925         }
 926      }
 927   }
 928   else
 929   {
 930      mDataBlock->onUnmountObject_callback( this, obj );
 931   }
 932}
 933
 934void TurretShape::onUnmount(SceneObject*,S32)
 935{
 936   // Make sure the client get's the final server pos of this turret.
 937   setMaskBits(PositionMask);
 938}
 939
 940//----------------------------------------------------------------------------
 941
 942void TurretShape::getCameraParameters(F32 *min,F32* max,Point3F* off,MatrixF* rot)
 943{
 944   *min = mDataBlock->cameraMinDist;
 945   *max = mDataBlock->cameraMaxDist;
 946
 947   off->set(0,0,mDataBlock->cameraOffset);
 948   rot->identity();
 949}
 950
 951void TurretShape::getCameraTransform(F32* pos,MatrixF* mat)
 952{
 953   // Returns camera to world space transform
 954   // Handles first person / third person camera position
 955   if (isServerObject() && mShapeInstance)
 956      mShapeInstance->animateNodeSubtrees(true);
 957
 958   if (*pos == 0) {
 959      getRenderEyeTransform(mat);
 960      return;
 961   }
 962
 963   // Get the shape's camera parameters.
 964   F32 min,max;
 965   MatrixF rot;
 966   Point3F offset;
 967   getCameraParameters(&min,&max,&offset,&rot);
 968
 969   // Start with the current eye position
 970   MatrixF eye;
 971   getRenderEyeTransform(&eye);
 972
 973   // Build a transform that points along the eye axis
 974   // but where the Z axis is always up.
 975   {
 976      MatrixF cam(1);
 977      VectorF x,y,z(0,0,1);
 978      eye.getColumn(1, &y);
 979      mCross(y, z, &x);
 980      x.normalize();
 981      mCross(x, y, &z);
 982      z.normalize();
 983      cam.setColumn(0,x);
 984      cam.setColumn(1,y);
 985      cam.setColumn(2,z);
 986      mat->mul(cam,rot);
 987   }
 988
 989   // Camera is positioned straight back along the eye's -Y axis.
 990   // A ray is cast to make sure the camera doesn't go through
 991   // anything solid.
 992   VectorF vp,vec;
 993   vp.x = vp.z = 0;
 994   vp.y = -(max - min) * *pos;
 995   eye.mulV(vp,&vec);
 996
 997   // Use the camera node as the starting position if it exists.
 998   Point3F osp,sp;
 999   if (mDataBlock->cameraNode != -1) 
1000   {
1001      mShapeInstance->mNodeTransforms[mDataBlock->cameraNode].getColumn(3,&osp);
1002      getRenderTransform().mulP(osp,&sp);
1003   }
1004   else
1005      eye.getColumn(3,&sp);
1006
1007   // Make sure we don't hit ourself...
1008   disableCollision();
1009   if (isMounted())
1010      getObjectMount()->disableCollision();
1011
1012   // Cast the ray into the container database to see if we're going
1013   // to hit anything.
1014   RayInfo collision;
1015   Point3F ep = sp + vec + offset;
1016   if (mContainer->castRay(sp, ep,
1017         ~(WaterObjectType | GameBaseObjectType | DefaultObjectType | sTriggerMask),
1018         &collision) == true) {
1019
1020      // Shift the collision point back a little to try and
1021      // avoid clipping against the front camera plane.
1022      F32 t = collision.t - (-mDot(vec, collision.normal) / vec.len()) * 0.1;
1023      if (t > 0.0f)
1024         ep = sp + offset + (vec * t);
1025      else
1026         eye.getColumn(3,&ep);
1027   }
1028   mat->setColumn(3,ep);
1029
1030   // Re-enable our collision.
1031   if (isMounted())
1032      getObjectMount()->enableCollision();
1033   enableCollision();
1034
1035   // Apply Camera FX.
1036   mat->mul( gCamFXMgr.getTrans() );
1037}
1038
1039//----------------------------------------------------------------------------
1040
1041void TurretShape::writePacketData(GameConnection *connection, BitStream *stream)
1042{
1043   // Update client regardless of status flags.
1044   Parent::writePacketData(connection, stream);
1045   
1046   stream->writeSignedFloat(mRot.x / M_2PI_F, 7);
1047   stream->writeSignedFloat(mRot.z / M_2PI_F, 7);
1048}
1049
1050void TurretShape::readPacketData(GameConnection *connection, BitStream *stream)
1051{
1052   Parent::readPacketData(connection, stream);
1053
1054   Point3F rot(0.0f, 0.0f, 0.0f);
1055   rot.x = stream->readSignedFloat(7) * M_2PI_F;
1056   rot.z = stream->readSignedFloat(7) * M_2PI_F;
1057   _setRotation(rot);
1058
1059   mTurretDelta.rot = rot;
1060   mTurretDelta.rotVec.set(0.0f, 0.0f, 0.0f);
1061}
1062
1063U32 TurretShape::packUpdate(NetConnection *connection, U32 mask, BitStream *stream)
1064{
1065   // Handle rotation ourselves (so it is not locked to the Z axis like for Items)
1066   U32 retMask = Parent::packUpdate( connection, mask & (~<a href="/coding/class/classitem/#classitem_1aaacac713d02fa2d54fcca2662866de3fa5f0360bea9b5df7a11abb6ab328e4a92">Item::RotationMask</a>), stream );
1067
1068   if (stream->writeFlag(mask & InitialUpdateMask)) {
1069      stream->writeFlag(mRespawn);
1070   }
1071
1072   if ( stream->writeFlag( mask & Item::RotationMask ) )
1073   {
1074      QuatF rot( mObjToWorld );
1075      mathWrite( *stream, rot );
1076   }
1077
1078   // The rest of the data is part of the control object packet update.
1079   // If we're controlled by this client, we don't need to send it.
1080   if(stream->writeFlag((NetConnection*)getControllingClient() == connection && !(mask & InitialUpdateMask)))
1081      return 0;
1082
1083   if (stream->writeFlag(mask & TurretUpdateMask))
1084   {
1085      stream->writeSignedFloat(mRot.x / M_2PI_F, 7);
1086      stream->writeSignedFloat(mRot.z / M_2PI_F, 7);
1087      stream->write(allowManualRotation);
1088      stream->write(allowManualFire);
1089   }
1090
1091   return retMask;
1092}
1093
1094void TurretShape::unpackUpdate(NetConnection *connection, BitStream *stream)
1095{
1096   Parent::unpackUpdate(connection,stream);
1097
1098   // InitialUpdateMask
1099   if (stream->readFlag()) {
1100      mRespawn = stream->readFlag();
1101   }
1102
1103   // Item::RotationMask
1104   if ( stream->readFlag() )
1105   {
1106      QuatF rot;
1107      mathRead( *stream, &rot );
1108
1109      Point3F pos = mObjToWorld.getPosition();
1110      rot.setMatrix( &mObjToWorld );
1111      mObjToWorld.setPosition( pos );
1112   }
1113
1114   // controlled by the client?
1115   if(stream->readFlag())
1116      return;
1117
1118   // TurretUpdateMask
1119   if (stream->readFlag())
1120   {
1121      Point3F rot(0.0f, 0.0f, 0.0f);
1122      rot.x = stream->readSignedFloat(7) * M_2PI_F;
1123      rot.z = stream->readSignedFloat(7) * M_2PI_F;
1124      _setRotation(rot);
1125
1126      // New delta for client side interpolation
1127      mTurretDelta.rot = rot;
1128      mTurretDelta.rotVec = VectorF(0.0f, 0.0f, 0.0f);
1129
1130      stream->read(&allowManualRotation);
1131      stream->read(&allowManualFire);
1132   }
1133}
1134
1135//----------------------------------------------------------------------------
1136
1137void TurretShape::getWeaponMountTransform( S32 index, const MatrixF &xfm, MatrixF *outMat )
1138{
1139   // Returns mount point to world space transform
1140   if ( index >= 0 && index < ShapeBase::MaxMountedImages) {
1141      S32 ni = mDataBlock->weaponMountNode[index];
1142      if (ni != -1) {
1143         MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni];
1144         mountTransform.mul( xfm );
1145         const Point3F& scale = getScale();
1146
1147         // The position of the mount point needs to be scaled.
1148         Point3F position = mountTransform.getPosition();
1149         position.convolve( scale );
1150         mountTransform.setPosition( position );
1151
1152         // Also we would like the object to be scaled to the model.
1153         outMat->mul(mObjToWorld, mountTransform);
1154         return;
1155      }
1156   }
1157
1158   // Then let SceneObject handle it.
1159   GrandParent::getMountTransform( index, xfm, outMat );      
1160}
1161
1162void TurretShape::getRenderWeaponMountTransform( F32 delta, S32 mountPoint, const MatrixF &xfm, MatrixF *outMat )
1163{
1164   // Returns mount point to world space transform
1165   if ( mountPoint >= 0 && mountPoint < ShapeBase::MaxMountedImages) {
1166      S32 ni = mDataBlock->weaponMountNode[mountPoint];
1167      if (ni != -1) {
1168         MatrixF mountTransform = mShapeInstance->mNodeTransforms[ni];
1169         mountTransform.mul( xfm );
1170         const Point3F& scale = getScale();
1171
1172         // The position of the mount point needs to be scaled.
1173         Point3F position = mountTransform.getPosition();
1174         position.convolve( scale );
1175         mountTransform.setPosition( position );
1176
1177         // Also we would like the object to be scaled to the model.
1178         mountTransform.scale( scale );
1179         outMat->mul(getRenderTransform(), mountTransform);
1180         return;
1181      }
1182   }
1183
1184   // Then let SceneObject handle it.
1185   GrandParent::getRenderMountTransform( delta, mountPoint, xfm, outMat );   
1186}
1187
1188void TurretShape::getImageTransform(U32 imageSlot,MatrixF* mat)
1189{
1190   // Image transform in world space
1191   MountedImage& image = mMountedImageList[imageSlot];
1192   if (image.dataBlock) {
1193      ShapeBaseImageData& data = *image.dataBlock;
1194
1195      MatrixF nmat;
1196      if (data.useEyeOffset && isFirstPerson()) {
1197         getEyeTransform(&nmat);
1198         mat->mul(nmat,data.eyeOffset);
1199      }
1200      else {
1201         getWeaponMountTransform( imageSlot, MatrixF::Identity, &nmat );
1202         mat->mul(nmat,data.mountTransform[getImageShapeIndex(image)]);
1203      }
1204   }
1205   else
1206      *mat = mObjToWorld;
1207}
1208
1209void TurretShape::getRenderImageTransform( U32 imageSlot, MatrixF* mat, bool noEyeOffset )
1210{
1211   // Image transform in world space
1212   MountedImage& image = mMountedImageList[imageSlot];
1213   if (image.dataBlock) 
1214   {
1215      ShapeBaseImageData& data = *image.dataBlock;
1216
1217      MatrixF nmat;
1218      if ( !noEyeOffset && data.useEyeOffset && isFirstPerson() ) 
1219      {
1220         getRenderEyeTransform(&nmat);
1221         mat->mul(nmat,data.eyeOffset);
1222      }
1223      else 
1224      {
1225         getRenderWeaponMountTransform( 0.0f, imageSlot, MatrixF::Identity, &nmat );
1226         mat->mul(nmat,data.mountTransform[getImageShapeIndex(image)]);
1227      }
1228   }
1229   else
1230      *mat = getRenderTransform();
1231}
1232
1233void TurretShape::getImageTransform(U32 imageSlot,S32 node,MatrixF* mat)
1234{
1235   // Same as ShapeBase::getImageTransform() other than getRenderWeaponMountTransform() below
1236
1237   // Image transform in world space
1238   MountedImage& image = mMountedImageList[imageSlot];
1239   if (image.dataBlock)
1240   {
1241      if (node != -1)
1242      {
1243         ShapeBaseImageData& data = *image.dataBlock;
1244         U32 shapeIndex = getImageShapeIndex(image);
1245
1246         MatrixF nmat = image.shapeInstance[shapeIndex]->mNodeTransforms[node];
1247         MatrixF mmat;
1248
1249         if (data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1)
1250         {
1251            // We need to animate, even on the server, to make sure the nodes are in the correct location.
1252            image.shapeInstance[shapeIndex]->animate();
1253
1254            MatrixF emat;
1255            getEyeBaseTransform(&emat, mDataBlock->mountedImagesBank);
1256
1257            MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
1258            mountTransform.affineInverse();
1259
1260            mmat.mul(emat, mountTransform);
1261         }
1262         else if (data.useEyeOffset && isFirstPerson())
1263         {
1264            MatrixF emat;
1265            getEyeTransform(&emat);
1266            mmat.mul(emat,data.eyeOffset);
1267         }
1268         else
1269         {
1270            MatrixF emat;
1271            getWeaponMountTransform( imageSlot, MatrixF::Identity, &emat );
1272            mmat.mul(emat,data.mountTransform[shapeIndex]);
1273         }
1274
1275         mat->mul(mmat, nmat);
1276      }
1277      else
1278         getImageTransform(imageSlot,mat);
1279   }
1280   else
1281      *mat = mObjToWorld;
1282}
1283
1284void TurretShape::getRenderImageTransform(U32 imageSlot,S32 node,MatrixF* mat)
1285{
1286   // Same as ShapeBase::getRenderImageTransform() other than getRenderWeaponMountTransform() below
1287
1288   // Image transform in world space
1289   MountedImage& image = mMountedImageList[imageSlot];
1290   if (image.dataBlock)
1291   {
1292      if (node != -1)
1293      {
1294         ShapeBaseImageData& data = *image.dataBlock;
1295         U32 shapeIndex = getImageShapeIndex(image);
1296
1297         MatrixF nmat = image.shapeInstance[shapeIndex]->mNodeTransforms[node];
1298         MatrixF mmat;
1299
1300         if ( data.useEyeNode && isFirstPerson() && data.eyeMountNode[shapeIndex] != -1 )
1301         {
1302            MatrixF emat;
1303            getRenderEyeBaseTransform(&emat, mDataBlock->mountedImagesBank);
1304
1305            MatrixF mountTransform = image.shapeInstance[shapeIndex]->mNodeTransforms[data.eyeMountNode[shapeIndex]];
1306            mountTransform.affineInverse();
1307
1308            mmat.mul(emat, mountTransform);
1309         }
1310         else if ( data.useEyeOffset && isFirstPerson() ) 
1311         {
1312            MatrixF emat;
1313            getRenderEyeTransform(&emat);
1314            mmat.mul(emat,data.eyeOffset);
1315         }
1316         else 
1317         {
1318            MatrixF emat;
1319            getRenderWeaponMountTransform( 0.0f, imageSlot, MatrixF::Identity, &emat );
1320            mmat.mul(emat,data.mountTransform[shapeIndex]);
1321         }
1322
1323         mat->mul(mmat, nmat);
1324      }
1325      else
1326         getRenderImageTransform(imageSlot,mat);
1327   }
1328   else
1329      *mat = getRenderTransform();
1330}
1331
1332//----------------------------------------------------------------------------
1333
1334void TurretShape::prepRenderImage( SceneRenderState *state )
1335{
1336   // Skip the Item class rendering
1337   _prepRenderImage( state, true, true );
1338}
1339
1340void TurretShape::prepBatchRender( SceneRenderState *state, S32 mountedImageIndex )
1341{
1342   Parent::prepBatchRender( state, mountedImageIndex );
1343
1344   if ( !gShowBoundingBox )
1345      return;
1346
1347   //if ( mountedImageIndex != -1 )
1348   //{
1349   //   ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
1350   //   ri->renderDelegate.bind( this, &Vehicle::_renderMuzzleVector );
1351   //   ri->objectIndex = mountedImageIndex;
1352   //   ri->type = RenderPassManager::RIT_Editor;
1353   //   state->getRenderPass()->addInst( ri );
1354   //   return;
1355   //}
1356
1357   //ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
1358   //ri->renderDelegate.bind( this, &Vehicle::_renderMassAndContacts );
1359   //ri->type = RenderPassManager::RIT_Editor;
1360   //state->getRenderPass()->addInst( ri );
1361}
1362
1363//----------------------------------------------------------------------------
1364
1365DefineEngineMethod( TurretShape, getAllowManualRotation, bool, (),,
1366   "@brief Get if the turret is allowed to rotate through moves.\n\n"
1367   "@return True if the turret is allowed to rotate through moves.\n" )
1368{
1369   return object->getAllowManualRotation();
1370}
1371
1372DefineEngineMethod( TurretShape, setAllowManualRotation, void, (bool allow),,
1373   "@brief Set if the turret is allowed to rotate through moves.\n\n"
1374   "@param allow If true then the turret may be rotated through moves.\n")
1375{
1376   return object->setAllowManualRotation(allow);
1377}
1378
1379DefineEngineMethod( TurretShape, getAllowManualFire, bool, (),,
1380   "@brief Get if the turret is allowed to fire through moves.\n\n"
1381   "@return True if the turret is allowed to fire through moves.\n" )
1382{
1383   return object->getAllowManualFire();
1384}
1385
1386DefineEngineMethod( TurretShape, setAllowManualFire, void, (bool allow),,
1387   "@brief Set if the turret is allowed to fire through moves.\n\n"
1388   "@param allow If true then the turret may be fired through moves.\n")
1389{
1390   return object->setAllowManualFire(allow);
1391}
1392
1393DefineEngineMethod( TurretShape, getState, const char*, (),,
1394   "@brief Get the name of the turret's current state.\n\n"
1395
1396   "The state is one of the following:\n\n<ul>"
1397   "<li>Dead - The TurretShape is destroyed.</li>"
1398   "<li>Mounted - The TurretShape is mounted to an object such as a vehicle.</li>"
1399   "<li>Ready - The TurretShape is free to move.  The usual state.</li></ul>\n"
1400
1401   "@return The current state; one of: \"Dead\", \"Mounted\", \"Ready\"\n" )
1402{
1403   return object->getStateName();
1404}
1405
1406DefineEngineMethod( TurretShape, getTurretEulerRotation, Point3F, (),,
1407   "@brief Get Euler rotation of this turret's heading and pitch nodes.\n\n"
1408   "@return the orientation of the turret's heading and pitch nodes in the "
1409   "form of rotations around the X, Y and Z axes in degrees.\n" )
1410{
1411   Point3F euler = object->getTurretRotation();
1412   
1413   // Convert to degrees.
1414   euler.x = mRadToDeg( euler.x );
1415   euler.y = mRadToDeg( euler.y );
1416   euler.z = mRadToDeg( euler.z );
1417   
1418   return euler;
1419}
1420
1421DefineEngineMethod( TurretShape, setTurretEulerRotation, void, ( Point3F rot ),,
1422   "@brief Set Euler rotation of this turret's heading and pitch nodes in degrees.\n\n"
1423   "@param rot The rotation in degrees.  The pitch is the X component and the "
1424   "heading is the Z component.  The Y component is ignored.\n")
1425{
1426   object->setTurretRotation( rot );
1427}
1428
1429DefineEngineMethod( TurretShape, doRespawn, bool, (),,
1430   "@brief Does the turret respawn after it has been destroyed.\n\n"
1431   "@returns True if the turret respawns.\n")
1432{
1433   return object->doRespawn();
1434}
1435