iterators.inc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /**--------------------------------------------------------------------------**\
  2. ===========================
  3. foreach efficient looping
  4. ===========================
  5. Description:
  6. Provides efficient looping through sparse data sets, such as connected
  7. players. Significantly improved from the original version to be a generic
  8. loop system, rather then purely a player loop system. When used for
  9. players this has constant time O(n) for number of connected players (n),
  10. unlike standard player loops which are O(MAX_PLAYERS), regardless of the
  11. actual number of connected players. Even when n is MAX_PLAYERS this is
  12. still faster.
  13. For extensive documentation on writing and using iterators, see this topic:
  14. http://forum.sa-mp.com/showthread.php?t=481877
  15. Legal:
  16. Version: MPL 1.1
  17. The contents of this file are subject to the Mozilla Public License Version
  18. 1.1 (the "License"); you may not use this file except in compliance with
  19. the License. You may obtain a copy of the License at
  20. [url]http://www.mozilla.org/MPL/[/url]
  21. Software distributed under the License is distributed on an "AS IS" basis,
  22. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  23. for the specific language governing rights and limitations under the
  24. License.
  25. The Original Code is the YSI foreach include.
  26. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  27. Portions created by the Initial Developer are Copyright (C) 2011
  28. the Initial Developer. All Rights Reserved.
  29. Contributors:
  30. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  31. Thanks:
  32. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  33. ZeeX - Very productive conversations.
  34. koolk - IsPlayerinAreaEx code.
  35. TheAlpha - Danish translation.
  36. breadfish - German translation.
  37. Fireburn - Dutch translation.
  38. yom - French translation.
  39. 50p - Polish translation.
  40. Zamaroht - Spanish translation.
  41. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  42. for me to strive to better.
  43. Pixels^ - Running XScripters where the idea was born.
  44. Matite - Pestering me to release it and using it.
  45. Very special thanks to:
  46. Thiadmer - PAWN, whose limits continue to amaze me!
  47. Kye/Kalcor - SA:MP.
  48. SA:MP Team past, present and future - SA:MP.
  49. Version:
  50. 0.4
  51. Changelog:
  52. 29/03/15:
  53. More testing.
  54. Repaired special iterators.
  55. 28/03/15:
  56. Breaking change: "Iter_Add" returns value added, not true/false.
  57. Breaking change: Special iterators take "cellmin", not "-1".
  58. Wrote many tests.
  59. Split in to multiple files.
  60. Added multi-iterators.
  61. Officially deprecated "foreach (Player, i)".
  62. 26/03/15:
  63. Re-added reverse iterators.
  64. Added support for extra spaces in "foreach".
  65. 26/12/13:
  66. Added sections.
  67. 17/10/12:
  68. Fixed a bug that was here but not in "foreach.inc".
  69. 04/10/12:
  70. Added a tiny tweak to detect tag-returning iterator functions.
  71. Added Iter_InternalSize.
  72. 13/01/12:
  73. Fixed the count thanks to AndreT.
  74. 05/01/12:
  75. Fixed multi-dimensional iterators.
  76. Fixed "FOREACH_NO_BOTS".
  77. Made "Iterator:" support multi-dimensional arrays.
  78. 24/12/11:
  79. Added _YSI_SPECIAL_DEBUG support.
  80. Added fix for function iterators.
  81. Ported back to YSI.
  82. Changed to use internal YSI "__" natives.
  83. Fixed calls order by using ALS.
  84. 31/10/11:
  85. Changed the underlying loop code to be slightly faster.
  86. Added support for Iter_SafeRemove, prompting refactoring.
  87. 17/09/11:
  88. Fixed arrays under the new syntax.
  89. 28/04/11:
  90. Moved iterator identifiers to end of variables.
  91. Rewrote "foreach" to accept two syntaxes for "foreach (new i : Iter)".
  92. 16/08/10:
  93. Removed all the "2" versions of the functions.
  94. 14/08/10:
  95. Added Iter_Clear to reset an array.
  96. 06/08/10:
  97. Added special array declaration format.
  98. 18/12/09:
  99. Added Iter_Func2 functions for multi-dimensional iterators.
  100. Renamed foreact et al as keywords in the documentation.
  101. Changed licensing from GPL to MPL.
  102. 02/09/09:
  103. Fixed (again) for 0.3.
  104. Added free slot finding.
  105. 21/08/09:
  106. Updated to include random functions.
  107. Made entirely stand alone.
  108. Ported to 0.3 (separate version).
  109. Added automatic callback hook code.
  110. Removed debug information from stand alone version.
  111. 06/01/08:
  112. Added debug information.
  113. 09/10/07:
  114. Moved to system.
  115. 16/09/07:
  116. Added list sorting.
  117. Made this part of Y SeRver Includes, not Y Sever Includes.
  118. Made list sorting optional.
  119. Fixed version number.
  120. 08/09/07:
  121. First version.
  122. Functions:
  123. Public:
  124. OnPlayerDisconnect - Called when a player leaves to remove them.
  125. OnPlayerConnect - Called when a player connects to add them.
  126. Core:
  127. -
  128. Stock:
  129. Iter_ShowArray - Displays the contents of the array.
  130. Iter_AddInternal - Add a value to an iterator.
  131. Iter_RemoveInternal - Remove a value from an iterator.
  132. Iter_RandomInternal - Get a random item from an iterator.
  133. Iter_FreeInternal - Gets the first free slot in the iterator.
  134. Iter_InitInternal - Initialises a multi-dimensional iterator.
  135. Static:
  136. -
  137. Inline:
  138. Iter_Create - Create a new iterator value set.
  139. Iter_Add - Wraps Iter_AddInternal.
  140. Iter_Remove - Wraps Iter_RemoveInternal.
  141. Iter_Random - Wraps Iter_RandomInternal.
  142. Iter_Count - Gets the number of items in an iterator.
  143. Iter_Debug - Wraps around Iter_ShowArray.
  144. Iter_Free - Wraps around Iter_FreeInternal.
  145. Iter_Create2 - Create a new iterator array value set.
  146. Iter_Add2 - Wraps Iter_AddInternal for arrays.
  147. Iter_Remove2 - Wraps Iter_RemoveInternal for arrays.
  148. Iter_Random2 - Wraps Iter_RandomInternal for arrays.
  149. Iter_Count2 - Gets the number of items in an iterator array.
  150. Iter_Debug2 - Wraps around Iter_ShowArray for arrays.
  151. Iter_Free2 - Wraps around Iter_FreeInternal for arrays.
  152. API:
  153. -
  154. Callbacks:
  155. -
  156. Hooks:
  157. Iter_OnPlayerConnect - Hook for the OnPlayerConnect callback.
  158. Iter_OnPlayerDisconnect - Hook for the OnPlayerDisconnect callback.
  159. Iter_OnGameModeInit - Only exists to make the code compile correctly...
  160. Definitions:
  161. -
  162. Enums:
  163. -
  164. Macros:
  165. -
  166. Keywords:
  167. foreach - Command to loop an iterator.
  168. foreachex - Like foreach but without a new variable.
  169. foreach2 - Command to loop through an iterator array.
  170. foreachex - Like foreach2 but without a new variable.
  171. Tags:
  172. Iterator - Declare an iterator.
  173. Variables:
  174. Global:
  175. -
  176. Static:
  177. YSI_g_OPC - Records wether Iter_OnPlayerConnect exists for speed.
  178. YSI_g_OPDC - Records wether Iter_OnPlayerDisconnect exists for speed.
  179. Commands:
  180. -
  181. Compile options:
  182. YSI_ITTER_NO_SORT - Removed.
  183. FOREACH_NO_BOTS - Remove the bot iterators for smaller code.
  184. FOREACH_NO_PLAYERS - Remove all default code for player itteration.
  185. Operators:
  186. -
  187. Iterators:
  188. Player - List of all players connected.
  189. Bot - List of all bots (npcs) connected.
  190. NPC - Alias of Bot.
  191. Character - All players and bots.
  192. \**--------------------------------------------------------------------------**/
  193. /*
  194. 88
  195. 88 ,d ,d
  196. 88 88 88
  197. 88 MM88MMM ,adPPYba, 8b,dPPYba, ,adPPYYba, MM88MMM ,adPPYba, 8b,dPPYba, ,adPPYba,
  198. 88 88 a8P_____88 88P' "Y8 "" `Y8 88 a8" "8a 88P' "Y8 I8[ ""
  199. 88 88 8PP""""""" 88 ,adPPPPP88 88 8b d8 88 `"Y8ba,
  200. 88 88, "8b, ,aa 88 88, ,88 88, "8a, ,a8" 88 aa ]8I
  201. 88 "Y888 `"Ybbd8"' 88 `"8bbdP"Y8 "Y888 `"YbbdP"' 88 `"YbbdP"'
  202. */
  203. /**--------------------------------------------------------------------------**\
  204. Create the internal iterators.
  205. \**--------------------------------------------------------------------------**/
  206. #if _FOREACH_PLAYERS
  207. new
  208. Iterator:Player<MAX_PLAYERS>;
  209. #endif
  210. #if _FOREACH_BOTS
  211. new
  212. Iterator:Bot<MAX_PLAYERS>,
  213. Iterator:Character<MAX_PLAYERS>;
  214. #define Iter_Single@NPC Iter_Single@Bot
  215. #define Iterator@NPC Iterator@Bot
  216. #endif
  217. #if _FOREACH_ACTORS
  218. new
  219. #if _FOREACH_LOCALS
  220. Iterator:LocalActor<MAX_ACTORS>,
  221. #endif
  222. Iterator:Actor<MAX_ACTORS>;
  223. #endif
  224. #if _FOREACH_VEHICLES
  225. new
  226. #if _FOREACH_LOCALS
  227. Iterator:LocalVehicle<MAX_VEHICLES + 1>,
  228. #endif
  229. Iterator:Vehicle<MAX_VEHICLES + 1>;
  230. #endif
  231. stock iterfunc Range(cur, min, max, step = 1)
  232. {
  233. if (cur == cellmin) cur = min;
  234. else cur += step;
  235. return (min <= cur < max || max <= cur < min) ? cur : cellmin;
  236. }
  237. #define iterstart@Range cellmin
  238. stock iterfunc Powers(cur, base)
  239. {
  240. static
  241. next = 0;
  242. if (cur)
  243. {
  244. return
  245. next = base * cur,
  246. _:(next > cur) * next;
  247. }
  248. return 1;
  249. }
  250. #define iterstart@Powers 0
  251. stock iterfunc Fib(cur)
  252. {
  253. static
  254. prev = -1,
  255. next = 0;
  256. if (cur == -1)
  257. {
  258. return
  259. prev = -1,
  260. 0;
  261. }
  262. else if (prev == -1)
  263. {
  264. return
  265. prev = 0,
  266. 1;
  267. }
  268. else if (cur == 1836311903)
  269. {
  270. return -1;
  271. }
  272. return
  273. next = prev + cur,
  274. prev = cur,
  275. next;
  276. }
  277. #define iterstart@Fib (-1)
  278. stock iterfunc Random(cur, count, ...)
  279. {
  280. static
  281. num = 0;
  282. if (cur == cellmin)
  283. {
  284. num = 0;
  285. }
  286. if (++num > count)
  287. {
  288. return cellmin;
  289. }
  290. switch (numargs())
  291. {
  292. case 2:
  293. {
  294. return random(cellmax);
  295. }
  296. case 3:
  297. {
  298. return random(getarg(2));
  299. }
  300. }
  301. return
  302. count = getarg(2),
  303. random(getarg(3) - count) + count;
  304. }
  305. #define iterstart@Random cellmin
  306. stock iterfunc Null(cur, arr[], size = sizeof (arr))
  307. {
  308. while (++cur < size)
  309. {
  310. if (!arr[cur])
  311. {
  312. return cur;
  313. }
  314. }
  315. return -1;
  316. }
  317. #define iterstart@Null (-1)
  318. stock iterfunc NonNull(cur, arr[], size = sizeof (arr))
  319. {
  320. while (++cur < size)
  321. {
  322. if (arr[cur])
  323. {
  324. return cur;
  325. }
  326. }
  327. return -1;
  328. }
  329. #define iterstart@NonNull (-1)
  330. stock iterfunc Until(cur, val, arr[], size = sizeof (arr))
  331. {
  332. return (++cur >= size || arr[cur] == val) ? -1 : cur;
  333. }
  334. #define iterstart@Until (-1)
  335. stock iterfunc Filter(cur, val, arr[], size = sizeof (arr))
  336. {
  337. while (++cur < size)
  338. {
  339. if (arr[cur] == val)
  340. {
  341. return cur;
  342. }
  343. }
  344. return -1;
  345. }
  346. #define iterstart@Filter (-1)
  347. /*
  348. 88 88 88
  349. 88 88 88
  350. 88 88 88
  351. 88aaaaaaaa88 ,adPPYba, ,adPPYba, 88 ,d8 ,adPPYba,
  352. 88""""""""88 a8" "8a a8" "8a 88 ,a8" I8[ ""
  353. 88 88 8b d8 8b d8 8888[ `"Y8ba,
  354. 88 88 "8a, ,a8" "8a, ,a8" 88`"Yba, aa ]8I
  355. 88 88 `"YbbdP"' `"YbbdP"' 88 `Y8a `"YbbdP"'
  356. */
  357. /**--------------------------------------------------------------------------**\
  358. <summary>Iter_OnScriptInit</summary>
  359. <returns>
  360. -
  361. </returns>
  362. <remarks>
  363. Sets up all existing iterators. Does nothing for "XXLocal" ones, since they
  364. are by definition empty when a script starts.
  365. </remarks>
  366. \**--------------------------------------------------------------------------**/
  367. hook OnScriptInit()
  368. {
  369. #if _FOREACH_VEHICLES
  370. Iter_Clear(Vehicle);
  371. for (new i = 1; i <= MAX_VEHICLES; ++i)
  372. {
  373. if (GetVehicleModel(i))
  374. {
  375. Iter_Add(Vehicle, i);
  376. }
  377. }
  378. #endif
  379. #if _FOREACH_ACTORS
  380. Iter_Clear(Actor);
  381. for (new i = 0; i != MAX_ACTORS; ++i)
  382. {
  383. if (IsValidActor(i))
  384. {
  385. Iter_Add(Actor, i);
  386. }
  387. }
  388. #endif
  389. #if _FOREACH_CHARACTERS
  390. #if _FOREACH_BOTS
  391. Iter_Clear(Bot);
  392. Iter_Clear(Character);
  393. #endif
  394. #if _FOREACH_PLAYERS
  395. Iter_Clear(Player);
  396. #endif
  397. for (new i = 0; i != MAX_PLAYERS; ++i)
  398. {
  399. if (IsPlayerConnected(i))
  400. {
  401. #if _FOREACH_BOTS
  402. Iter_Add(Character, i);
  403. if (IsPlayerNPC(i))
  404. {
  405. Iter_Add(Bot, i);
  406. }
  407. else
  408. #endif
  409. #if _FOREACH_PLAYERS
  410. {
  411. Iter_Add(Player, i);
  412. }
  413. #endif
  414. }
  415. }
  416. #endif
  417. return 1;
  418. }
  419. /*
  420. 88888888ba 88
  421. 88 "8b 88
  422. 88 ,8P 88
  423. 88aaaaaa8P' 88 ,adPPYYba, 8b d8 ,adPPYba, 8b,dPPYba, ,adPPYba,
  424. 88""""""' 88 "" `Y8 `8b d8' a8P_____88 88P' "Y8 I8[ ""
  425. 88 88 ,adPPPPP88 `8b d8' 8PP""""""" 88 `"Y8ba,
  426. 88 88 88, ,88 `8b,d8' "8b, ,aa 88 aa ]8I
  427. 88 88 `"8bbdP"Y8 Y88' `"Ybbd8"' 88 `"YbbdP"'
  428. d8'
  429. d8'
  430. */
  431. /**--------------------------------------------------------------------------**\
  432. <summary>Iter_OnPlayerConnect</summary>
  433. <param name="playerid">Player who joined.</param>
  434. <returns>
  435. -
  436. </returns>
  437. <remarks>
  438. Adds a player to the loop data. Now sorts the list too. Note that I found
  439. the most bizzare bug ever (I *think* it may be a compiler but, but it
  440. requires further investigation), basically it seems that multiple variables
  441. were being treated as the same variable (namely @YSII_EgotS and
  442. @YSII_CgharacterS were the same and @YSII_EgotC and @YSII_CgharacterC were the
  443. same). Adding print statements which reference these variables seem to fix
  444. the problem, and I've tried to make sure that the values will never actually
  445. get printed.
  446. </remarks>
  447. \**--------------------------------------------------------------------------**/
  448. #if _FOREACH_CHARACTERS
  449. hook OnPlayerConnect(playerid)
  450. {
  451. P:1("Iter_OnPlayerConnect called: %d, %d", playerid, IsPlayerNPC(playerid));
  452. #if _FOREACH_BOTS
  453. Iter_Add(Character, playerid);
  454. if (IsPlayerNPC(playerid))
  455. {
  456. Iter_Add(Bot, playerid);
  457. }
  458. else
  459. #endif
  460. #if _FOREACH_PLAYERS
  461. {
  462. Iter_Add(Player, playerid);
  463. }
  464. #endif
  465. P:2("Iter_OnPlayerConnect end");
  466. return 1;
  467. }
  468. /**----------------------------------------------------------------------**\
  469. <summary>Iter_OnPlayerDisconnect</summary>
  470. <param name="playerid">Player who left.</param>
  471. <returns>
  472. -
  473. </returns>
  474. <remarks>
  475. Removes a player from the loop data. No longer uses "hook" to ENSURE
  476. that this is always last. Previously I think that the order of
  477. evaluation in y_hooks meant that this got called before the user
  478. "OnPlayerDisconnect".
  479. </remarks>
  480. \**----------------------------------------------------------------------**/
  481. hook OnPlayerDisconnect(playerid, reason)
  482. {
  483. SetTimerEx("Iter_OPDCInternal", 0, false, "i", playerid);
  484. return 1;
  485. }
  486. /**----------------------------------------------------------------------**\
  487. <summary>Iter_OPDCInternal</summary>
  488. <param name="playerid">Player who left.</param>
  489. <returns>
  490. -
  491. </returns>
  492. <remarks>
  493. Called AFTER "OnPlayerDisconnect" so that using "Kick" inside a
  494. "foreach" loop doesn't crash the server due to an OOB error.
  495. </remarks>
  496. \**----------------------------------------------------------------------**/
  497. public Iter_OPDCInternal(playerid)
  498. {
  499. if (IsPlayerConnected(playerid))
  500. {
  501. return;
  502. }
  503. #if _FOREACH_BOTS
  504. Iter_Remove(Character, playerid);
  505. if (IsPlayerNPC(playerid))
  506. {
  507. Iter_Remove(Bot, playerid);
  508. }
  509. else
  510. #endif
  511. #if _FOREACH_PLAYERS
  512. {
  513. Iter_Remove(Player, playerid);
  514. }
  515. #endif
  516. }
  517. #endif
  518. /*
  519. db
  520. d88b ,d
  521. d8'`8b 88
  522. d8' `8b ,adPPYba, MM88MMM ,adPPYba, 8b,dPPYba, ,adPPYba,
  523. d8YaaaaY8b a8" "" 88 a8" "8a 88P' "Y8 I8[ ""
  524. d8""""""""8b 8b 88 8b d8 88 `"Y8ba,
  525. d8' `8b "8a, ,aa 88, "8a, ,a8" 88 aa ]8I
  526. d8' `8b `"Ybbd8"' "Y888 `"YbbdP"' 88 `"YbbdP"'
  527. */
  528. #if _FOREACH_ACTORS
  529. remotefunc void:Iter_ActorDo(bool:add, actorid)
  530. {
  531. // Because there may be multiple scripts running, we need to tell all of
  532. // them when an actor is created or destroyed.
  533. if (add)
  534. Iter_Add(Actor, actorid);
  535. else
  536. Iter_Remove(Actor, actorid);
  537. }
  538. stock Iter_CreateActor(modelid, Float:X, Float:Y, Float:Z, Float:Rotation)
  539. {
  540. new
  541. ret = CreateActor(modelid, X, Y, Z, Rotation);
  542. broadcastfunc Iter_ActorDo(true, ret);
  543. #if _FOREACH_LOCALS
  544. Iter_Add(LocalActor, ret);
  545. #endif
  546. return ret;
  547. }
  548. #if defined _ALS_CreateActor
  549. #undef CreateActor
  550. #else
  551. #define _ALS_CreateActor
  552. #endif
  553. #define CreateActor Iter_CreateActor
  554. stock Iter_DestroyActor(actorid)
  555. {
  556. broadcastfunc Iter_ActorDo(false, actorid);
  557. #if _FOREACH_LOCALS
  558. Iter_Remove(LocalActor, actorid);
  559. #endif
  560. return DestroyActor(actorid);
  561. }
  562. #if defined _ALS_DestroyActor
  563. #undef DestroyActor
  564. #else
  565. #define _ALS_DestroyActor
  566. #endif
  567. #define DestroyActor Iter_DestroyActor
  568. #endif
  569. /*
  570. 8b d8 88 88 88
  571. `8b d8' 88 "" 88
  572. `8b d8' 88 88
  573. `8b d8' ,adPPYba, 88,dPPYba, 88 ,adPPYba, 88 ,adPPYba, ,adPPYba,
  574. `8b d8' a8P_____88 88P' "8a 88 a8" "" 88 a8P_____88 I8[ ""
  575. `8b d8' 8PP""""""" 88 88 88 8b 88 8PP""""""" `"Y8ba,
  576. `888' "8b, ,aa 88 88 88 "8a, ,aa 88 "8b, ,aa aa ]8I
  577. `8' `"Ybbd8"' 88 88 88 `"Ybbd8"' 88 `"Ybbd8"' `"YbbdP"'
  578. */
  579. #if _FOREACH_VEHICLES
  580. remotefunc void:Iter_VehicleDo(bool:add, vehicleid)
  581. {
  582. // Because there may be multiple scripts running, we need to tell all of
  583. // them when a vehicle is created or destroyed.
  584. if (add)
  585. Iter_Add(Vehicle, vehicleid);
  586. else
  587. Iter_Remove(Vehicle, vehicleid);
  588. }
  589. stock Iter_CreateVehicle(modelid, Float:x, Float:y, Float:z, Float:angle, color1, color2, respawn_delay, addsiren = 0)
  590. {
  591. #if _FOREACH_ACTORS
  592. new
  593. ret = CreateVehicle(modelid, x, y, z, angle, color1, color2, respawn_delay, addsiren);
  594. #else
  595. new
  596. ret = CreateVehicle(modelid, x, y, z, angle, color1, color2, respawn_delay);
  597. #endif
  598. broadcastfunc Iter_VehicleDo(true, ret);
  599. #if _FOREACH_LOCALS
  600. Iter_Add(LocalVehicle, ret);
  601. #endif
  602. return ret;
  603. }
  604. #if defined _ALS_CreateVehicle
  605. #undef CreateVehicle
  606. #else
  607. #define _ALS_CreateVehicle
  608. #endif
  609. #define CreateVehicle Iter_CreateVehicle
  610. stock Iter_AddStaticVehicle(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:angle, color1, color2)
  611. {
  612. new
  613. ret = AddStaticVehicle(modelid, spawn_x, spawn_y, spawn_z, angle, color1, color2);
  614. broadcastfunc Iter_VehicleDo(true, ret);
  615. #if _FOREACH_LOCALS
  616. Iter_Add(LocalVehicle, ret);
  617. #endif
  618. return ret;
  619. }
  620. #if defined _ALS_AddStaticVehicle
  621. #undef AddStaticVehicle
  622. #else
  623. #define _ALS_AddStaticVehicle
  624. #endif
  625. #define AddStaticVehicle Iter_AddStaticVehicle
  626. stock Iter_AddStaticVehicleEx(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:angle, color1, color2, respawn_delay, addsiren = 0)
  627. {
  628. #if _FOREACH_ACTORS
  629. new
  630. ret = AddStaticVehicleEx(modelid, spawn_x, spawn_y, spawn_z, angle, color1, color2, respawn_delay, addsiren);
  631. #else
  632. new
  633. ret = AddStaticVehicleEx(modelid, spawn_x, spawn_y, spawn_z, angle, color1, color2, respawn_delay);
  634. #endif
  635. broadcastfunc Iter_VehicleDo(true, ret);
  636. #if _FOREACH_LOCALS
  637. Iter_Add(LocalVehicle, ret);
  638. #endif
  639. return ret;
  640. }
  641. #if defined _ALS_AddStaticVehicleEx
  642. #undef AddStaticVehicleEx
  643. #else
  644. #define _ALS_AddStaticVehicleEx
  645. #endif
  646. #define AddStaticVehicleEx Iter_AddStaticVehicleEx
  647. stock Iter_DestroyVehicle(vehicleid)
  648. {
  649. broadcastfunc Iter_VehicleDo(false, vehicleid);
  650. #if _FOREACH_LOCALS
  651. Iter_Remove(LocalVehicle, vehicleid);
  652. #endif
  653. return DestroyVehicle(vehicleid);
  654. }
  655. #if defined _ALS_DestroyVehicle
  656. #undef DestroyVehicle
  657. #else
  658. #define _ALS_DestroyVehicle
  659. #endif
  660. #define DestroyVehicle Iter_DestroyVehicle
  661. #endif