y_groupsecond.inc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. /*----------------------------------------------------------------------------*\
  2. =======================================
  3. y_groups - Player group abstractions!
  4. =======================================
  5. Description:
  6. Admin levels, gangs, teams etc - they're all "groups" of people, this
  7. provides an abstraction for all of these collections.
  8. Legal:
  9. Version: MPL 1.1
  10. The contents of this file are subject to the Mozilla Public License Version
  11. 1.1 (the "License"); you may not use this file except in compliance with
  12. the License. You may obtain a copy of the License at
  13. http://www.mozilla.org/MPL/
  14. Software distributed under the License is distributed on an "AS IS" basis,
  15. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  16. for the specific language governing rights and limitations under the
  17. License.
  18. The Original Code is the YSI group include.
  19. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  20. Portions created by the Initial Developer are Copyright (C) 2011
  21. the Initial Developer. All Rights Reserved.
  22. Contributors:
  23. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  24. Thanks:
  25. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  26. ZeeX - Very productive conversations.
  27. koolk - IsPlayerinAreaEx code.
  28. TheAlpha - Danish translation.
  29. breadfish - German translation.
  30. Fireburn - Dutch translation.
  31. yom - French translation.
  32. 50p - Polish translation.
  33. Zamaroht - Spanish translation.
  34. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  35. for me to strive to better.
  36. Pixels^ - Running XScripters where the idea was born.
  37. Matite - Pestering me to release it and using it.
  38. Very special thanks to:
  39. Thiadmer - PAWN, whose limits continue to amaze me!
  40. Kye/Kalcor - SA:MP.
  41. SA:MP Team past, present and future - SA:MP.
  42. Version:
  43. 2.0
  44. Changelog:
  45. 21/10/12:
  46. Added Group_Get... functions.
  47. 20/10/12:
  48. Pretty much a ground-up API-compatible rewrite. Shorter and reliabler.
  49. 29/11/10:
  50. First version
  51. \*----------------------------------------------------------------------------*/
  52. #undef _inc_y_groupsecond
  53. // This code, having been updated to use the later version of y_hooks,
  54. // unfortunately no longer has one function spread between two files, which was
  55. // a very unique (required) code feature. However this version should be better
  56. // overall (at least slightly).
  57. //#include "..\y_hooks"
  58. // This file contains generic code for setting all the stats to do with a single
  59. // element type. Groups can be defined for any element (classes, objects etc)
  60. // and each one will specialise this file to give different functions.
  61. #if !defined _GROUP_MAKE_NAME
  62. #error Please define _GROUP_MAKE_NAME before including y_groups.
  63. #endif
  64. #if !defined _GROUP_MAKE_LIMIT
  65. #error Please define _GROUP_MAKE_LIMIT before including y_groups.
  66. #endif
  67. #if !defined _GROUP_MAKE_TAG
  68. #define _GROUP_MAKE_TAG _
  69. #endif
  70. // Start of the multi-use file.
  71. static stock
  72. BitArray:_GROUP_GROUP_NAME[_GROUP_MAKE_LIMIT]<_:_MAX_GROUPS_G>,
  73. BitArray:_GROUP_DEFAULTS<_:_MAX_GROUPS_G>,
  74. BitArray:YSI_g_sEmpty<_:_MAX_GROUPS_G>,
  75. _yGI,
  76. _yGU,
  77. _yGA;
  78. // Define the callback chaining for the current
  79. #if YSIM_HAS_MASTER
  80. #if _YSIM_IS_CLIENT
  81. #define _gchain%0(%2) stock _GROUP_MAKE_NAME<%0...>(%2)
  82. // Should never be needed.
  83. #define _GROUP_SET_PLAYER _GROUP_MAKE_NAME<_Error_..._Client_Set>
  84. #else
  85. #if _YSIM_IS_SERVER
  86. #define _gchain%0(%2) _GROUP_MAKE_NAME<%0...>(%2);public _GROUP_MAKE_NAME<%0...>(%2);for(J@=1;J@;GROUP_CHAIN?<%0>(%2))
  87. #define _GROUP_SET_PLAYER _GROUP_MAKE_NAME<..._SetPlayer>
  88. #else
  89. #if _YSIM_IS_STUB
  90. #define _gchain%0(%2) stock _GROUP_MAKE_NAME<%0...>(%2)
  91. // Because of the interaction between the various things that
  92. // the groups and master systems this will NEVER be called in a
  93. // stub script - and if it is we now get a nice compile-time
  94. // error telling us so! It may, however, prove difficult to
  95. // trace!
  96. #define _GROUP_SET_PLAYER _GROUP_MAKE_NAME<_Error_..._Stub_Set>
  97. #else
  98. #define _gchain%0(%2) _GROUP_MAKE_NAME<%0...>(%2);public _GROUP_MAKE_NAME<%0...>(%2)<>GROUP_CHAIN?<%0>(%2);public _GROUP_MAKE_NAME<%0...>(%2)<_YCM:y>for(J@=1;J@;GROUP_CHAIN?<%0>(%2))
  99. #define _GROUP_SET_PLAYER _GROUP_MAKE_NAME<..._SetPlayer>
  100. #endif
  101. #endif
  102. #endif
  103. #else
  104. #define _gchain%0(%2) _GROUP_MAKE_NAME<%0...>(%2);public _GROUP_MAKE_NAME<%0...>(%2);for(J@=1;J@;GROUP_CHAIN?<%0>(%2))
  105. #define _GROUP_SET_PLAYER _GROUP_MAKE_NAME<..._SetPlayer>
  106. #endif
  107. /*----------------------------------------------------------------------------*\
  108. Function:
  109. Group_FU
  110. Params:
  111. playerid - Player to check.
  112. el - Element to show or hide.
  113. previous - The old state of affairs.
  114. current - The new state of affairs.
  115. reference - What to compare changes to.
  116. Return:
  117. -
  118. Notes:
  119. I did have a good reason for calling this "FU", but I forgot it! Anyway,
  120. the state of some groups has changed - either a player's groups or an
  121. elements groups have changed. If the player could previously see the
  122. element but now can't, hide it. If the player previously couldn't see it
  123. but now can, show it. If there is no change do nothing. The old version of
  124. this library would just re-show the element even if they could already see
  125. it, but this was a bad design as it could incur large overheads in other
  126. libraries when they had to do IO to enable or disable something for a
  127. player.
  128. The change can be in either the player's groups or the element's groups,
  129. either way this code will work regardless.
  130. Oh yeah, "FU" means "Full Update".
  131. \*----------------------------------------------------------------------------*/
  132. static stock Group_FU(playerid, el, Bit:previous[], Bit:current[], Bit:reference[])
  133. {
  134. // "_GROUPS_CHECK" is a macro that expands to a massive unrolled "if"
  135. // statement checking up to 512 groups at once. Any more than that and this
  136. // code resorts to a loop instead. I say "at once"; it does 32 AT ONCE
  137. // (as in truly in parallel), starting with the most likely match (the
  138. // default group that every player and every element is usually in), and
  139. // loops over all the groups in 32 group chunks. When I say "loop", this
  140. // could be in the form of a huge "if" statement with every iteration put in
  141. // explicitly.
  142. // nr = NOT REFERENCE
  143. // ar = ALOW REFERENCE
  144. // cur = NEW SETTINGS
  145. // pre = PREVIOUS SETTINGS
  146. /*if (Bit_Get(gNotDat, el))
  147. {
  148. if (Bit_Get(gAndDat, el))
  149. {
  150. _GROUPS_CHECK_IN(ar, cur)
  151. {
  152. _GROUPS_CHECK_NONE(nr, cur)
  153. {
  154. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, true);
  155. return;
  156. }
  157. }
  158. // SHOULD IT BE REMOVED?
  159. {
  160. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, false);
  161. return;
  162. }
  163. }
  164. else
  165. {
  166. _GROUPS_CHECK_ANY(ar, cur)
  167. {
  168. _GROUPS_CHECK_NONE(nr, cur)
  169. {
  170. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, true);
  171. return;
  172. }
  173. }
  174. // SHOULD IT BE REMOVED?
  175. {
  176. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, false);
  177. return;
  178. }
  179. }
  180. }
  181. else
  182. {
  183. if (Bit_Get(gAndDat, el))
  184. {
  185. _GROUPS_CHECK_IN(ar, cur)
  186. {
  187. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, true);
  188. return;
  189. }
  190. // SHOULD IT BE REMOVED?
  191. {
  192. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, false);
  193. return;
  194. }
  195. }
  196. else
  197. {
  198. _GROUPS_CHECK_ANY(ar, cur)
  199. {
  200. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, true);
  201. return;
  202. }
  203. // SHOULD IT BE REMOVED?
  204. {
  205. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, false);
  206. return;
  207. }
  208. }
  209. }*/
  210. /*_GROUPS_CHECK_ALL(nr, ar)
  211. {
  212. _GROUPS_CHECK_IN(ar, cur)
  213. {
  214. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, true);
  215. return;
  216. }
  217. _GROUPS_CHECK_IN(ar, pre)
  218. {
  219. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, false);
  220. return;
  221. }
  222. return;
  223. }
  224. _GROUPS_CHECK_ANY(ar, cur)
  225. {
  226. _GROUPS_CHECK_NONE(nr, cur)
  227. {
  228. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, true);
  229. return;
  230. }
  231. }
  232. _GROUPS_CHECK_IN(ar, pre)
  233. {
  234. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, false);
  235. return;
  236. }*/
  237. _GROUPS_CHECK_ANY(previous, reference)
  238. {
  239. // Could previously see this thing. The thing about this design is that
  240. // it can (best case) take just 2 comparisons to end - and that should
  241. // be the common case!
  242. _GROUPS_CHECK_ANY(current, reference)
  243. {
  244. // Still can.
  245. return;
  246. }
  247. // Now can't.
  248. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, false);
  249. return;
  250. }
  251. // Couldn't see it before.
  252. _GROUPS_CHECK_ANY(current, reference)
  253. {
  254. // They have whatever this thing is. Note that this may be called
  255. // MULTIPLE times for an element, without anything actually changing.
  256. // I.e. this could be set to "true" repeatedly while never being set
  257. // to "false".
  258. _GROUP_SET_PLAYER(_GROUP_MAKE_TAG:el, playerid, true);
  259. // We use "return" here because "_GROUPS_CHECK_ANY" MAY be a loop.
  260. return;
  261. }
  262. }
  263. /*----------------------------------------------------------------------------*\
  264. Function:
  265. _yGI
  266. Params:
  267. &ni - Next init function variable as returned by y_amx.
  268. &na - Next add function variable as returned by y_amx.
  269. &nu - Next update function variable as returned by y_amx.
  270. Return:
  271. -
  272. Notes:
  273. This function is called when the group system first starts up to initialise
  274. the global group and all the various function pointers. The way the
  275. "_gchain" macro works means that the fact that "ni" etc are references is
  276. irrelevant; however, it does make the code LOOK much nicer and like
  277. assigning to the variables does have some wider meaning.
  278. If this is called with "ni = -1", it is special code to temporarilly set or
  279. restore the defaults for use with the "GROUP_ADD" macro.
  280. \*----------------------------------------------------------------------------*/
  281. _gchain _yGI(&ni, &na, &nu)
  282. {
  283. if (ni == -1)
  284. {
  285. static
  286. BitArray:sStack<_MAX_GROUPS_G>;
  287. if (na)
  288. {
  289. //printf("PUSH %d", nu);
  290. // Called to "push" the default settings.
  291. sStack = _GROUP_DEFAULTS;
  292. //printf("ONE %d", nu);
  293. _GROUP_DEFAULTS = YSI_g_cEmptyGroups;
  294. //printf("TWO %d", nu);
  295. Bit_Let(_GROUP_DEFAULTS, nu);
  296. //printf("THREE %d", nu);
  297. for (new i = 0; i != bits<_MAX_GROUPS_G>; ++i)
  298. {
  299. YSI_g_sEmpty[i] = ~_GROUP_DEFAULTS[i];
  300. }
  301. //printf("DONE %d", nu);
  302. }
  303. else
  304. {
  305. //printf("POP");
  306. // Called to "pop" the default settings.
  307. _GROUP_DEFAULTS = sStack;
  308. YSI_g_sEmpty = YSI_g_cEmptyGroups;
  309. }
  310. }
  311. else
  312. {
  313. P:4(#_GROUP_MAKE_NAME<_yGI...> " called: %i, %i, %i", ni, na, nu);
  314. // Enable the default group. If I'm right, this way is actually better than
  315. // using variables as in most cases because "_MAX_GROUPS" is a constant so
  316. // all the other maths will be constant.
  317. Bit_Let(_GROUP_DEFAULTS, _MAX_GROUPS);
  318. // Don't need this loop anymore, it is done for every element individually.
  319. //for (new i = 0; i != _GROUP_MAKE_LIMIT; ++i)
  320. //{
  321. // // Basically, enable everything in the default group.
  322. // Bit_Let(_GROUP_GROUP_NAME[i], _MAX_GROUPS);
  323. //}
  324. // Set up the function chaining.
  325. ni = AMX_GetPublicPointerPrefix(ni, _yGI, _A<_yGI>);
  326. na = AMX_GetPublicPointerPrefix(na, _yGA, _A<_yGA>);
  327. nu = AMX_GetPublicPointerPrefix(nu, _yGU, _A<_yGU>);
  328. }
  329. }
  330. /*----------------------------------------------------------------------------*\
  331. Function:
  332. Group_Exclusive...
  333. Params:
  334. Group:g - Group to add this to.
  335. _GROUP_MAKE_TAG:el - Element to add.
  336. Return:
  337. -
  338. Notes:
  339. Add this element to ONLY this group and remove it from any others it might
  340. already be in. This is basically a simplified version of "GROUP_ADD".
  341. \*----------------------------------------------------------------------------*/
  342. gforeign Group_Exclusive...(Group:g,_GROUP_MAKE_TAG:el);
  343. gglobal Group_Exclusive...(Group:g,_GROUP_MAKE_TAG:el)
  344. {
  345. if (GROUP_MASK <= g <= GROUP_GLOBAL)
  346. {
  347. GROUP_FIX(g);
  348. YSI_gTempGroups = _GROUP_DEFAULTS;
  349. _GROUP_DEFAULTS = YSI_g_cEmptyGroups;
  350. Bit_Let(_GROUP_DEFAULTS, _:g);
  351. for (new i = 0; i != bits<_MAX_GROUPS_G>; ++i)
  352. {
  353. YSI_g_sEmpty[i] = ~_GROUP_DEFAULTS[i];
  354. }
  355. _GROUP_INITIALISE(el);
  356. _GROUP_DEFAULTS = YSI_gTempGroups;
  357. YSI_g_sEmpty = YSI_g_cEmptyGroups;
  358. return 1;
  359. }
  360. return 0;
  361. }
  362. /*----------------------------------------------------------------------------*\
  363. Function:
  364. _yGA
  365. Params:
  366. &group - The group that was just created.
  367. Return:
  368. -
  369. Notes:
  370. The given group was just created, loop over all elements and make sure they
  371. are NOT in this group - only the global group has a "default default" of
  372. true. We don't need to update any players with this as no-one will ever be
  373. in a brand new group.
  374. \*----------------------------------------------------------------------------*/
  375. _gchain _yGA(&group)
  376. {
  377. P:4(#_GROUP_MAKE_NAME<_yGA...> " called: %i", _:group);
  378. // Adding a new group is now a lot harder than it was before, but on the
  379. // other hand, adding and using elements is vastly simpler so that's OK.
  380. new
  381. s = Bit_Slot(group),
  382. Bit:m = ~Bit_Mask(group);
  383. // Set the default "contains" for this group to false.
  384. _GROUP_DEFAULTS[s] &= m;
  385. // Disable every element in this group.
  386. for (new i = 0; i != _GROUP_MAKE_LIMIT; ++i)
  387. {
  388. _GROUP_GROUP_NAME[i][s] &= m;
  389. }
  390. }
  391. /*----------------------------------------------------------------------------*\
  392. Function:
  393. _yGU
  394. Params:
  395. &pid - The player who joined or left groups.
  396. Bit:p[] - Their previous groups.
  397. Bit:c[] - Their new groups.
  398. Return:
  399. -
  400. Notes:
  401. The player "pid" just joined or left a group (or groups - can do multiple).
  402. Update their visibility accordingly. This function is ONLY called if there
  403. is a CHANGE - earlier functions confirm that they weren't already in (or
  404. not) this group(s) before the call.
  405. \*----------------------------------------------------------------------------*/
  406. _gchain _yGU(&pid, Bit:p[], Bit:c[])
  407. {
  408. P:4(#_GROUP_MAKE_NAME<_yGU...> " called: %i, %s, %s", pid, Bit_Display(p, bits<_MAX_GROUPS_G>), Bit_Display(c, bits<_MAX_GROUPS_G>));
  409. // This code loops over every "thing" controlled by this script. For every
  410. // one it checks to see if the player can or can't see something that they
  411. // previously could or couldn't see. If their ability to see it has
  412. // changed then the "_GROUP_SET_PLAYER" function in the controlling library
  413. // is called to do the actual internal function of updating their state.
  414. for (new el = 0; el != _GROUP_MAKE_LIMIT; ++el)
  415. {
  416. Group_FU(pid, el, p, c, _GROUP_GROUP_NAME[el]);
  417. }
  418. }
  419. /*----------------------------------------------------------------------------*\
  420. Function:
  421. _GROUP_INITIALISE
  422. Params:
  423. x - The element that was added (maybe).
  424. s - Was the element added or removed?
  425. Return:
  426. -
  427. Notes:
  428. The name is a macro, so this function isn't actually called this. This is
  429. called when a new element is created, and as such it is NOT chained to other
  430. parts of the groups system because each part handles one type of element.
  431. Loop through all players and set up the element for them if they are in a
  432. group that this is also in by default.
  433. If x is "_GROUP_MAKE_LIMIT" then this is the test used in OnPlayerConnect in
  434. various libraries to see if the groups system exists, and if not locally
  435. initialise the player instead of leaving it up to this system.
  436. \*----------------------------------------------------------------------------*/
  437. #if !defined _YSI_GROUPS_FIRST_HALF
  438. forward bool:_GROUP_INITIALISE(_GROUP_MAKE_TAG:x = _GROUP_MAKE_TAG:_GROUP_MAKE_LIMIT);
  439. #endif
  440. stock bool:_GROUP_INITIALISE(_GROUP_MAKE_TAG:x = _GROUP_MAKE_TAG:_GROUP_MAKE_LIMIT) <YSI_has_groups:y>
  441. {
  442. P:4(#_GROUP_INITIALISE " called: %i", x);
  443. // A new item has been added to the system - update all players according to
  444. // the default settings for a group.
  445. if (x != _GROUP_MAKE_TAG:_GROUP_MAKE_LIMIT)
  446. {
  447. //static
  448. // BitArray:sEmpty<_MAX_GROUPS_G>;
  449. //printf("%d %s %s", _:x, Bit_Display(_GROUP_DEFAULTS), Bit_Display(YSI_g_sEmpty));
  450. _GROUP_GROUP_NAME[_:x] = _GROUP_DEFAULTS;
  451. foreach (new playerid : Player)
  452. {
  453. // Uses "YSI_g_sEmpty" instead of a truly blank variable so that we
  454. // can ensure that NO other groups have this element when we use the
  455. // "GROUP_ADD" macro.
  456. Group_FU(playerid, _:x, YSI_g_sEmpty, _GROUP_DEFAULTS, YSI_gGroupPlayers[playerid]);
  457. }
  458. }
  459. return true;
  460. }
  461. /*----------------------------------------------------------------------------*\
  462. Function:
  463. Group_Set...Default
  464. Params:
  465. Group:g - Group to set for.
  466. bool:s - Set or unset?
  467. Return:
  468. -
  469. Notes:
  470. If "s" is true, then all elements are added to this group (i.e. the default
  471. is set to true and all previous settings are wiped out). If it is false
  472. then all elements are removed and a full update is done.
  473. \*----------------------------------------------------------------------------*/
  474. gforeign Group_Set...Default(Group:g,bool:s);
  475. gglobal Group_Set...Default(Group:g,bool:s)
  476. {
  477. P:2(#_GROUP_MAKE_NAME<Group_Set...Default> " called: %i, %i", _:g, s);
  478. if (GROUP_MASK <= g <= GROUP_GLOBAL)
  479. {
  480. // There is now NO validity check for reasons of distruibution.
  481. GROUP_FIX(g);
  482. new
  483. slot = Bit_Slot(g),
  484. Bit:mask = Bit_Mask(g),
  485. Iterator:GP<MAX_PLAYERS>;
  486. foreach (new playerid : Player)
  487. {
  488. // Do this check here so it is only done once per player. This is a
  489. // good argument for moving iterators to be duplicated in every
  490. // script; however, the default "Group()" iterator implementation is
  491. // a function, not a standard iterator - actually it now isn't...
  492. if (YSI_gGroupPlayers[playerid][slot] & mask)
  493. {
  494. // Make a fast local iterator of all the players.
  495. Iter_Add(GP, playerid);
  496. }
  497. }
  498. static
  499. BitArray:sNext<_MAX_GROUPS_G>;
  500. if (s)
  501. {
  502. Bit_Let(_GROUP_DEFAULTS, _:g);
  503. for (new el = 0; el != _GROUP_MAKE_LIMIT; ++el)
  504. {
  505. sNext = _GROUP_GROUP_NAME[el];
  506. if (sNext[slot] & mask)
  507. {
  508. continue;
  509. }
  510. // Is this element NOT in the current group?
  511. Bit_Let(sNext, _:g);
  512. foreach (new playerid : GP)
  513. {
  514. Group_FU(playerid, el, _GROUP_GROUP_NAME[el], sNext, YSI_gGroupPlayers[playerid]);
  515. }
  516. _GROUP_GROUP_NAME[el] = sNext;
  517. }
  518. }
  519. else
  520. {
  521. Bit_Vet(_GROUP_DEFAULTS, _:g);
  522. for (new el = 0; el != _GROUP_MAKE_LIMIT; ++el)
  523. {
  524. sNext = _GROUP_GROUP_NAME[el];
  525. if (!(sNext[slot] & mask))
  526. {
  527. continue;
  528. }
  529. // Is this element in the current group?
  530. Bit_Vet(sNext, _:g);
  531. foreach (new playerid : GP)
  532. {
  533. Group_FU(playerid, el, _GROUP_GROUP_NAME[el], sNext, YSI_gGroupPlayers[playerid]);
  534. }
  535. _GROUP_GROUP_NAME[el] = sNext;
  536. }
  537. }
  538. return 1;
  539. }
  540. return 0;
  541. }
  542. /*----------------------------------------------------------------------------*\
  543. Function:
  544. Group_SetGlobal...Default
  545. Params:
  546. bool:s - Set or unset?
  547. Return:
  548. -
  549. Notes:
  550. If "s" is true, then all elements are added to the global group (i.e. the
  551. default is set to true and all previous settings are wiped out). If it is
  552. false then all elements are removed and a full update is done.
  553. \*----------------------------------------------------------------------------*/
  554. gforeign Group_SetGlobal...Default(bool:s);
  555. gglobal Group_SetGlobal...Default(bool:s)
  556. {
  557. P:2(#_GROUP_MAKE_NAME<Group_SetGlobal...Default> " called: %i", s);
  558. return _GROUP_MAKE_NAME<Group_Set...Default>(GROUP_GLOBAL, s);
  559. }
  560. /*----------------------------------------------------------------------------*\
  561. Function:
  562. Group_Set...New
  563. Params:
  564. Group:g - Group to set for.
  565. bool:s - Set or unset?
  566. Return:
  567. -
  568. Notes:
  569. Similar to "Group_Set...Default", but doesn't reset all existing elements,
  570. just sets the permissions for any future items.
  571. \*----------------------------------------------------------------------------*/
  572. gforeign Group_Set...New(Group:g,bool:s);
  573. gglobal Group_Set...New(Group:g,bool:s)
  574. {
  575. P:2(#_GROUP_MAKE_NAME<Group_Set...New> " called: %i, %i", _:g, s);
  576. if (GROUP_MASK <= g <= GROUP_GLOBAL)
  577. {
  578. // There is now NO validity check for reasons of distruibution.
  579. Bit_Set(_GROUP_DEFAULTS, _:GROUP_TEMP_FIX(g), s);
  580. return 1;
  581. }
  582. return 0;
  583. }
  584. /*----------------------------------------------------------------------------*\
  585. Function:
  586. Group_SetGlobal...New
  587. Params:
  588. bool:s - Set or unset?
  589. Return:
  590. -
  591. Notes:
  592. All elements created FROM THIS POINT ON will have this default setting.
  593. \*----------------------------------------------------------------------------*/
  594. gforeign Group_SetGlobal...New(bool:s);
  595. gglobal Group_SetGlobal...New(bool:s)
  596. {
  597. P:2(#_GROUP_MAKE_NAME<Group_SetGlobal...New> " called: %i", s);
  598. return _GROUP_MAKE_NAME<Group_Set...New>(GROUP_GLOBAL, s);
  599. }
  600. /*----------------------------------------------------------------------------*\
  601. Function:
  602. Group_Set...
  603. Params:
  604. Group:g - Group to set for.
  605. el - Element to set.
  606. bool:s - Set or unset?
  607. Return:
  608. -
  609. Notes:
  610. If "s" is true, then one element is added to the current group. False it is
  611. removed.
  612. \*----------------------------------------------------------------------------*/
  613. gforeign Group_Set...(Group:g,_GROUP_MAKE_TAG:el,bool:s);
  614. gglobal Group_Set...(Group:g,_GROUP_MAKE_TAG:el,bool:s)
  615. {
  616. P:2(#_GROUP_MAKE_NAME<Group_Set...> " called: %i, %i, %i", _:g, _:el, s);
  617. // Set wether a group can use this item.
  618. if (0 <= _:el < _GROUP_MAKE_LIMIT && GROUP_MASK <= g <= GROUP_GLOBAL)
  619. {
  620. // There is now NO validity check for reasons of distruibution.
  621. GROUP_FIX(g);
  622. new
  623. slot = Bit_Slot(g),
  624. Bit:mask = Bit_Mask(g);
  625. //static
  626. // BitArray:sNext<_MAX_GROUPS_G>;
  627. if (s)
  628. {
  629. YSI_gTempGroups = _GROUP_GROUP_NAME[_:el];
  630. if (YSI_gTempGroups[slot] & mask)
  631. {
  632. // No point adding an element to a group that it is already in.
  633. return 1;
  634. }
  635. // Is this element NOT in the current group?
  636. Bit_Let(YSI_gTempGroups, _:g);
  637. }
  638. else
  639. {
  640. YSI_gTempGroups = _GROUP_GROUP_NAME[_:el];
  641. if (!(YSI_gTempGroups[slot] & mask))
  642. {
  643. return 1;
  644. }
  645. // Is this element in the current group?
  646. Bit_Vet(YSI_gTempGroups, _:g);
  647. }
  648. foreach (new playerid : Player)
  649. {
  650. if (YSI_gGroupPlayers[playerid][slot] & mask)
  651. {
  652. // The player is in the group in question, so they need a full
  653. // update.
  654. Group_FU(playerid, _:el, _GROUP_GROUP_NAME[_:el], YSI_gTempGroups, YSI_gGroupPlayers[playerid]);
  655. }
  656. }
  657. _GROUP_GROUP_NAME[_:el] = YSI_gTempGroups;
  658. return 1;
  659. }
  660. return 0;
  661. }
  662. /*----------------------------------------------------------------------------*\
  663. Function:
  664. Group_SetGlobal...
  665. Params:
  666. el - Element to set.
  667. bool:s - Set or unset?
  668. Return:
  669. -
  670. Notes:
  671. If "s" is true, then one element is added to the global group. False it is
  672. removed.
  673. \*----------------------------------------------------------------------------*/
  674. gforeign Group_SetGlobal...(_GROUP_MAKE_TAG:el,bool:s);
  675. gglobal Group_SetGlobal...(_GROUP_MAKE_TAG:el,bool:s)
  676. {
  677. P:2(#_GROUP_MAKE_NAME<Group_SetGlobal...> " called: %i, %i", _:el, s);
  678. return _GROUP_MAKE_NAME<Group_Set...>(GROUP_GLOBAL, el, s);
  679. }
  680. /*----------------------------------------------------------------------------*\
  681. Function:
  682. Group_Get...
  683. Params:
  684. Group:g - Group to get from.
  685. el - Element to get.
  686. Return:
  687. bool: Does the group have the element?
  688. Notes:
  689. -
  690. \*----------------------------------------------------------------------------*/
  691. gforeign bool:Group_Get...(Group:g,_GROUP_MAKE_TAG:el);
  692. gglobal bool:Group_Get...(Group:g,_GROUP_MAKE_TAG:el)
  693. {
  694. P:2(#_GROUP_MAKE_NAME<Group_Get...> " called: %i, %i", _:g, _:el);
  695. return (0 <= _:el < _GROUP_MAKE_LIMIT && GROUP_MASK <= g <= GROUP_GLOBAL && Bit_Get(_GROUP_GROUP_NAME[_:el], _:GROUP_TEMP_FIX(g)));
  696. }
  697. /*----------------------------------------------------------------------------*\
  698. Function:
  699. Group_GetGlobal...
  700. Params:
  701. el - Element to get.
  702. Return:
  703. bool: Does the global group have the element?
  704. Notes:
  705. -
  706. \*----------------------------------------------------------------------------*/
  707. gforeign Group_GetGlobal...(_GROUP_MAKE_TAG:el);
  708. gglobal Group_GetGlobal...(_GROUP_MAKE_TAG:el)
  709. {
  710. P:2(#_GROUP_MAKE_NAME<Group_GetGlobal...> " called: %i", _:el);
  711. return _GROUP_MAKE_NAME<Group_Get...>(GROUP_GLOBAL, el);
  712. }
  713. #undef _GROUP_MAKE_TAG
  714. #undef _gchain
  715. #undef _GROUP_SET_PLAYER