SpikeStrip.inc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. /*
  2. * SA-MP Spike Strips
  3. *
  4. * Copyright (c) 2013, Stylock
  5. * This file is provided as is with no warranties of any kind.
  6. */
  7. /*
  8. * Changelog
  9. *
  10. * 13/8/2013
  11. * ~ shortened the prefix from "SpikeStrip" to "Stinger"
  12. * ~ added a config option to enable/disable the OnSpikeStripPopTire callback
  13. * ~ added a config option to enable/disable the Streamer plugin support
  14. *
  15. * 5/7/2013:
  16. * ~ changed parameter order in OnSpikeStripPopTire callback
  17. * ~ fixed a bug where OnSpikeStripPopTire callback wasn't getting called
  18. * ~ fixed incorrect arguments being passed to SetTimer function
  19. * ~ added a function named SpikeStrip_DeleteAll that deletes all spike strips
  20. *
  21. * 4/7/2013:
  22. * ~ removed the auto-adjustment of the Z coordinate when creating a spike strip
  23. * ~ added a callback named OnSpikeStripPopTire that is called when a tire is popped
  24. * ~ added a function named SpikeStrip_IsValid that checks the validity of a spike strip
  25. * ~ added a function named SpikeStrip_SetGhost that toggles a player's ghost mode
  26. * ~ added a function named SpikeStrip_IsGhost that checks a player's ghost mode
  27. *
  28. * 3/7/2013:
  29. * ~ initial release
  30. */
  31. #include <a_samp>
  32. // Alternatively use foreach
  33. #include <YSI\y_iterate>
  34. #define MAX_SPIKE_STRIPS (100)
  35. #define SS_TIME_INTERVAL (250)
  36. #define SS_LINE_SEGMENTS (2) // 1, 2 or 4
  37. #define SS_USE_CALLBACK (true) // OnSpikeStripPopTire
  38. #define SS_USE_STREAMER (false) // Streamer plugin support
  39. // Spike strip models
  40. #define SPIKE_STRIP_LONG (2892)
  41. #define SPIKE_STRIP_SHORT (2899)
  42. static stock
  43. g_SpikeStrip[MAX_SPIKE_STRIPS],
  44. Iterator:g_Spike<MAX_SPIKE_STRIPS>,
  45. Float:g_Spike_x1[MAX_SPIKE_STRIPS],
  46. Float:g_Spike_y1[MAX_SPIKE_STRIPS],
  47. Float:g_Spike_x2[MAX_SPIKE_STRIPS],
  48. Float:g_Spike_y2[MAX_SPIKE_STRIPS],
  49. Float:g_Spike_x3[MAX_SPIKE_STRIPS],
  50. Float:g_Spike_y3[MAX_SPIKE_STRIPS],
  51. Float:g_Spike_x4[MAX_SPIKE_STRIPS],
  52. Float:g_Spike_y4[MAX_SPIKE_STRIPS],
  53. Float:g_Spike_zA[MAX_SPIKE_STRIPS],
  54. Float:g_Tire1_x1[MAX_PLAYERS],
  55. Float:g_Tire1_y1[MAX_PLAYERS],
  56. Float:g_Tire1_z1[MAX_PLAYERS],
  57. Float:g_Tire1_x2[MAX_PLAYERS],
  58. Float:g_Tire1_y2[MAX_PLAYERS],
  59. Float:g_Tire1_z2[MAX_PLAYERS],
  60. Float:g_Tire1_x3[MAX_PLAYERS],
  61. Float:g_Tire1_y3[MAX_PLAYERS],
  62. Float:g_Tire1_z3[MAX_PLAYERS],
  63. Float:g_Tire1_x4[MAX_PLAYERS],
  64. Float:g_Tire1_y4[MAX_PLAYERS],
  65. Float:g_Tire1_z4[MAX_PLAYERS],
  66. Float:g_Tire2_x1[MAX_PLAYERS],
  67. Float:g_Tire2_y1[MAX_PLAYERS],
  68. Float:g_Tire2_x2[MAX_PLAYERS],
  69. Float:g_Tire2_z1[MAX_PLAYERS],
  70. Float:g_Tire2_y2[MAX_PLAYERS],
  71. Float:g_Tire2_z2[MAX_PLAYERS],
  72. g_GetGhostMode[MAX_PLAYERS char],
  73. g_GetTireState[MAX_PLAYERS char],
  74. g_GetTireCount[MAX_PLAYERS char],
  75. g_GetVehicleID[MAX_PLAYERS],
  76. g_GetTickCount[MAX_PLAYERS],
  77. g_GetServerTC;
  78. enum (<<= 1)
  79. {
  80. e_TIRE_RR = 0b0001,
  81. e_TIRE_FR,
  82. e_TIRE_RL,
  83. e_TIRE_FL,
  84. }
  85. // Forwards
  86. forward SS_GetTickCount();
  87. forward OnSpikeStripPopTire(spikeid, vehicleid, playerid, tire);
  88. public SS_GetTickCount()
  89. {
  90. // Store the tick count for fast access. Better than
  91. // calling the function 20 times per second per player.
  92. g_GetServerTC = GetTickCount();
  93. return 1;
  94. }
  95. public OnGameModeInit()
  96. {
  97. SetTimer("SS_GetTickCount", 50, 1);
  98. #if defined SS_OnGameModeInit
  99. return SS_OnGameModeInit();
  100. #else
  101. return 1;
  102. #endif
  103. }
  104. #if defined _ALS_OnGameModeInit
  105. #undef OnGameModeInit
  106. #else
  107. #define _ALS_OnGameModeInit
  108. #endif
  109. #define OnGameModeInit SS_OnGameModeInit
  110. #if defined SS_OnGameModeInit
  111. forward SS_OnGameModeInit();
  112. #endif
  113. public OnPlayerUpdate(playerid)
  114. {
  115. static
  116. Float:matrix3x3[9],
  117. Float:x1, Float:y1, Float:z1,
  118. Float:x2, Float:y2, Float:z2,
  119. Float:x3, Float:y3, Float:z3,
  120. Float:x4, Float:y4, Float:z4;
  121. if (g_GetTickCount[playerid] < g_GetServerTC)
  122. {
  123. if (GetPlayerState(playerid) == 2) // Driver
  124. {
  125. if (IsPlayerNPC(playerid))
  126. {
  127. return 1;
  128. }
  129. if (!g_GetGhostMode{playerid})
  130. {
  131. new
  132. vid = GetPlayerVehicleID(playerid);
  133. if (vid != g_GetVehicleID[playerid])
  134. {
  135. new
  136. mid = GetVehicleModel(vid);
  137. g_GetTireCount{playerid} = SS_GetTireCount(mid);
  138. g_GetTireState{playerid} = SS_GetTireState(vid);
  139. GetVehicleModelInfo(mid, 6, x1, y1, z1);
  140. SS_GetTireSize(mid, e_TIRE_RR, z2);
  141. // Save rear wheel offsets
  142. g_Tire2_x1[playerid] = x1,
  143. g_Tire2_y1[playerid] = y1,
  144. g_Tire2_z1[playerid] = z1 - z2 / 2;
  145. GetVehicleModelInfo(mid, 5, x1, y1, z1);
  146. SS_GetTireSize(mid, e_TIRE_FR, z2);
  147. // Save front wheel offsets
  148. g_Tire2_x2[playerid] = x1,
  149. g_Tire2_y2[playerid] = y1,
  150. g_Tire2_z2[playerid] = z1 - z2 / 2;
  151. }
  152. if (g_GetTireCount{playerid}) // Check if the player's vehicle has any tires
  153. {
  154. if (g_GetTireState{playerid} < 0b1111) // Check if at least one tire is not flat (0b1111 = all tires are flat)
  155. {
  156. SS_GetVehicleRotationMatrix(vid, matrix3x3);
  157. // If the tire is not flat, then get its position
  158. !(g_GetTireState{playerid} & e_TIRE_RR) && SS_GetTirePos(vid, x1, y1, z1, g_Tire2_x1[playerid], g_Tire2_y1[playerid], g_Tire2_z1[playerid], matrix3x3), // RR
  159. !(g_GetTireState{playerid} & e_TIRE_FR) && SS_GetTirePos(vid, x2, y2, z2, g_Tire2_x2[playerid], g_Tire2_y2[playerid], g_Tire2_z2[playerid], matrix3x3); // FR
  160. if (g_GetTireCount{playerid} > 2)
  161. {
  162. !(g_GetTireState{playerid} & e_TIRE_RL) && SS_GetTirePos(vid, x3, y3, z3, -g_Tire2_x1[playerid], g_Tire2_y1[playerid], g_Tire2_z1[playerid], matrix3x3), // RL
  163. !(g_GetTireState{playerid} & e_TIRE_FL) && SS_GetTirePos(vid, x4, y4, z4, -g_Tire2_x2[playerid], g_Tire2_y2[playerid], g_Tire2_z2[playerid], matrix3x3); // FL
  164. }
  165. foreach (new i : g_Spike)
  166. {
  167. if (IsPlayerInRangeOfPoint(playerid, 60.0, g_Spike_x1[i], g_Spike_y1[i], g_Spike_zA[i]))
  168. {
  169. // If the tire is not flat, then monitor it
  170. !(g_GetTireState{playerid} & e_TIRE_RR) && SS_MonitorTire(vid, e_TIRE_RR, i, playerid, x1, y1, z1, g_Tire1_x1[playerid], g_Tire1_y1[playerid], g_Tire1_z1[playerid]), // RR
  171. !(g_GetTireState{playerid} & e_TIRE_FR) && SS_MonitorTire(vid, e_TIRE_FR, i, playerid, x2, y2, z2, g_Tire1_x2[playerid], g_Tire1_y2[playerid], g_Tire1_z2[playerid]); // FR
  172. if (g_GetTireCount{playerid} > 2)
  173. {
  174. !(g_GetTireState{playerid} & e_TIRE_RL) && SS_MonitorTire(vid, e_TIRE_RL, i, playerid, x3, y3, z3, g_Tire1_x3[playerid], g_Tire1_y3[playerid], g_Tire1_z3[playerid]), // RL
  175. !(g_GetTireState{playerid} & e_TIRE_FL) && SS_MonitorTire(vid, e_TIRE_FL, i, playerid, x4, y4, z4, g_Tire1_x4[playerid], g_Tire1_y4[playerid], g_Tire1_z4[playerid]); // FL
  176. }
  177. }
  178. }
  179. // If the tire is not flat, then save its position
  180. !(g_GetTireState{playerid} & e_TIRE_RR) && (g_Tire1_x1[playerid] = x1, g_Tire1_y1[playerid] = y1, g_Tire1_z1[playerid] = z1),
  181. !(g_GetTireState{playerid} & e_TIRE_FR) && (g_Tire1_x2[playerid] = x2, g_Tire1_y2[playerid] = y2, g_Tire1_z2[playerid] = z2);
  182. if (g_GetTireCount{playerid} > 2)
  183. {
  184. !(g_GetTireState{playerid} & e_TIRE_RL) && (g_Tire1_x3[playerid] = x3, g_Tire1_y3[playerid] = y3, g_Tire1_z3[playerid] = z3),
  185. !(g_GetTireState{playerid} & e_TIRE_FL) && (g_Tire1_x4[playerid] = x4, g_Tire1_y4[playerid] = y4, g_Tire1_z4[playerid] = z4);
  186. }
  187. }
  188. }
  189. g_GetVehicleID[playerid] = vid;
  190. }
  191. }
  192. g_GetTickCount[playerid] = g_GetServerTC + SS_TIME_INTERVAL;
  193. }
  194. #if defined SS_OnPlayerUpdate
  195. return SS_OnPlayerUpdate(playerid);
  196. #else
  197. return 1;
  198. #endif
  199. }
  200. #if defined _ALS_OnPlayerUpdate
  201. #undef OnPlayerUpdate
  202. #else
  203. #define _ALS_OnPlayerUpdate
  204. #endif
  205. #define OnPlayerUpdate SS_OnPlayerUpdate
  206. #if defined SS_OnPlayerUpdate
  207. forward SS_OnPlayerUpdate(playerid);
  208. #endif
  209. public OnVehicleDamageStatusUpdate(vehicleid, playerid)
  210. {
  211. new
  212. tire_state = SS_GetTireState(vehicleid);
  213. if (tire_state != g_GetTireState{playerid})
  214. {
  215. if (g_GetTireState{playerid} > tire_state) // Check if at least one tire is fixed
  216. {
  217. new
  218. Float:matrix3x3[9];
  219. SS_GetVehicleRotationMatrix(vehicleid, matrix3x3);
  220. if (e_TIRE_RR & (g_GetTireState{playerid} & ~tire_state)) // If a flat tire is fixed
  221. {
  222. SS_GetTirePos(vehicleid, g_Tire1_x1[playerid], g_Tire1_y1[playerid], g_Tire1_z1[playerid], g_Tire2_x1[playerid], g_Tire2_y1[playerid], g_Tire2_z1[playerid], matrix3x3);
  223. }
  224. if (e_TIRE_FR & (g_GetTireState{playerid} & ~tire_state)) // If a flat tire is fixed
  225. {
  226. SS_GetTirePos(vehicleid, g_Tire1_x2[playerid], g_Tire1_y2[playerid], g_Tire1_z2[playerid], g_Tire2_x2[playerid], g_Tire2_y2[playerid], g_Tire2_z2[playerid], matrix3x3);
  227. }
  228. if (e_TIRE_RL & (g_GetTireState{playerid} & ~tire_state)) // If a flat tire is fixed
  229. {
  230. SS_GetTirePos(vehicleid, g_Tire1_x3[playerid], g_Tire1_y3[playerid], g_Tire1_z3[playerid], -g_Tire2_x1[playerid], g_Tire2_y1[playerid], g_Tire2_z1[playerid], matrix3x3);
  231. }
  232. if (e_TIRE_FL & (g_GetTireState{playerid} & ~tire_state)) // If a flat tire is fixed
  233. {
  234. SS_GetTirePos(vehicleid, g_Tire1_x4[playerid], g_Tire1_y4[playerid], g_Tire1_z4[playerid], -g_Tire2_x2[playerid], g_Tire2_y2[playerid], g_Tire2_z2[playerid], matrix3x3);
  235. }
  236. }
  237. g_GetTireState{playerid} = tire_state;
  238. }
  239. #if defined SS_OnVehicleDamageStatusUpdate
  240. return SS_OnVehicleDamageStatusUpdate(vehicleid, playerid);
  241. #else
  242. return 1;
  243. #endif
  244. }
  245. #if defined _ALS_OnVehicleDamageStatusUpd
  246. #undef OnVehicleDamageStatusUpdate
  247. #else
  248. #define _ALS_OnVehicleDamageStatusUpd
  249. #endif
  250. #define OnVehicleDamageStatusUpdate SS_OnVehicleDamageStatusUpdate
  251. #if defined SS_OnVehicleDamageStatusUpdate
  252. forward SS_OnVehicleDamageStatusUpdate(vehicleid, playerid);
  253. #endif
  254. stock SS_MonitorTire(vid, tire, sid, pid, Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2)
  255. {
  256. new
  257. Float:distance = 1.0;
  258. if (SS_SegmentsIntersect_2D(g_Spike_x1[sid], g_Spike_y1[sid], g_Spike_x2[sid], g_Spike_y2[sid], x1, y1, x2, y2))
  259. {
  260. SS_DistanceLineToLine_3D(g_Spike_x1[sid], g_Spike_y1[sid], g_Spike_zA[sid], g_Spike_x2[sid], g_Spike_y2[sid], g_Spike_zA[sid], x1, y1, z1, x2, y2, z2, distance);
  261. }
  262. #if SS_LINE_SEGMENTS >= 2
  263. else if (SS_SegmentsIntersect_2D(g_Spike_x3[sid], g_Spike_y3[sid], g_Spike_x4[sid], g_Spike_y4[sid], x1, y1, x2, y2))
  264. {
  265. SS_DistanceLineToLine_3D(g_Spike_x3[sid], g_Spike_y3[sid], g_Spike_zA[sid], g_Spike_x4[sid], g_Spike_y4[sid], g_Spike_zA[sid], x1, y1, z1, x2, y2, z2, distance);
  266. }
  267. #endif
  268. #if SS_LINE_SEGMENTS == 4
  269. else if (SS_SegmentsIntersect_2D(g_Spike_x1[sid], g_Spike_y1[sid], g_Spike_x3[sid], g_Spike_y3[sid], x1, y1, x2, y2))
  270. {
  271. SS_DistanceLineToLine_3D(g_Spike_x1[sid], g_Spike_y1[sid], g_Spike_zA[sid], g_Spike_x3[sid], g_Spike_y3[sid], g_Spike_zA[sid], x1, y1, z1, x2, y2, z2, distance);
  272. }
  273. else if (SS_SegmentsIntersect_2D(g_Spike_x2[sid], g_Spike_y2[sid], g_Spike_x4[sid], g_Spike_y4[sid], x1, y1, x2, y2))
  274. {
  275. SS_DistanceLineToLine_3D(g_Spike_x2[sid], g_Spike_y2[sid], g_Spike_zA[sid], g_Spike_x4[sid], g_Spike_y4[sid], g_Spike_zA[sid], x1, y1, z1, x2, y2, z2, distance);
  276. }
  277. #endif
  278. if (distance < 0.24)
  279. {
  280. if (vid == g_GetVehicleID[pid]) // Make sure surprise tire pops don't occur
  281. {
  282. new
  283. data1,
  284. data2,
  285. data3,
  286. data4;
  287. GetVehicleDamageStatus(vid, data1, data2, data3, data4);
  288. UpdateVehicleDamageStatus(vid, data1, data2, data3, (data4 | tire)); // Pop
  289. #if SS_USE_CALLBACK
  290. CallRemoteFunction("OnSpikeStripPopTire", "iiii", sid, vid, pid, tire);
  291. #endif
  292. }
  293. }
  294. return 1;
  295. }
  296. stock SS_GetTireState(vid)
  297. {
  298. new
  299. data;
  300. GetVehicleDamageStatus(vid, data, data, data, data);
  301. return data;
  302. }
  303. stock SS_GetTireCount(mid)
  304. {
  305. static const
  306. tire_data[] =
  307. {
  308. 4, 4, 4, 6, 4, 4, 4, 4, 6, 4,
  309. 4, 4, 4, 4, 4, 4, 4, 0, 4, 4,
  310. 4, 4, 4, 4, 4, 0, 4, 4, 4, 4,
  311. 0, 6, 4, 6, 4, 4, 4, 6, 4, 4,
  312. 4, 0, 4, 6, 4, 4, 0, 0, 2, 0,
  313. 4, 4, 0, 0, 0, 6, 4, 4, 4, 4,
  314. 0, 2, 2, 2, 0, 0, 4, 4, 2, 0,
  315. 4, 4, 0, 0, 4, 4, 0, 4, 4, 4,
  316. 4, 0, 4, 4, 0, 4, 4, 0, 0, 4,
  317. 4, 4, 4, 0, 4, 4, 4, 0, 4, 4,
  318. 4, 0, 4, 4, 4, 4, 4, 4, 4, 0,
  319. 0, 0, 0, 0, 6, 6, 4, 4, 4, 0,
  320. 0, 2, 2, 2, 6, 4, 4, 4, 4, 4,
  321. 4, 4, 6, 4, 4, 4, 4, 0, 0, 0,
  322. 4, 4, 4, 4, 4, 4, 4, 4, 0, 4,
  323. 4, 4, 4, 0, 4, 4, 4, 4, 4, 4,
  324. 4, 4, 4, 0, 0, 4, 4, 4, 4, 0,
  325. 0, 4, 4, 4, 4, 4, 4, 0, 6, 4,
  326. 4, 2, 4, 4, 4, 4, 2, 4, 4, 4,
  327. 0, 4, 0, 0, 0, 0, 4, 4, 4, 4,
  328. 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
  329. 4, 4
  330. };
  331. // Aircraft, boats, bicycles, trains
  332. // and RC vehicles return zero tires
  333. return tire_data[mid - 400];
  334. }
  335. stock SS_GetTireSize(mid, tire, &Float:size)
  336. {
  337. static const
  338. Float:tire_size_R[] =
  339. {
  340. // Rear wheel size (from vehicles.ide)
  341. 0.7680, 0.7749, 0.6999, 1.1000, 0.6600, 0.6999, 2.2799, 1.0000, 1.0599, 0.7500,
  342. 0.8000, 0.6999, 0.6999, 0.7200, 0.7599, 0.6800, 0.8640, 0.0000, 0.6999, 0.6399,
  343. 0.7879, 0.6499, 0.6999, 0.6999, 0.9200, 0.0000, 0.6999, 0.9359, 0.9139, 0.6999,
  344. 0.0000, 1.0000, 1.2999, 1.2000, 0.8000, 1.1000, 0.6999, 1.0000, 0.6999, 0.6999,
  345. 0.6999, 0.0000, 0.6800, 1.0820, 1.5000, 0.6800, 0.0000, 0.0000, 0.4639, 0.0000,
  346. 1.1000, 0.7500, 0.0000, 0.0000, 0.0000, 1.2000, 0.8399, 0.5000, 0.7200, 0.6999,
  347. 0.0000, 0.6700, 0.4639, 0.5600, 0.0000, 0.0000, 0.6999, 0.6999, 0.6200, 0.0000,
  348. 0.8939, 0.6000, 0.0000, 0.0000, 0.6999, 0.6999, 0.0000, 0.7599, 0.6999, 0.6999,
  349. 0.6999, 0.0000, 0.6999, 0.6600, 0.0000, 0.6000, 1.5000, 0.0000, 0.0000, 0.8999,
  350. 0.9200, 0.6499, 0.6999, 0.0000, 0.8199, 0.9720, 0.6999, 0.0000, 0.7599, 0.8000,
  351. 0.8000, 0.0000, 0.8199, 0.8199, 0.6999, 0.8999, 0.7730, 0.6999, 0.8000, 0.0000,
  352. 0.0000, 0.0000, 0.0000, 0.0000, 1.1059, 1.1799, 0.7500, 0.7500, 0.6600, 0.0000,
  353. 0.0000, 0.6800, 0.6800, 0.6700, 1.0000, 0.9200, 0.6999, 0.6999, 0.8500, 0.6999,
  354. 0.4499, 1.2999, 1.0000, 0.6999, 0.6999, 0.7400, 0.6999, 0.0000, 0.0000, 0.0000,
  355. 0.6999, 1.0000, 0.7400, 0.6999, 1.0000, 0.6999, 0.6999, 0.6999, 0.0000, 0.6840,
  356. 0.7599, 0.7500, 0.8399, 0.0000, 0.8399, 0.6999, 1.5000, 1.5000, 0.7879, 0.6999,
  357. 0.8700, 0.6999, 0.6800, 0.0000, 0.0000, 0.6399, 0.6999, 0.6999, 0.6999, 0.0000,
  358. 0.0000, 0.2599, 0.5600, 1.1399, 0.5000, 0.6999, 0.6999, 0.0000, 1.0000, 0.8999,
  359. 0.7799, 0.6800, 0.7699, 0.7500, 1.1200, 0.7400, 0.6539, 0.6999, 0.8600, 0.7400,
  360. 0.0000, 1.1000, 0.0000, 0.0000, 0.0000, 0.0000, 0.6999, 0.6999, 0.6999, 0.9499,
  361. 0.6999, 1.3660, 0.6999, 0.6999, 0.6999, 0.6999, 0.6000, 0.6000, 0.6000, 0.7599,
  362. 0.3199, 0.6800
  363. };
  364. if (tire & (e_TIRE_RR | e_TIRE_RL))
  365. {
  366. size = tire_size_R[mid - 400];
  367. return 1;
  368. }
  369. static const
  370. Float:tire_size_F[] =
  371. {
  372. // Front wheel size (from vehicles.ide)
  373. 0.7680, 0.7749, 0.6999, 1.1000, 0.6600, 0.6999, 2.2799, 1.0000, 1.0599, 0.7500,
  374. 0.8000, 0.6999, 0.6999, 0.7200, 0.7599, 0.6800, 0.8640, 0.0000, 0.6999, 0.6399,
  375. 0.7879, 0.6499, 0.6999, 0.6999, 0.8399, 0.0000, 0.6999, 0.9359, 0.9139, 0.6999,
  376. 0.0000, 1.0000, 1.2999, 1.2000, 0.7200, 1.1000, 0.6999, 1.0000, 0.6999, 0.6999,
  377. 0.6999, 0.0000, 0.6800, 1.0820, 1.5000, 0.6800, 0.0000, 0.0000, 0.4639, 0.0000,
  378. 1.1000, 0.6999, 0.0000, 0.0000, 0.0000, 1.2000, 0.8399, 0.5000, 0.7200, 0.6999,
  379. 0.0000, 0.6700, 0.4639, 0.7799, 0.0000, 0.0000, 0.6999, 0.6999, 0.6800, 0.0000,
  380. 0.8939, 0.6000, 0.0000, 0.0000, 0.6999, 0.6999, 0.0000, 0.7599, 0.6999, 0.6999,
  381. 0.6999, 0.0000, 0.6999, 0.6600, 0.0000, 0.6000, 1.5000, 0.0000, 0.0000, 0.8999,
  382. 0.9200, 0.6499, 0.6999, 0.0000, 0.8199, 0.9720, 0.6999, 0.0000, 0.7599, 0.8000,
  383. 0.8000, 0.0000, 0.8199, 0.8199, 0.6999, 0.8999, 0.7730, 0.6999, 0.8000, 0.0000,
  384. 0.0000, 0.0000, 0.0000, 0.0000, 1.1059, 1.1799, 0.7500, 0.7500, 0.6600, 0.0000,
  385. 0.0000, 0.6800, 0.6800, 0.6700, 1.1200, 0.9200, 0.6999, 0.6999, 0.8500, 0.6999,
  386. 0.4499, 0.6800, 0.5879, 0.6999, 0.6999, 0.7400, 0.6999, 0.0000, 0.0000, 0.0000,
  387. 0.6999, 1.0000, 0.7400, 0.6999, 1.0000, 0.6999, 0.6999, 0.6999, 0.0000, 0.6840,
  388. 0.7599, 0.7500, 0.8399, 0.0000, 0.8399, 0.6999, 1.5000, 1.5000, 0.7879, 0.6999,
  389. 0.8700, 0.6999, 0.6800, 0.0000, 0.0000, 0.6399, 0.6999, 0.6999, 0.5500, 0.0000,
  390. 0.0000, 0.2599, 0.4799, 1.1399, 0.5000, 0.6999, 0.6999, 0.0000, 1.0000, 0.8999,
  391. 0.7799, 0.6800, 0.7699, 0.6600, 1.1200, 0.7400, 0.6539, 0.6999, 0.8600, 0.7400,
  392. 0.0000, 1.1000, 0.0000, 0.0000, 0.0000, 0.0000, 0.6999, 0.6999, 0.6999, 0.9499,
  393. 0.6999, 1.3660, 0.6999, 0.6999, 0.6999, 0.6999, 0.6000, 0.6000, 0.6000, 0.7599,
  394. 0.3199, 0.6800
  395. };
  396. if (tire & (e_TIRE_FR | e_TIRE_FL))
  397. {
  398. size = tire_size_F[mid - 400];
  399. return 1;
  400. }
  401. return 0;
  402. }
  403. stock SS_GetTirePos(vid, &Float:px, &Float:py, &Float:pz, Float:ox, Float:oy, Float:oz, Float:matrix3x3[])
  404. {
  405. GetVehiclePos(vid, px, py, pz);
  406. px = px + ox * (1 - 2 * (matrix3x3[4] + matrix3x3[7])) + oy * (2 * (matrix3x3[1] + matrix3x3[8])) + oz * (2 * (matrix3x3[2] - matrix3x3[6])),
  407. py = py + ox * (2 * (matrix3x3[1] - matrix3x3[8])) + oy * (1 - 2 * (matrix3x3[0] + matrix3x3[7])) + oz * (2 * (matrix3x3[5] + matrix3x3[3])),
  408. pz = pz + ox * (2 * (matrix3x3[2] + matrix3x3[6])) + oy * (2 * (matrix3x3[5] - matrix3x3[3])) + oz * (1 - 2 * (matrix3x3[0] + matrix3x3[4]));
  409. return 1;
  410. }
  411. stock SS_GetVehicleRotationMatrix(vid, Float:matrix3x3[])
  412. {
  413. new
  414. Float:qw,
  415. Float:qx,
  416. Float:qy,
  417. Float:qz;
  418. GetVehicleRotationQuat(vid, qw, qx, qy, qz);
  419. matrix3x3[0] = qx * qx, matrix3x3[1] = qx * qy, matrix3x3[2] = qx * qz,
  420. matrix3x3[3] = qx * qw, matrix3x3[4] = qy * qy, matrix3x3[5] = qy * qz,
  421. matrix3x3[6] = qy * qw, matrix3x3[7] = qz * qz, matrix3x3[8] = qz * qw;
  422. return 1;
  423. }
  424. /*
  425. This function checks if two line segments intersect (2D space)
  426. */
  427. stock SS_SegmentsIntersect_2D(Float:x1, Float:y1, Float:x2, Float:y2, Float:x3, Float:y3, Float:x4, Float:y4)
  428. {
  429. new
  430. Float:xA = x2 - x1,
  431. Float:yA = y2 - y1,
  432. Float:xB = x4 - x3,
  433. Float:yB = y4 - y3,
  434. Float:d = xA * yB - yA * xB;
  435. if (!d)
  436. {
  437. // Lines are parallel, or one or
  438. // both segments are zero-length
  439. return 0;
  440. }
  441. new
  442. Float:xC = x3 - x1,
  443. Float:yC = y3 - y1,
  444. Float:pA = (xC * yB - yC * xB) / d,
  445. Float:pB = (xC * yA - yC * xA) / d;
  446. if (pA < 0 || pA > 1 || pB < 0 || pB > 1)
  447. {
  448. return 0;
  449. }
  450. // Compute the intersection point
  451. // xi = x1 + pA * xA
  452. // yi = y1 + pA * yA
  453. return 1;
  454. }
  455. /*
  456. This function computes the shortest distance between two lines (3D space)
  457. */
  458. stock SS_DistanceLineToLine_3D(Float:x1, Float:y1, Float:z1, Float:x2, Float:y2, Float:z2, Float:x3, Float:y3, Float:z3, Float:x4, Float:y4, Float:z4, &Float:distance)
  459. {
  460. new
  461. Float:ux = x2 - x1,
  462. Float:uy = y2 - y1,
  463. Float:uz = z2 - z1,
  464. Float:vx = x4 - x3,
  465. Float:vy = y4 - y3,
  466. Float:vz = z4 - z3,
  467. Float:wx = x1 - x3,
  468. Float:wy = y1 - y3,
  469. Float:wz = z1 - z3,
  470. Float:uu = ux * ux + uy * uy + uz * uz,
  471. Float:uv = ux * vx + uy * vy + uz * vz,
  472. Float:uw = ux * wx + uy * wy + uz * wz,
  473. Float:vv = vx * vx + vy * vy + vz * vz,
  474. Float:vw = vx * wx + vy * wy + vz * wz,
  475. Float:d = uu * vv - uv * uv,
  476. Float:pA = (uv * vw - vv * uw) / d,
  477. Float:pB = (uu * vw - uv * uw) / d,
  478. // The difference of the two closest points
  479. Float:dx = wx + pA * ux - pB * vx,
  480. Float:dy = wy + pA * uy - pB * vy,
  481. Float:dz = wz + pA * uz - pB * vz;
  482. distance = floatsqroot(dx * dx + dy * dy + dz * dz);
  483. return 1;
  484. }
  485. #if !SS_USE_STREAMER
  486. #define SS_CreateObject(%0) \
  487. CreateObject(%0, 200.0)
  488. #define SS_DestroyObject \
  489. DestroyObject
  490. #else
  491. #include <streamer>
  492. #define SS_CreateObject \
  493. CreateDynamicObject
  494. #define SS_DestroyObject \
  495. DestroyDynamicObject
  496. #endif
  497. /*
  498. native Stinger_Create(mid, Float:x, Float:y, Float:z, Float:a);
  499. */
  500. stock Stinger_Create(mid, Float:x, Float:y, Float:z, Float:a)
  501. {
  502. new
  503. idx = Iter_Free(g_Spike);
  504. if (idx != -1)
  505. {
  506. new
  507. Float:adjust,
  508. Float:length;
  509. switch (mid)
  510. {
  511. case 2892:
  512. {
  513. length = 5.0;
  514. }
  515. case 2899:
  516. {
  517. length = 2.5;
  518. adjust = 0.118;
  519. }
  520. default:
  521. {
  522. return INVALID_OBJECT_ID;
  523. }
  524. }
  525. new
  526. id = SS_CreateObject(mid, x, y, z + adjust, 0.0, 0.0, a - 90.0);
  527. if (id != INVALID_OBJECT_ID)
  528. {
  529. a = -a;
  530. Iter_Add(g_Spike, idx);
  531. g_SpikeStrip[idx] = id;
  532. #if SS_LINE_SEGMENTS == 1
  533. g_Spike_x1[idx] = x + length * floatsin(a - 90.0, degrees);
  534. g_Spike_y1[idx] = y + length * floatcos(a - 90.0, degrees);
  535. g_Spike_x2[idx] = x - length * floatsin(a - 90.0, degrees);
  536. g_Spike_y2[idx] = y - length * floatcos(a - 90.0, degrees);
  537. #endif
  538. #if SS_LINE_SEGMENTS >= 2
  539. new
  540. value;
  541. mid != 2892 && (value = 10) || (value = 5);
  542. g_Spike_x1[idx] = x + length * floatsin(a - (90.0 + value), degrees);
  543. g_Spike_y1[idx] = y + length * floatcos(a - (90.0 + value), degrees);
  544. g_Spike_x3[idx] = x + length * floatsin(a - (90.0 - value), degrees);
  545. g_Spike_y3[idx] = y + length * floatcos(a - (90.0 - value), degrees);
  546. #if SS_LINE_SEGMENTS == 2
  547. g_Spike_x2[idx] = x - length * floatsin(a - (90.0 + value), degrees);
  548. g_Spike_y2[idx] = y - length * floatcos(a - (90.0 + value), degrees);
  549. g_Spike_x4[idx] = x - length * floatsin(a - (90.0 - value), degrees);
  550. g_Spike_y4[idx] = y - length * floatcos(a - (90.0 - value), degrees);
  551. #endif
  552. #if SS_LINE_SEGMENTS == 4
  553. g_Spike_x2[idx] = x - length * floatsin(a - (90.0 - value), degrees);
  554. g_Spike_y2[idx] = y - length * floatcos(a - (90.0 - value), degrees);
  555. g_Spike_x4[idx] = x - length * floatsin(a - (90.0 + value), degrees);
  556. g_Spike_y4[idx] = y - length * floatcos(a - (90.0 + value), degrees);
  557. #endif
  558. #endif
  559. g_Spike_zA[idx] = z;
  560. return idx;
  561. }
  562. }
  563. return INVALID_OBJECT_ID;
  564. }
  565. #define SpikeStrip_Create Stinger_Create
  566. /*
  567. native Stinger_Delete(sid);
  568. */
  569. stock Stinger_Delete(sid)
  570. {
  571. if (Iter_Contains(g_Spike, sid))
  572. {
  573. SS_DestroyObject(g_SpikeStrip[sid]);
  574. Iter_Remove(g_Spike, sid);
  575. }
  576. return 1;
  577. }
  578. #define SpikeStrip_Delete Stinger_Delete
  579. /*
  580. native Stinger_DeleteAll();
  581. */
  582. stock Stinger_DeleteAll()
  583. {
  584. foreach (new i : g_Spike)
  585. {
  586. SS_DestroyObject(g_SpikeStrip[i]);
  587. Iter_SafeRemove(g_Spike, i, i);
  588. }
  589. return 1;
  590. }
  591. #define SpikeStrip_DeleteAll Stinger_DeleteAll
  592. /*
  593. native Stinger_IsValid(sid);
  594. */
  595. stock Stinger_IsValid(sid)
  596. {
  597. return Iter_Contains(g_Spike, sid);
  598. }
  599. #define SpikeStrip_IsValid Stinger_IsValid
  600. /*
  601. native Stinger_SetGhost(pid, bool:toggle);
  602. */
  603. stock Stinger_SetGhost(pid, bool:toggle)
  604. {
  605. g_GetVehicleID[pid] = 0;
  606. g_GetGhostMode{pid} = toggle;
  607. return 1;
  608. }
  609. #define SpikeStrip_SetGhost Stinger_SetGhost
  610. /*
  611. native Stinger_IsGhost(pid);
  612. */
  613. stock Stinger_IsGhost(pid)
  614. {
  615. return g_GetGhostMode{pid};
  616. }
  617. #define SpikeStrip_IsGhost Stinger_IsGhost