PageRenderTime 545ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/MTA10_Server/mods/deathmatch/logic/CMarker.cpp

https://github.com/popovag/multitheftauto
C++ | 379 lines | 260 code | 55 blank | 64 comment | 64 complexity | 1a50c512ebdcb2715084d1b29ad26ad0 MD5 | raw file
  1. /*****************************************************************************
  2. *
  3. * PROJECT: Multi Theft Auto v1.0
  4. * LICENSE: See LICENSE in the top level directory
  5. * FILE: mods/deathmatch/logic/CMarker.cpp
  6. * PURPOSE: Marker entity class
  7. * DEVELOPERS: Christian Myhre Lundheim <>
  8. * Jax <>
  9. * Kevin Whiteside <>
  10. * lil_Toady <>
  11. *
  12. * Multi Theft Auto is available from http://www.multitheftauto.com/
  13. *
  14. *****************************************************************************/
  15. #include "StdInc.h"
  16. CMarker::CMarker ( CMarkerManager* pMarkerManager, CColManager* pColManager, CElement* pParent, CXMLNode* pNode ) : CPerPlayerEntity ( pParent, pNode )
  17. {
  18. // Init
  19. m_pMarkerManager = pMarkerManager;
  20. m_pColManager = pColManager;
  21. m_iType = CElement::MARKER;
  22. SetTypeName ( "marker" );
  23. m_ucType = TYPE_CHECKPOINT;
  24. m_fSize = 4.0f;
  25. m_Color = SColorRGBA ( 255, 255, 255, 255 );
  26. m_bHasTarget = false;
  27. m_ucIcon = ICON_NONE;
  28. // Create our collision object
  29. m_pCollision = new CColCircle ( pColManager, NULL, m_vecPosition, m_fSize, NULL, true );
  30. m_pCollision->SetCallback ( this );
  31. m_pCollision->SetAutoCallEvent ( false );
  32. // Add us to the marker manager
  33. pMarkerManager->AddToList ( this );
  34. };
  35. CMarker::~CMarker ( void )
  36. {
  37. // Delete our collision object
  38. if ( m_pCollision )
  39. delete m_pCollision;
  40. // Unlink from manager
  41. Unlink ();
  42. }
  43. void CMarker::Unlink ( void )
  44. {
  45. // Remove us from the marker manager
  46. m_pMarkerManager->RemoveFromList ( this );
  47. }
  48. bool CMarker::ReadSpecialData ( void )
  49. {
  50. // Grab the "posX" data
  51. if ( !GetCustomDataFloat ( "posX", m_vecPosition.fX, true ) )
  52. {
  53. CLogger::ErrorPrintf ( "Bad/missing 'posX' attribute in <marker> (line %u)\n", m_uiLine );
  54. return false;
  55. }
  56. // Grab the "posY" data
  57. if ( !GetCustomDataFloat ( "posY", m_vecPosition.fY, true ) )
  58. {
  59. CLogger::ErrorPrintf ( "Bad/missing 'posY' attribute in <marker> (line %u)\n", m_uiLine );
  60. return false;
  61. }
  62. // Grab the "posZ" data
  63. if ( !GetCustomDataFloat ( "posZ", m_vecPosition.fZ, true ) )
  64. {
  65. CLogger::ErrorPrintf ( "Bad/missing 'posZ' attribute in <marker> (line %u)\n", m_uiLine );
  66. return false;
  67. }
  68. // Set the position in the col object
  69. if ( m_pCollision )
  70. m_pCollision->SetPosition ( m_vecPosition );
  71. // Grab the "type" data
  72. char szBuffer [128];
  73. if ( GetCustomDataString ( "type", szBuffer, 128, true ) )
  74. {
  75. // Convert it to a type
  76. m_ucType = static_cast < unsigned char > ( CMarkerManager::StringToType ( szBuffer ) );
  77. if ( m_ucType == CMarker::TYPE_INVALID )
  78. {
  79. CLogger::LogPrintf ( "WARNING: Unknown 'type' value specified in <marker>; defaulting to \"default\" (line %u)\n", m_uiLine );
  80. m_ucType = CMarker::TYPE_CHECKPOINT;
  81. }
  82. }
  83. else
  84. {
  85. m_ucType = CMarker::TYPE_CHECKPOINT;
  86. }
  87. // Grab the "color" data
  88. if ( GetCustomDataString ( "color", szBuffer, 128, true ) )
  89. {
  90. // Convert the HTML-style color to RGB
  91. if ( !XMLColorToInt ( szBuffer, m_Color.R, m_Color.G, m_Color.B, m_Color.A ) )
  92. {
  93. CLogger::ErrorPrintf ( "Bad 'color' specified in <marker> (line %u)\n", m_uiLine );
  94. return false;
  95. }
  96. }
  97. else
  98. {
  99. SetColor ( SColorRGBA( 255, 0, 0, 255 ) );
  100. }
  101. float fSize;
  102. if ( GetCustomDataFloat ( "size", fSize, true ) )
  103. m_fSize = fSize;
  104. int iTemp;
  105. if ( GetCustomDataInt ( "dimension", iTemp, true ) )
  106. m_usDimension = static_cast < unsigned short > ( iTemp );
  107. if ( GetCustomDataInt ( "interior", iTemp, true ) )
  108. m_ucInterior = static_cast < unsigned char > ( iTemp );
  109. // Success
  110. return true;
  111. }
  112. void CMarker::SetPosition ( const CVector& vecPosition )
  113. {
  114. // Remember our last position
  115. m_vecLastPosition = m_vecPosition;
  116. // Different from our current position?
  117. if ( m_vecPosition != vecPosition )
  118. {
  119. // Set the new position
  120. m_vecPosition = vecPosition;
  121. if ( m_pCollision )
  122. m_pCollision->SetPosition ( vecPosition );
  123. // We need to make sure the time context is replaced
  124. // before that so old packets don't arrive after this.
  125. GenerateSyncTimeContext ();
  126. // Tell all the players that know about us
  127. CBitStream BitStream;
  128. BitStream.pBitStream->Write ( m_ID );
  129. BitStream.pBitStream->Write ( vecPosition.fX );
  130. BitStream.pBitStream->Write ( vecPosition.fY );
  131. BitStream.pBitStream->Write ( vecPosition.fZ );
  132. BitStream.pBitStream->Write ( GetSyncTimeContext () );
  133. BroadcastOnlyVisible ( CLuaPacket ( SET_ELEMENT_POSITION, *BitStream.pBitStream ) );
  134. }
  135. }
  136. void CMarker::SetTarget ( const CVector* pTargetVector )
  137. {
  138. // Got a target vector?
  139. if ( pTargetVector )
  140. {
  141. // Different from our current target
  142. if ( !m_bHasTarget || m_vecTarget != *pTargetVector )
  143. {
  144. // Is this a marker type that has a destination?
  145. if ( m_ucType == CMarker::TYPE_CHECKPOINT || m_ucType == CMarker::TYPE_RING )
  146. {
  147. // Set the target position
  148. m_bHasTarget = true;
  149. m_vecTarget = *pTargetVector;
  150. // Tell everyone that knows about this marker
  151. CBitStream BitStream;
  152. BitStream.pBitStream->Write ( m_ID );
  153. BitStream.pBitStream->Write ( static_cast < unsigned char > ( 1 ) );
  154. BitStream.pBitStream->Write ( m_vecTarget.fX );
  155. BitStream.pBitStream->Write ( m_vecTarget.fY );
  156. BitStream.pBitStream->Write ( m_vecTarget.fZ );
  157. BroadcastOnlyVisible ( CLuaPacket ( SET_MARKER_TARGET, *BitStream.pBitStream ) );
  158. }
  159. else
  160. {
  161. // Reset the target position
  162. m_bHasTarget = false;
  163. }
  164. }
  165. }
  166. else
  167. {
  168. // Not already without target?
  169. if ( m_bHasTarget )
  170. {
  171. // Reset the target position
  172. m_bHasTarget = false;
  173. // Is this a marker type that has a destination?
  174. if ( m_ucType == CMarker::TYPE_CHECKPOINT || m_ucType == CMarker::TYPE_RING )
  175. {
  176. // Tell everyone that knows about this marker
  177. CBitStream BitStream;
  178. BitStream.pBitStream->Write ( m_ID );
  179. BitStream.pBitStream->Write ( static_cast < unsigned char > ( 0 ) );
  180. BroadcastOnlyVisible ( CLuaPacket ( SET_MARKER_TARGET, *BitStream.pBitStream ) );
  181. }
  182. }
  183. }
  184. }
  185. void CMarker::SetMarkerType ( unsigned char ucType )
  186. {
  187. // Different from our current type?
  188. if ( ucType != m_ucType )
  189. {
  190. // Set the new type
  191. unsigned char ucOldType = m_ucType;
  192. m_ucType = ucType;
  193. UpdateCollisionObject ( ucOldType );
  194. // Tell all players
  195. CBitStream BitStream;
  196. BitStream.pBitStream->Write ( m_ID );
  197. BitStream.pBitStream->Write ( ucType );
  198. BroadcastOnlyVisible ( CLuaPacket ( SET_MARKER_TYPE, *BitStream.pBitStream ) );
  199. // Is the new type not a checkpoint or a ring? Remove the target
  200. if ( ucType != CMarker::TYPE_CHECKPOINT && ucType != CMarker::TYPE_RING )
  201. {
  202. m_bHasTarget = false;
  203. }
  204. }
  205. }
  206. void CMarker::SetSize ( float fSize )
  207. {
  208. // Different from our current size?
  209. if ( fSize != m_fSize )
  210. {
  211. // Set the new size and update the col object
  212. m_fSize = fSize;
  213. UpdateCollisionObject ( m_ucType );
  214. // Tell all players
  215. CBitStream BitStream;
  216. BitStream.pBitStream->Write ( m_ID );
  217. BitStream.pBitStream->Write ( fSize );
  218. BroadcastOnlyVisible ( CLuaPacket ( SET_MARKER_SIZE, *BitStream.pBitStream ) );
  219. }
  220. }
  221. void CMarker::SetColor ( const SColor color )
  222. {
  223. // Different from our current color?
  224. if ( color != m_Color )
  225. {
  226. // Set the new color
  227. m_Color = color;
  228. // Tell all the players
  229. CBitStream BitStream;
  230. BitStream.pBitStream->Write ( m_ID );
  231. BitStream.pBitStream->Write ( color.B );
  232. BitStream.pBitStream->Write ( color.G );
  233. BitStream.pBitStream->Write ( color.R );
  234. BitStream.pBitStream->Write ( color.A );
  235. BroadcastOnlyVisible ( CLuaPacket ( SET_MARKER_COLOR, *BitStream.pBitStream ) );
  236. }
  237. }
  238. void CMarker::SetIcon ( unsigned char ucIcon )
  239. {
  240. if ( m_ucIcon != ucIcon )
  241. {
  242. m_ucIcon = ucIcon;
  243. // Tell everyone that knows about this marker
  244. CBitStream BitStream;
  245. BitStream.pBitStream->Write ( m_ID );
  246. BitStream.pBitStream->Write ( m_ucIcon );
  247. BroadcastOnlyVisible ( CLuaPacket ( SET_MARKER_ICON, *BitStream.pBitStream ) );
  248. }
  249. }
  250. void CMarker::Callback_OnCollision ( CColShape& Shape, CElement& Element )
  251. {
  252. // Matching interior?
  253. if ( GetInterior () == Element.GetInterior () )
  254. {
  255. // Call the marker hit event
  256. CLuaArguments Arguments;
  257. Arguments.PushElement ( &Element ); // Hit element
  258. Arguments.PushBoolean ( GetDimension () == Element.GetDimension () ); // Matching dimension?
  259. CallEvent ( "onMarkerHit", Arguments );
  260. if ( IS_PLAYER ( &Element ) )
  261. {
  262. CLuaArguments Arguments2;
  263. Arguments2.PushElement ( this ); // marker
  264. Arguments2.PushBoolean ( GetDimension () == Element.GetDimension () ); // Matching dimension?
  265. Element.CallEvent ( "onPlayerMarkerHit", Arguments2 );
  266. }
  267. }
  268. }
  269. void CMarker::Callback_OnLeave ( CColShape& Shape, CElement& Element )
  270. {
  271. // Matching interior?
  272. if ( GetInterior () == Element.GetInterior () )
  273. {
  274. // Call the marker hit event
  275. CLuaArguments Arguments;
  276. Arguments.PushElement ( &Element ); // Hit element
  277. Arguments.PushBoolean ( GetDimension () == Element.GetDimension () ); // Matching dimension?
  278. CallEvent ( "onMarkerLeave", Arguments );
  279. if ( IS_PLAYER ( &Element ) )
  280. {
  281. CLuaArguments Arguments2;
  282. Arguments2.PushElement ( this ); // marker
  283. Arguments2.PushBoolean ( GetDimension () == Element.GetDimension () ); // Matching dimension?
  284. Element.CallEvent ( "onPlayerMarkerLeave", Arguments2 );
  285. }
  286. }
  287. }
  288. void CMarker::Callback_OnCollisionDestroy ( CColShape* pCollision )
  289. {
  290. if ( pCollision == m_pCollision )
  291. m_pCollision = NULL;
  292. }
  293. void CMarker::UpdateCollisionObject ( unsigned char ucOldType )
  294. {
  295. // Different type than before?
  296. if ( m_ucType != ucOldType )
  297. {
  298. // Are we becomming a checkpoint? Make the col object a circle. If we're becomming something and we were a checkpoint, make the col object a sphere.
  299. // lil_Toady: Simply deleting the colshape may cause a dangling pointer in CColManager if we're in DoHitDetection loop
  300. if ( m_ucType == CMarker::TYPE_CHECKPOINT )
  301. {
  302. if ( m_pCollision )
  303. g_pGame->GetElementDeleter()->Delete ( m_pCollision );
  304. m_pCollision = new CColCircle ( m_pColManager, NULL, m_vecPosition, m_fSize, NULL );
  305. }
  306. else if ( ucOldType == CMarker::TYPE_CHECKPOINT )
  307. {
  308. if ( m_pCollision )
  309. g_pGame->GetElementDeleter()->Delete ( m_pCollision );
  310. m_pCollision = new CColSphere ( m_pColManager, NULL, m_vecPosition, m_fSize, NULL );
  311. }
  312. m_pCollision->SetCallback ( this );
  313. m_pCollision->SetAutoCallEvent ( false );
  314. }
  315. // Set the radius after the size
  316. if ( m_ucType == CMarker::TYPE_CHECKPOINT )
  317. {
  318. static_cast < CColCircle* > ( m_pCollision )->SetRadius ( m_fSize );
  319. }
  320. else
  321. {
  322. static_cast < CColSphere* > ( m_pCollision )->SetRadius ( m_fSize );
  323. }
  324. }