y_grouponce.inc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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. 1.0
  44. Changelog:
  45. 29/11/10:
  46. First version
  47. \*----------------------------------------------------------------------------*/
  48. #include <a_samp>
  49. //#include "..\y_scriptinit"
  50. #define YSIM_U_DISABLE
  51. #include "..\y_master"
  52. #include "..\y_playerarray"
  53. #include "..\y_stringhash"
  54. #include "..\y_debug"
  55. //#include "..\y_hooks"
  56. #include "..\y_amx"
  57. #include "..\y_iterate"
  58. #include "..\y_hooks"
  59. //#define _YSI_HAS_GROUP_SYSTEM
  60. //#define _GROUP_MAKE_NAME<%0...%1> %0_%1
  61. // Dummy value
  62. //#define _GROUP_MAKE_LIMIT 0
  63. // Dummy values.
  64. #undef _GROUP_MAKE_NAME
  65. #undef _GROUP_MAKE_LIMIT
  66. #define _GROUP_MAKE_NAME<%0...%1> %0_%1
  67. #define _GROUP_MAKE_LIMIT 0
  68. // Example:
  69. // #define _GROUP_MAKE_NAME<%0...%1> %0Checkpoint%1
  70. /*#if !defined _GROUP_MAKE_NAME
  71. #error Please define _GROUP_MAKE_NAME before including y_groupsone.
  72. #endif
  73. #if !defined _GROUP_MAKE_LIMIT
  74. #error Please define _GROUP_MAKE_LIMIT before including y_groupsone.
  75. #endif*/
  76. // Define local variable names. This will go in the single call file.
  77. //#define _GROUP_LOCAL_NAME _GROUP_MAKE_NAME<i...>
  78. #define _GROUP_GROUP_NAME _GROUP_MAKE_NAME<YSI_gs_Group...Data>
  79. #define _GROUP_GLOBAL_NAME _GROUP_MAKE_NAME<YSI_gs_GroupGlobal...>
  80. #define _GROUP_SET_PLAYER _GROUP_MAKE_NAME<..._SetPlayer>
  81. /*#define _GROUP_UPDATE _GROUP_MAKE_NAME<Group_UpdatePlayer...>
  82. #define _GROUP_UPDATE_ALL _GROUP_MAKE_NAME<Group_UpdateAll...>
  83. #define _GROUP_GROUP_FUNC _GROUP_MAKE_NAME<Group_Set...>
  84. #define _GROUP_GLOBAL_FUNC _GROUP_MAKE_NAME<Group_SetGlobal...>
  85. #define _GROUP_GLOBAL_DEF _GROUP_MAKE_NAME<Group_SetGlobal...Default>
  86. #define _GROUP_GROUP_DEF _GROUP_MAKE_NAME<Group_Set...Default>
  87. //#define _GROUP_ON_PLAYER_CONNECT _GROUP_MAKE_NAME<@yH_PlayerConnect_...@yG>
  88. #define _GROUP_ON_PLAYER_CONNECT _GROUP_MAKE_NAME<@yH_PlayerConnect...@yG>
  89. #define _GROUP_DEFAULTS _GROUP_MAKE_NAME<Group_...Defaults>
  90. #define _GROUP_INIT _GROUP_MAKE_NAME<Group_...Init>*/
  91. #define _GROUP_CREATE _GROUP_MAKE_NAME<@yG_Init...>
  92. #define _GROUP_UPDATE_PLAYER _GROUP_MAKE_NAME<@yG_Upd...>
  93. //#define _GROUP_ON_PLAYER_CONNECT _GROUP_MAKE_NAME<@yG_..._PlayerConnect>
  94. //#define _GROUP_ON_PLAYER_CONNECT RH:_GROUP_MAKE_NAME<...@yG_OnPlayerConnect>
  95. /*#define _GROUP_OPC_OTHER_CALLED _GROUP_MAKE_NAME<_@yGPlayerConnect_...>
  96. #define _GROUP_OPC_IS_CALLED _GROUP_MAKE_NAME<_yG@PlayerConnect_...>
  97. #define _GROUP_OPC_PUBLIC _GROUP_MAKE_NAME<@yG_PlayerConnect_...>*/
  98. //#define group_hook%0On%1(%2) _GROUP_MAKE_NAME<master_hook On%1...>(%2)
  99. #define ghook group_hook
  100. #define gforeign%1(%2); _GROUP_MAKE_NAME<foreign%1>(%2);
  101. #define gglobal%1(%2) _GROUP_MAKE_NAME<global%1>(%2)
  102. //#define master_hook%0On%2(%3) hook On%2(%3)<>return 1;rehook On%2(%3)<_YCM:y>
  103. #if !defined MAX_GROUP_NAME
  104. #define MAX_GROUP_NAME (24)
  105. #endif
  106. #if !defined MAX_GROUPS
  107. // 1 less than a nice number (with good reason).
  108. #define MAX_GROUPS (Group:127)
  109. #endif
  110. enum e_GROUP_FLAGS (<<= 1)
  111. {
  112. e_GROUP_FLAGS_GANG = 1,
  113. // I can't remember why I had this!
  114. //e_GROUP_FLAGS_CHAT,
  115. e_GROUP_FLAGS_ACTIVE,
  116. e_GROUP_FLAGS_COLOR = 0xFFFFFF00
  117. }
  118. enum E_GROUP_DATA
  119. {
  120. E_GROUP_DATA_NAME[MAX_GROUP_NAME char],
  121. //E_GROUP_DATA_COUNT,
  122. E_GROUP_DATA_HASH,
  123. e_GROUP_FLAGS:E_GROUP_DATA_FLAGS,
  124. }
  125. stock
  126. PlayerArray:YSI_gGroupPlayers[MAX_GROUPS]<MAX_PLAYERS>,
  127. YSI_gGroupData[MAX_GROUPS][E_GROUP_DATA];
  128. #define GROUPS_MAX_LIBRARIES 4
  129. static stock
  130. YSI_g_sNextUpdateFunc,//[32],
  131. YSI_g_sNextInitFunc,//[32],
  132. YSI_g_sGroupCount/*,
  133. bool:YSI_g_sHasOPC = false*/;
  134. #define _Group_HasPlayer(%0,%1) \
  135. PA_Get(YSI_gGroupPlayers[(%0)],(%1))
  136. //Bit_Get(YSI_gGroupPlayers[(%0)], (%1), MAX_PLAYERS)
  137. #define _Group_GetColor(%0) \
  138. (_:(YSI_gGroupData[(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_COLOR | e_GROUP_FLAGS:0xAA))
  139. #define _Group_SetColor(%0,%1) \
  140. (YSI_gGroupData[(%0)][E_GROUP_DATA_FLAGS] |= e_GROUP_FLAGS:(%1) & e_GROUP_FLAGS_COLOR)
  141. #define _Group_GetGang(%0) \
  142. (bool:(YSI_gGroupData[(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_GANG))
  143. #define _Group_LetGang(%0) \
  144. (YSI_gGroupData[(%0)][E_GROUP_DATA_FLAGS] |= e_GROUP_FLAGS_GANG)
  145. #define _Group_VetGang(%0) \
  146. (YSI_gGroupData[(%0)][E_GROUP_DATA_FLAGS] &= ~e_GROUP_FLAGS_GANG)
  147. #define _Group_IsActive(%0) \
  148. (YSI_gGroupData[(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_ACTIVE)
  149. //#define _Group_IsValid(%0)
  150. // (0 <= (%0) < MAX_GROUPS && Group_IsActive(%0))
  151. #define _Group_IsValid(%0) \
  152. (Group:0 <= (%0) < MAX_GROUPS && _Group_IsActive(%0))
  153. #define Group_IsActive(%0) \
  154. (YSI_gGroupData[GROUP_FIX(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_ACTIVE)
  155. /*#define Group_IsValid(%0) \
  156. (GROUP_MASK <= (%0) < (GROUP_MASK + MAX_GROUPS) <= && Group_IsActive(%0))*/
  157. //#define Group_GetColor(%0)
  158. // (YSI_gGroupData[(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_COLOR | 0xAA);
  159. // (0 <= GROUP_FIX(%0) < MAX_GROUPS && Group_IsActive(%0))
  160. hook OnScriptInit()
  161. {
  162. state YSI_has_groups:y;
  163. //YSI_g_sHasOPC = funcidx(#_GROUP_OPC_PUBLIC) != -1;
  164. //P:2(#_GROUP_OPC_PUBLIC " does%s exist", YSI_g_sHasOPC ? ("") : (" not"));
  165. //P:5("Group_OnScriptInit: OPC = %d", YSI_g_sHasOPC);
  166. new
  167. a = AMX_GetPublicPointer(0, YSI_g_sNextUpdateFunc, "@yG_Upd"),
  168. idx = AMX_GetPublicPointer(0, YSI_g_sNextInitFunc, "@yG_Init");
  169. P:5("Group_OnScriptInit: %d, %d", a, idx);
  170. if (idx)
  171. {
  172. //CallLocalFunction(YSI_g_sNextInitFunc, "ii", -1, (a << 16) | idx);
  173. a = (a << 16) | idx;
  174. #emit PUSH.S a
  175. #emit PUSH.C 0xFFFFFFFF
  176. #emit PUSH.C 8
  177. #emit LCTRL 6
  178. #emit ADD.C 28
  179. #emit PUSH.pri
  180. #emit LOAD.pri YSI_g_sNextInitFunc
  181. #emit SCTRL 6
  182. }
  183. }
  184. hook OnPlayerDisconnect(playerid, reason)
  185. {
  186. P:2("hook OnPlayerDisconnect called: %d, %d", playerid, reason);
  187. new
  188. s = Bit_Slot(playerid) + 1,
  189. Bit:m = ~Bit_Mask(playerid);
  190. for (new Group:i; i != MAX_GROUPS; ++i)
  191. {
  192. // Pre-calculate the slot and mask. Remove the player from every group
  193. // they were in.
  194. YSI_gGroupPlayers[i][s] &= m;
  195. }
  196. }
  197. /*hook OnPlayerConnect(playerid)
  198. {
  199. P:2("Group_OnPlayerConnect called");
  200. if (YSI_g_sHasOPC) CallLocalFunction(#_GROUP_OPC_PUBLIC, "i", playerid);
  201. }
  202. forward _GROUP_OPC_PUBLIC(playerid);*/
  203. foreign Group_SetPlayer(Group:g,p,bool:s);
  204. global Group_SetPlayer(Group:g,p,bool:s)
  205. {
  206. P:2("Group_SetPlayer called: %i, %i, %i", _:g, p, s);
  207. //g &= ~GROUP_MASK;
  208. GROUP_FIX(g);
  209. if (_Group_IsValid(g) && 0 <= p < MAX_PLAYERS)
  210. {
  211. PA_Set(YSI_gGroupPlayers[g], p, s);//, bits<MAX_PLAYERS>);
  212. P:4("Group_SetPlayer: %d %d", _:g, _:YSI_gGroupPlayers[g][1]);
  213. /*if (YSI_g_sNextUpdateFunc[0])
  214. {
  215. CallLocalFunction(YSI_g_sNextUpdateFunc, "iii", p, _:g, s);
  216. }*/
  217. if (YSI_g_sNextUpdateFunc)
  218. {
  219. #emit PUSH.S s
  220. #emit PUSH.S g
  221. #emit PUSH.S p
  222. #emit PUSH.C 12
  223. #emit LCTRL 6
  224. #emit ADD.C 28
  225. #emit PUSH.pri
  226. #emit LOAD.pri YSI_g_sNextUpdateFunc
  227. #emit SCTRL 6
  228. }
  229. }
  230. return 1;
  231. }
  232. foreign Group:Group_SetBalancedInternal(p,Group:gs[],s,c);
  233. global Group:Group_SetBalancedInternal(p,Group:gs[],s,c)
  234. {
  235. // Find which of the listed groups has the least players in.
  236. #pragma unused s
  237. new
  238. count = cellmax,
  239. Group:id = Group:-1,
  240. slot = Bit_Slot(p) + 1,
  241. Bit:mask = Bit_Mask(p),
  242. Bit:inv = ~mask;
  243. for (new i = 0; i != c; ++i)
  244. {
  245. // Find the group with the least players.
  246. new
  247. Group:gi = GROUP_TEMP_FIX(gs[i]);
  248. if (_Group_IsValid(gi))
  249. {
  250. new
  251. cc = PA_GetCount(YSI_gGroupPlayers[gi]);
  252. if (YSI_gGroupPlayers[gi][slot] & mask)
  253. {
  254. // The player is already in this group - prefer it to others.
  255. --cc;
  256. if (cc <= count)
  257. {
  258. count = cc;
  259. id = gi;
  260. }
  261. // Remove the player from this group. Doing this here avoids a
  262. // double loop.
  263. YSI_gGroupPlayers[gi][slot] &= inv;
  264. }
  265. else
  266. {
  267. // Needs to be better than their current group to move.
  268. if (cc < count)
  269. {
  270. count = cc;
  271. id = gi;
  272. }
  273. }
  274. }
  275. }
  276. if (id != Group:-1)
  277. {
  278. // Quickly update all the player location stats.
  279. YSI_gGroupPlayers[id][slot] |= mask;
  280. // Do all the updates at once insted of using Group_SetPlayer which can
  281. // be quite slow for large numbers of updates. I should really encode
  282. // this in a more generic way so that other people can use this deferal.
  283. if (YSI_g_sNextUpdateFunc)
  284. {
  285. // Using "PUSH.C 0" forces a full update.
  286. #emit PUSH.C 0
  287. #emit PUSH.C 0
  288. #emit PUSH.S p
  289. #emit PUSH.C 12
  290. #emit LCTRL 6
  291. #emit ADD.C 28
  292. #emit PUSH.pri
  293. #emit LOAD.pri YSI_g_sNextUpdateFunc
  294. #emit SCTRL 6
  295. }
  296. return Group:id;
  297. //Group_SetPlayer(
  298. }
  299. return GROUP_GLOBAL;
  300. }
  301. stock Group:Group_SetBalanced(playerid, {Group, _}:...)
  302. {
  303. new
  304. Group:possible[MAX_GROUPS],
  305. count = numargs();
  306. switch (count)
  307. {
  308. case 1, 2:
  309. {
  310. P:W("Group_AddBalanced requires at least 2 groups or an array.");
  311. }
  312. case 3:
  313. {
  314. new
  315. third = getarg(2);
  316. if (third & _:GROUP_MASK)
  317. {
  318. // Two groups.
  319. possible[0] = Group:getarg(1);
  320. possible[1] = Group:third;
  321. return Group_SetBalancedInternal(playerid, possible, MAX_GROUPS, 2);
  322. }
  323. else
  324. {
  325. // Array of groups.
  326. for (new i = 0; i != third; ++i)
  327. {
  328. possible[i] = getarg(1, i);
  329. }
  330. return Group_SetBalancedInternal(playerid, possible, MAX_GROUPS, third);
  331. }
  332. }
  333. default:
  334. {
  335. for (new i = 1; i != count; ++i)
  336. {
  337. possible[i - 1] = getarg(i);
  338. }
  339. return Group_SetBalancedInternal(playerid, possible, MAX_GROUPS, count - 1);
  340. }
  341. }
  342. }
  343. foreign bool:Group_GetPlayer(Group:g,p);
  344. global bool:Group_GetPlayer(Group:g,p)
  345. {
  346. P:2("bool:Group_GetPlayer called: %i, %i", _:g, p);
  347. GROUP_FIX(g);
  348. if (_Group_IsValid(g) && 0 <= p < MAX_PLAYERS)
  349. {
  350. return PA_Get(YSI_gGroupPlayers[g], p);
  351. //Bit_Set(YSI_gGroupPlayers[g], p, s, bits<MAX_PLAYERS>);
  352. }
  353. return false;
  354. }
  355. foreign Group_SetName(Group:g,string:n[]);
  356. global Group_SetName(Group:g,string:n[])
  357. {
  358. P:2("Group_SetName called: %i, \"%s\"", _:g, n);
  359. GROUP_FIX(g);
  360. if (_Group_IsValid(g))
  361. {
  362. strpack(YSI_gGroupData[g][E_GROUP_DATA_NAME], n, MAX_GROUP_NAME char);
  363. YSI_gGroupData[g][E_GROUP_DATA_HASH] = YHash(n);
  364. }
  365. return 1;
  366. }
  367. foreign string:Group_GetName(Group:g);
  368. global string:Group_GetName(Group:g)
  369. {
  370. P:2("Group_GetName called: %i", _:g);
  371. new
  372. ret[YSI_MAX_STRING];
  373. GROUP_FIX(g);
  374. if (_Group_IsValid(g))
  375. {
  376. //return Bit_Get(YSI_gGroupPlayers[g], p);
  377. //Bit_Set(YSI_gGroupPlayers[g], p, s, bits<MAX_PLAYERS>);
  378. strunpack(ret, YSI_gGroupData[g][E_GROUP_DATA_NAME], YSI_MAX_STRING);
  379. }
  380. return ret;
  381. }
  382. foreign Group:Group_GetID(string:name[]);
  383. global Group:Group_GetID(string:name[])
  384. {
  385. P:2("Group_GetID called: %s", name);
  386. new
  387. Group:i,
  388. hash = YHash(name);
  389. while (i != MAX_GROUPS)
  390. {
  391. if (_Group_IsActive(i) && YSI_gGroupData[i][E_GROUP_DATA_HASH] == hash)
  392. {
  393. break;
  394. }
  395. ++i;
  396. }
  397. if (i == MAX_GROUPS) return GROUP_GLOBAL;
  398. return i | GROUP_MASK;
  399. }
  400. foreign Group_SetGang(Group:g,bool:n);
  401. global Group_SetGang(Group:g,bool:n)
  402. {
  403. P:2("Group_SetGang called: %i, %i", _:g, n);
  404. GROUP_FIX(g);
  405. if (_Group_IsValid(g))
  406. {
  407. if (n)
  408. {
  409. _Group_LetGang(g);
  410. }
  411. else
  412. {
  413. _Group_VetGang(g);
  414. }
  415. }
  416. return 1;
  417. }
  418. foreign bool:Group_GetGang(Group:g);
  419. global bool:Group_GetGang(Group:g)
  420. {
  421. P:2("bool:Group_GetGang called: %i", _:g);
  422. GROUP_FIX(g);
  423. if (_Group_IsValid(g))
  424. {
  425. return _Group_GetGang(g);
  426. }
  427. return false;
  428. }
  429. foreign Group_SetColour(Group:g,c);
  430. global Group_SetColour(Group:g,c)
  431. {
  432. P:2("Group_SetColour called: %i, %i", _:g, c);
  433. GROUP_FIX(g);
  434. if (_Group_IsValid(g))
  435. {
  436. _Group_SetColor(g, c);
  437. }
  438. return 1;
  439. }
  440. foreign Group_GetColour(Group:g);
  441. global Group_GetColour(Group:g)
  442. {
  443. P:2("Group_GetColour called: %i", _:g);
  444. GROUP_FIX(g);
  445. if (_Group_IsValid(g))
  446. {
  447. return _Group_GetColor(g);
  448. //Bit_Set(YSI_gGroupPlayers[g], p, s, bits<MAX_PLAYERS>);
  449. }
  450. return 0;
  451. }
  452. #define Group_SetColor Group_SetColour
  453. #define Group_GetColor Group_GetColour
  454. foreign Group:Group_Create(string:name[]);
  455. global Group:Group_Create(string:name[])
  456. {
  457. P:2("Group:Group_Create called: \"%s\"", name);
  458. P:2("Group_Create called in %d", _@);
  459. new
  460. Group:i;
  461. while (i != MAX_GROUPS && _Group_IsActive(i))
  462. {
  463. ++i;
  464. }
  465. if (i == MAX_GROUPS) return GROUP_GLOBAL;
  466. strpack(YSI_gGroupData[i][E_GROUP_DATA_NAME], name, MAX_GROUP_NAME char);
  467. ++YSI_g_sGroupCount;
  468. PA_Init(YSI_gGroupPlayers[i]);
  469. YSI_gGroupData[i][E_GROUP_DATA_FLAGS] = e_GROUP_FLAGS_ACTIVE;
  470. YSI_gGroupData[i][E_GROUP_DATA_HASH] = YHash(name);
  471. // Now initialise all the little bits. __CallRemoteFunction to get ALL
  472. // scripts which may control part of the group system.
  473. //CallRemoteFunction(#_GROUP_CREATE, "ii", _:i, -1);
  474. /*if (YSI_g_sNextInitFunc[0])
  475. {
  476. CallLocalFunction(YSI_g_sNextInitFunc, "ii", _:i, -1);
  477. }*/
  478. if (YSI_g_sNextInitFunc)
  479. {
  480. #emit PUSH.C 0xFFFFFFFF
  481. #emit PUSH.S i
  482. #emit PUSH.C 8
  483. #emit LCTRL 6
  484. #emit ADD.C 28
  485. #emit PUSH.pri
  486. #emit LOAD.pri YSI_g_sNextInitFunc
  487. #emit SCTRL 6
  488. }
  489. return i | GROUP_MASK;
  490. }
  491. // Added for the fun of it.
  492. foreign Group_Destroy(Group:group);
  493. global Group_Destroy(Group:group)
  494. {
  495. P:2("Group_Destroy called: %i", _:group);
  496. P:2("Group_Destroy called in %d", _@);
  497. GROUP_FIX(group);
  498. if (_Group_IsValid(group))
  499. {
  500. YSI_gGroupData[group][E_GROUP_DATA_FLAGS] = e_GROUP_FLAGS:0;
  501. YSI_gGroupData[group][E_GROUP_DATA_HASH] = 0;
  502. if (YSI_g_sNextUpdateFunc)
  503. {
  504. // Update all players who were in this group as they may have lost
  505. // some permissions.
  506. foreach (new p : Player)
  507. {
  508. if (_Group_HasPlayer(group, p))
  509. {
  510. //CallLocalFunction(YSI_g_sNextInitFunc, "iii", p, _:MAX_GROUPS, 0);
  511. #emit PUSH.C 0
  512. #emit PUSH.C 0
  513. #emit PUSH.S p
  514. #emit PUSH.C 12
  515. #emit LCTRL 6
  516. #emit ADD.C 28
  517. #emit PUSH.pri
  518. #emit LOAD.pri YSI_g_sNextUpdateFunc
  519. #emit SCTRL 6
  520. }
  521. }
  522. }
  523. }
  524. return 1;
  525. }
  526. //forward _GROUP_CREATE(group);
  527. /*foreign YSI_gSGroupFunc(Group:group);
  528. global YSI_gSGroupFunc(Group:group)
  529. {
  530. P:3("YSI_gSGroup called: %i", _:group);
  531. GROUP_FIX(group);
  532. if (!_Group_IsValid(group))
  533. {
  534. return -1;
  535. }
  536. static const
  537. scDeBruijn[] =
  538. {
  539. 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  540. 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
  541. };
  542. new
  543. cur;
  544. for (new i = 1; i != bits<MAX_PLAYERS> + 1; ++i)
  545. {
  546. if ((cur = _:YSI_gGroupPlayers[group][i]))
  547. {
  548. // http://supertech.csail.mit.edu/papers/debruijn.pdf
  549. return ((i - 1) * cellbits) + scDeBruijn[((cur & -cur) * 0x077CB531) >>> 27];
  550. }
  551. }
  552. return -1;
  553. }*/
  554. //foreign YSI_gAGroupFunc(Group:group, start);
  555. //global YSI_gAGroupFunc(Group:group, start)
  556. foreign Group@YSII_Ag(Group:group, start);
  557. global Group@YSII_Ag(Group:group, start)
  558. {
  559. P:3("YSI_gAGroupFunc called: %i, %i", _:group, start);
  560. GROUP_FIX(group);
  561. if (!_Group_IsValid(group))
  562. {
  563. return -1;
  564. }
  565. static const
  566. scDeBruijn[] =
  567. {
  568. 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  569. 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
  570. };
  571. ++start;
  572. new
  573. cur,
  574. i = Bit_Slot(start) + 1;
  575. if ((cur = (_:YSI_gGroupPlayers[group][i] & (~((1 << start) - 1)))))
  576. {
  577. return ((i - 1) * cellbits) + scDeBruijn[((cur & -cur) * 0x077CB531) >>> 27];
  578. }
  579. ++i;
  580. while (i != bits<MAX_PLAYERS> + 1)
  581. {
  582. if ((cur = _:YSI_gGroupPlayers[group][i]))
  583. {
  584. return ((i - 1) * cellbits) + scDeBruijn[((cur & -cur) * 0x077CB531) >>> 27];
  585. }
  586. ++i;
  587. }
  588. return -1;
  589. }
  590. /*stock Group:operator-(Group:group, Group:playerid)
  591. {
  592. P:3("Group:operator- called: %i, %i", _:group, _:playerid);
  593. Group_SetPlayer(group, playerid, false);
  594. return group;
  595. }
  596. stock Group:operator+(Group:group, playerid)
  597. {
  598. P:3("Group:operator+ called: %i, %i", _:group, playerid);
  599. Group_SetPlayer(group, playerid, false);
  600. return group;
  601. }
  602. stock Group:operator==(Group:group, playerid)
  603. {
  604. P:3("Group:operator== called: %i, %i", _:group, playerid);
  605. return Group_GetPlayer(group, playerid);
  606. }*/
  607. //#define YSI_gAGroup(%0)[%1] YSI_gAGroupFunc(%0,%1)
  608. /*foreign Group:YSI_gSPlayerGroupsFunc(playerid);
  609. global Group:YSI_gSPlayerGroupsFunc(playerid)
  610. {
  611. P:3("Group:YSI_gSPlayerGroups called: %i", playerid);
  612. new
  613. s = Bit_Slot(playerid) + 1,
  614. Bit:m = ~Bit_Mask(playerid);
  615. for (new Group:i; i != MAX_GROUPS; ++i)
  616. {
  617. if (_Group_IsValid(i))
  618. {
  619. // Fast membership test.
  620. if (YSI_gGroupPlayers[i][s] & m)
  621. {
  622. return i | GROUP_MASK;
  623. }
  624. }
  625. }
  626. return Group:-1;
  627. }*/
  628. //foreign Group:YSI_gAPlayerGroupsFunc(playerid, Group:start);
  629. //global Group:YSI_gAPlayerGroupsFunc(playerid, Group:start)
  630. foreign Group:PlayerGroups@YSII_Ag(playerid, Group:start);
  631. global Group:PlayerGroups@YSII_Ag(playerid, Group:start)
  632. {
  633. P:3("Group:YSI_gAPlayerGroupsFunc called: %i, %i", playerid, _:start);
  634. // Get the bit for this player in the bit array.
  635. if (start == Group:-1)
  636. {
  637. start = GROUP_MASK;
  638. }
  639. new
  640. s = Bit_Slot(playerid) + 1,
  641. Bit:m = ~Bit_Mask(playerid);
  642. // To identify them, groups have special data set, but we need access to
  643. // the low-level information contained within.
  644. for (new Group:i = GROUP_TEMP_FIX(start); i != MAX_GROUPS; ++i)
  645. {
  646. if (_Group_IsValid(i))
  647. {
  648. // Fast membership test.
  649. if (YSI_gGroupPlayers[i][s] & m)
  650. {
  651. return Group:i | GROUP_MASK;
  652. }
  653. }
  654. }
  655. return Group:-1;
  656. }
  657. stock _Group_ChainCall1(a, h)
  658. {
  659. // Because "#emit" ignores "#ifdef".
  660. #emit PUSH.S a
  661. #emit PUSH.C 0xFFFFFFFF
  662. #emit PUSH.C 8
  663. #emit LCTRL 6
  664. #emit ADD.C 28
  665. #emit PUSH.pri
  666. #emit LOAD.S.pri h
  667. #emit SCTRL 6
  668. }
  669. stock _Group_ChainCall2(s, g, p, n)
  670. {
  671. // Because "#emit" ignores "#ifdef".
  672. #emit PUSH.S s
  673. #emit PUSH.S g
  674. #emit PUSH.S p
  675. #emit PUSH.C 12
  676. #emit LCTRL 6
  677. #emit ADD.C 28
  678. #emit PUSH.pri
  679. #emit LOAD.pri n
  680. #emit SCTRL 6
  681. }
  682. //#define YSI_gAPlayerGroups(%0)[%1] YSI_gAPlayerGroupsFunc(%0,%1)
  683. // These are hacks to make the old system of functions working. This is now
  684. // done natively by "y_iterate" - which does free up the "Group" macro for more
  685. // useful things!
  686. //#define Group(%0)_YSII_Sg;_:%1!=-1;%2=_Y_ITER_ARRAY:%8Group(%3)_YSII_Ag[%4] YSI_gSGroupFunc(%0);_:%1!=-1;%2=YSI_gAGroupFunc(%3,%4)
  687. //#define PlayerGroups(%0)_YSII_Sg;_:%1!=-1;%2=_Y_ITER_ARRAY:%8PlayerGroups(%3)_YSII_Ag[%4] YSI_gSPlayerGroupsFunc(%0);_:%1!=-1;%2=YSI_gAPlayerGroupsFunc(%3,%4)
  688. #define _YSIM_RESET_USER
  689. #include "..\y_master"