1
0

y_grouponce.inc 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631
  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. 04/10/12:
  46. Major update to better distribute group data. Now all script have it.
  47. Changed the code to favour common cases of element creation not groups.
  48. Added group hierarchys.
  49. 29/11/10:
  50. First version
  51. \*----------------------------------------------------------------------------*/
  52. #include <a_samp>
  53. #include "..\y_scriptinit"
  54. //#include "..\y_master"
  55. #define YSIM_U_DISABLE
  56. #include "..\y_master"
  57. #include "..\y_playerarray"
  58. #include "..\y_stringhash"
  59. #include "..\y_debug"
  60. #include "..\y_remote"
  61. //#include "..\y_hooks"
  62. #include "..\y_amx"
  63. //#include "..\y_cell"
  64. #include "..\y_iterate"
  65. #include "..\y_hooks"
  66. //#define _YSI_HAS_GROUP_SYSTEM
  67. //#define _GROUP_MAKE_NAME<%0...%1> %0_%1
  68. // Dummy value
  69. //#define _GROUP_MAKE_LIMIT 0
  70. // Dummy values.
  71. #undef _GROUP_MAKE_NAME
  72. #undef _GROUP_MAKE_LIMIT
  73. #define _GROUP_MAKE_NAME<%0...%1> %0_%1
  74. #define _GROUP_MAKE_LIMIT 0
  75. #define _GROUP_MAKE_NAME_GROUP<%0...%1> %0Group%1
  76. #define _GROUP_MAKE_LIMIT_GROUP _MAX_GROUPS
  77. // Example:
  78. // #define _GROUP_MAKE_NAME<%0...%1> %0Checkpoint%1
  79. /*#if !defined _GROUP_MAKE_NAME
  80. #error Please define _GROUP_MAKE_NAME before including y_groupsone.
  81. #endif
  82. #if !defined _GROUP_MAKE_LIMIT
  83. #error Please define _GROUP_MAKE_LIMIT before including y_groupsone.
  84. #endif*/
  85. // Define local variable names. This will go in the single call file.
  86. //#define _GROUP_LOCAL_NAME _GROUP_MAKE_NAME<i...>
  87. #define _GROUP_GROUP_NAME _GROUP_MAKE_NAME<YSI_gs_Group...Data>
  88. #define _GROUP_GLOBAL_NAME //_GROUP_MAKE_NAME<YSI_gs_GroupGlobal...>
  89. /*stock _Group_ErrorFunc()
  90. {
  91. // BEST FUNCTION EVER!
  92. group group group
  93. }*/
  94. //#define _GROUP_SET_PLAYER _GROUP_MAKE_NAME<..._SetPlayer>
  95. /*#define _GROUP_UPDATE _GROUP_MAKE_NAME<Group_UpdatePlayer...>
  96. #define _GROUP_UPDATE_ALL _GROUP_MAKE_NAME<Group_UpdateAll...>
  97. #define _GROUP_GROUP_FUNC _GROUP_MAKE_NAME<Group_Set...>
  98. #define _GROUP_GLOBAL_FUNC _GROUP_MAKE_NAME<Group_SetGlobal...>
  99. #define _GROUP_GLOBAL_DEF _GROUP_MAKE_NAME<Group_SetGlobal...Default>
  100. #define _GROUP_GROUP_DEF _GROUP_MAKE_NAME<Group_Set...Default>
  101. //#define _GROUP_ON_PLAYER_CONNECT _GROUP_MAKE_NAME<@yH_PlayerConnect_...@yG>
  102. #define _GROUP_ON_PLAYER_CONNECT _GROUP_MAKE_NAME<@yH_PlayerConnect...@yG>
  103. #define _GROUP_DEFAULTS _GROUP_MAKE_NAME<Group_...Defaults>
  104. #define _GROUP_INIT _GROUP_MAKE_NAME<Group_...Init>*/
  105. #define _GROUP_CREATE _GROUP_MAKE_NAME<@yG_Init...>
  106. #define _GROUP_UPDATE_PLAYER _GROUP_MAKE_NAME<@yG_Upd...>
  107. //#define _GROUP_ON_PLAYER_CONNECT _GROUP_MAKE_NAME<@yG_..._PlayerConnect>
  108. //#define _GROUP_ON_PLAYER_CONNECT RH:_GROUP_MAKE_NAME<...@yG_OnPlayerConnect>
  109. /*#define _GROUP_OPC_OTHER_CALLED _GROUP_MAKE_NAME<_@yGPlayerConnect_...>
  110. #define _GROUP_OPC_IS_CALLED _GROUP_MAKE_NAME<_yG@PlayerConnect_...>
  111. #define _GROUP_OPC_PUBLIC _GROUP_MAKE_NAME<@yG_PlayerConnect_...>*/
  112. //#define group_hook%0On%1(%2) _GROUP_MAKE_NAME<master_hook On%1...>(%2)
  113. /*#define ghook%0(%1)
  114. #include "y_groupsecond.inc"
  115. #undef ghook
  116. #define ghook group_hook*/
  117. #define gforeign%1(%2); _GROUP_MAKE_NAME<foreign%1>(%2);
  118. #define gglobal%1(%2) _GROUP_MAKE_NAME<global%1>(%2)
  119. /*----------------------------------------------------------------------------*\
  120. Function:
  121. GROUP_CHAIN
  122. Params:
  123. %9 - Check if the function exists?
  124. %0 - Variable holding the function.
  125. %1 - Parameters.
  126. Return:
  127. -
  128. Notes:
  129. Calls the correct function to chain a function with the given number of
  130. parameters, calls the function stored in a variable and passes parameters
  131. BY REFERENCE - ALL of them!
  132. \*----------------------------------------------------------------------------*/
  133. #define GROUP_CHAIN%9<%0>(%1) (J@=_:(_Y_G@C_YES:_Y_G@C_NO:%0%9|||(_:_Y_G@C3:_Y_G@C2:_Y_G@C0:_Y_G@C1:%0(%1))))
  134. #define _Y_G@C3:_Y_G@C2:_Y_G@C0:_Y_G@C1:%0(%1,%2,%3) _Y_G@C_3(%0,_:_Y_G@P:_Y_G@Q:_Y_G@R:%1,_:%2,_:%3|||)
  135. #define _Y_G@C2:_Y_G@C0:_Y_G@C1:%0(%1,%2) _Y_G@C_2(%0,_:_Y_G@P:_Y_G@Q:_Y_G@R:%1,_:%2|||)
  136. #define _Y_G@C0:_Y_G@C1:%0() _Y_G@C_0(%0)
  137. #define _Y_G@C1:%0(%1) _Y_G@C_1(%0,_:_Y_G@P:_Y_G@Q:_Y_G@R:%1|||)
  138. #define _Y_G@C_YES:_Y_G@C_NO:%0?||| (!(%0))?(0):
  139. #define _Y_G@C_NO:%0|||
  140. // Can strip out multiple brackets in one go.
  141. #define _Y_G@P:%0[]%1||| _Y_G@P:%0%1|||
  142. #define _Y_G@Q:%0&%1||| _Y_G@Q:%0%1|||
  143. #define _Y_G@R:%0||| %0
  144. //#define master_hook%0On%2(%3) hook On%2(%3)<>return 1;rehook On%2(%3)<_YCM:y>
  145. #if !defined MAX_GROUP_NAME
  146. #define MAX_GROUP_NAME (24)
  147. #endif
  148. #if defined MAX_GROUPS
  149. // Round up to the next nice number (or not, we could with long macros).
  150. #define _MAX_GROUPS (_:MAX_GROUPS)
  151. #else
  152. // 1 less than a nice number (with good reason).
  153. #define _MAX_GROUPS (_:127)
  154. #endif
  155. #define _MAX_GROUPS_G (_:_MAX_GROUPS + 1)
  156. // Note that these macros always do the last element before all the others
  157. // (which may or may not be in order). This is as the last element holds the
  158. // "default" group, which is the most likely to be a good match.
  159. #if _MAX_GROUPS < 32
  160. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[0]&%1[0])
  161. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[0]&%1[0]==%0[0])
  162. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[0]==%1[0])
  163. #define _GROUPS_CHECK_NONE(%0,%1) if(!(%0[0]&%1[0]))
  164. #elseif _MAX_GROUPS < 64
  165. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[1]&%1[1]||%0[0]&%1[0])
  166. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[1]&%1[1]||%0[0]&%1[0])
  167. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[1]&%1[1]||%0[0]&%1[0])
  168. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[1]&%1[1]||%0[0]&%1[0])
  169. #elseif _MAX_GROUPS < 96
  170. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[2]&%1[2]||%0[0]&%1[0]||%0[1]&%1[1])
  171. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[2]&%1[2]||%0[0]&%1[0]||%0[1]&%1[1])
  172. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[2]&%1[2]||%0[0]&%1[0]||%0[1]&%1[1])
  173. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[2]&%1[2]||%0[0]&%1[0]||%0[1]&%1[1])
  174. #elseif _MAX_GROUPS < 128
  175. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[3]&%1[3]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2])
  176. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[3]&%1[3]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2])
  177. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[3]&%1[3]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2])
  178. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[3]&%1[3]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2])
  179. #elseif _MAX_GROUPS < 160
  180. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[4]&%1[4]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3])
  181. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[4]&%1[4]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3])
  182. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[4]&%1[4]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3])
  183. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[4]&%1[4]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3])
  184. #elseif _MAX_GROUPS < 192
  185. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[5]&%1[5]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4])
  186. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[5]&%1[5]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4])
  187. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[5]&%1[5]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4])
  188. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[5]&%1[5]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4])
  189. #elseif _MAX_GROUPS < 224
  190. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[6]&%1[6]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5])
  191. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[6]&%1[6]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5])
  192. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[6]&%1[6]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5])
  193. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[6]&%1[6]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5])
  194. #elseif _MAX_GROUPS < 256
  195. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[7]&%1[7]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6])
  196. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[7]&%1[7]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6])
  197. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[7]&%1[7]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6])
  198. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[7]&%1[7]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6])
  199. #elseif _MAX_GROUPS < 288
  200. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[8]&%1[8]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7])
  201. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[8]&%1[8]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7])
  202. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[8]&%1[8]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7])
  203. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[8]&%1[8]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7])
  204. #elseif _MAX_GROUPS < 320
  205. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[9]&%1[9]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8])
  206. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[9]&%1[9]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8])
  207. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[9]&%1[9]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8])
  208. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[9]&%1[9]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8])
  209. #elseif _MAX_GROUPS < 352
  210. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[10]&%1[10]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9])
  211. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[10]&%1[10]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9])
  212. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[10]&%1[10]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9])
  213. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[10]&%1[10]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9])
  214. #elseif _MAX_GROUPS < 384
  215. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[11]&%1[11]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10])
  216. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[11]&%1[11]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10])
  217. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[11]&%1[11]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10])
  218. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[11]&%1[11]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10])
  219. #elseif _MAX_GROUPS < 416
  220. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[12]&%1[12]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11])
  221. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[12]&%1[12]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11])
  222. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[12]&%1[12]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11])
  223. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[12]&%1[12]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11])
  224. #elseif _MAX_GROUPS < 448
  225. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[13]&%1[13]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12])
  226. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[13]&%1[13]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12])
  227. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[13]&%1[13]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12])
  228. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[13]&%1[13]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12])
  229. #elseif _MAX_GROUPS < 480
  230. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[14]&%1[14]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13])
  231. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[14]&%1[14]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13])
  232. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[14]&%1[14]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13])
  233. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[14]&%1[14]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13])
  234. #elseif _MAX_GROUPS < 512
  235. #define _GROUPS_CHECK_ANY(%0,%1) if(%0[15]&%1[15]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13]||%0[14]&%1[14])
  236. #define _GROUPS_CHECK_ALL(%0,%1) if(%0[15]&%1[15]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13]||%0[14]&%1[14])
  237. #define _GROUPS_CHECK_BOTH(%0,%1) if(%0[15]&%1[15]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13]||%0[14]&%1[14])
  238. #define _GROUPS_CHECK_NONE(%0,%1) if(%0[15]&%1[15]||%0[0]&%1[0]||%0[1]&%1[1]||%0[2]&%1[2]||%0[3]&%1[3]||%0[4]&%1[4]||%0[5]&%1[5]||%0[6]&%1[6]||%0[7]&%1[7]||%0[8]&%1[8]||%0[9]&%1[9]||%0[10]&%1[10]||%0[11]&%1[11]||%0[12]&%1[12]||%0[13]&%1[13]||%0[14]&%1[14])
  239. #else
  240. #define _GROUPS_CHECK(%0,%1) \
  241. for (new __g = bits<_:_MAX_GROUPS + 1>; __g-- != 0; ) if (_:%0[__g] & _:%1[__g])
  242. //for (new __g = 0; __g != bits<_:_MAX_GROUPS + 1>; ++__g) if (_:%0[__g] & _:%1[__g])
  243. #endif
  244. /*
  245. New groups check:
  246. if (ALL A == ALL B)
  247. {
  248. if (ALL A == P)
  249. {
  250. // Add.
  251. }
  252. else
  253. {
  254. // Remove.
  255. }
  256. }
  257. else
  258. {
  259. if (ANY A == P && NO B == P)
  260. {
  261. // Add.
  262. }
  263. else
  264. {
  265. // Remove.
  266. }
  267. }
  268. */
  269. enum e_GROUP_FLAGS (<<= 1)
  270. {
  271. e_GROUP_FLAGS_NONE = 0,
  272. e_GROUP_FLAGS_GANG = 1,
  273. // I can't remember why I had this!
  274. //e_GROUP_FLAGS_CHAT,
  275. e_GROUP_FLAGS_ACTIVE,
  276. // Only ever set for one group.
  277. e_GROUP_FLAGS_GLOBAL,
  278. // Has no name.
  279. e_GROUP_FLAGS_TEMP,
  280. e_GROUP_FLAGS_COLOR = 0xFFFFFF00
  281. }
  282. enum E_GROUP_DATA
  283. {
  284. E_GROUP_DATA_NAME[MAX_GROUP_NAME char],
  285. //E_GROUP_DATA_COUNT,
  286. E_GROUP_DATA_HASH,
  287. e_GROUP_FLAGS:E_GROUP_DATA_FLAGS,
  288. }
  289. // Define the groups iterator in terms of the underlying bits, but without the
  290. // need for users to know about the "YSI_gGroupPlayers" array, just the player.
  291. #define PlayerGroups@YSII_Ag(%0,%1) Group:Bits@YSII_Ag(YSI_gGroupPlayers[%0],_:%1)|GROUP_MASK
  292. // I have "new", "stock", "static", "static stock" and "static stock const" -
  293. // that is pretty much every meaningful combination possible! The only other
  294. // vaguely useful one would be "stock const". In fact I now have that too!
  295. new //stock
  296. //PlayerArray:YSI_gGroupPlayers[_MAX_GROUPS]<MAX_PLAYERS>,
  297. BitArray:YSI_gGroupPlayers[MAX_PLAYERS]<_MAX_GROUPS_G>;
  298. stock
  299. BitArray:YSI_gTempGroups<_MAX_GROUPS_G>;
  300. stock const
  301. BitArray:YSI_g_cEmptyGroups<_MAX_GROUPS_G>;
  302. //#define GROUPS_MAX_LIBRARIES 4
  303. static
  304. // Function pointers for chaining.
  305. YSI_g_sNextInitFunc,
  306. YSI_g_sNextUpdFunc,
  307. YSI_g_sNextAddFunc,
  308. YSI_g_sGroupCount;
  309. static stock const
  310. YSI_g_scGlobalName[] = "__GLOBAL",
  311. BitArray:RG@<_MAX_GROUPS_G>;
  312. static stock
  313. // Create group hierarchys.
  314. YSI_gGroupData[_MAX_GROUPS_G][E_GROUP_DATA],
  315. BitArray:YSI_g_sChildGroups[_MAX_GROUPS_G]<_MAX_GROUPS_G>,
  316. //BitArray:YSI_g_sChildDefaults<_MAX_GROUPS_G>,
  317. Iterator:GroupPlayers[_MAX_GROUPS_G]<MAX_PLAYERS>;
  318. MASTER_DATA<_MAX_GROUPS_G>
  319. //#define GROUP_BITS<%0> BitArray:%0<_MAX_GROUPS_G>,
  320. #define _Group_HasPlayer(%0,%1) \
  321. Bit_Get(YSI_gGroupPlayers[(%1)],(%0)) //, _MAX_GROUPS_G)
  322. //PA_Get(YSI_gGroupPlayers[(%0)],(%1))
  323. //Bit_Get(YSI_gGroupPlayers[(%0)], (%1), MAX_PLAYERS)
  324. #define _Group_GetColor(%0) \
  325. (_:(YSI_gGroupData[_:(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_COLOR) | 0xAA)
  326. #define _Group_SetColor(%0,%1) \
  327. (YSI_gGroupData[_:(%0)][E_GROUP_DATA_FLAGS] = (YSI_gGroupData[_:(%0)][E_GROUP_DATA_FLAGS] & ~e_GROUP_FLAGS_COLOR) | (e_GROUP_FLAGS:(%1) & e_GROUP_FLAGS_COLOR))
  328. #define _Group_GetGang(%0) \
  329. (bool:(YSI_gGroupData[_:(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_GANG))
  330. #define _Group_LetGang(%0) \
  331. (YSI_gGroupData[_:(%0)][E_GROUP_DATA_FLAGS] |= e_GROUP_FLAGS_GANG)
  332. #define _Group_VetGang(%0) \
  333. (YSI_gGroupData[_:(%0)][E_GROUP_DATA_FLAGS] &= ~e_GROUP_FLAGS_GANG)
  334. #define _Group_IsActive(%0) \
  335. (YSI_gGroupData[_:(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_ACTIVE)
  336. //#define _Group_IsValid(%0)
  337. // (0 <= (%0) < _MAX_GROUPS && Group_IsActive(%0))
  338. #define _Group_IsValid(%0) \
  339. ((_:GROUP_MASK<=_:(%0)<=_:GROUP_GLOBAL)&&(_Group_IsActive(GROUP_TEMP_FIX(%0))))
  340. //#define Group_IsActive(%0)
  341. // (YSI_gGroupData[_:GROUP_FIX(%0)][E_GROUP_DATA_FLAGS] & e_GROUP_FLAGS_ACTIVE)
  342. /*----------------------------------------------------------------------------*\
  343. Function:
  344. GROUP_ADD
  345. Params:
  346. Group:g - Group to add the following items to.
  347. Return:
  348. -
  349. Notes:
  350. This sets up a temporary environment, during which all items are ONLY added
  351. to the specified group and no others, with no complex extra code required.
  352. \*----------------------------------------------------------------------------*/
  353. #define GROUP_ADD<%0> for(J@=_Group_AddInternal(1,(%0));J@;J@=_Group_AddInternal(0,(%0)))
  354. stock _Group_AddInternal(a, Group:g)
  355. {
  356. //printf("_Group_AddInternal %d %d", a, _:g);
  357. if (_Group_IsValid(g))
  358. {
  359. broadcastfunc __Group_AddInternal(a, _:GROUP_TEMP_FIX(g));
  360. return a;
  361. }
  362. else
  363. {
  364. return 0;
  365. }
  366. }
  367. static remotefunc void:__Group_AddInternal(a,g)
  368. {
  369. GROUP_CHAIN?<YSI_g_sNextInitFunc>(-1, a, g);
  370. }
  371. /*----------------------------------------------------------------------------*\
  372. Function:
  373. Group_IsValid
  374. Params:
  375. Group:g - Group to check.
  376. Return:
  377. bool: - Is the group active and valid?
  378. Notes:
  379. -
  380. \*----------------------------------------------------------------------------*/
  381. foreign bool:Group_IsValid(Group:g);
  382. global bool:Group_IsValid(Group:g)
  383. {
  384. //GROUP_FIX(g);
  385. return _Group_IsValid(g);
  386. }
  387. /*----------------------------------------------------------------------------*\
  388. Function:
  389. OnScriptInit
  390. Params:
  391. -
  392. Return:
  393. -
  394. Notes:
  395. Finds three functions by prefix:
  396. _yGI - An init function to set up a script using groups.
  397. _yGA - An add function called when a new group is created.
  398. _yGU - An update function called when a player's groups change.
  399. \*----------------------------------------------------------------------------*/
  400. public OnScriptInit()
  401. {
  402. P:1("Group_OnScriptInit called");
  403. state YSI_has_groups:y;
  404. // Set up the global groups.
  405. #if !(YSIM_HAS_MASTER && (_YSIM_IS_STUB || _YSIM_IS_CLIENT))
  406. #if _YSIM_IS_CLOUD
  407. if (_YCM@y)
  408. #endif
  409. {
  410. P:5("Group_OnScriptInit: Master");
  411. Iter_Init(GroupPlayers);
  412. strpack(YSI_gGroupData[_MAX_GROUPS][E_GROUP_DATA_NAME], YSI_g_scGlobalName, MAX_GROUP_NAME char);
  413. YSI_gGroupData[_MAX_GROUPS][E_GROUP_DATA_FLAGS] = e_GROUP_FLAGS_ACTIVE | e_GROUP_FLAGS_GLOBAL;
  414. YSI_gGroupData[_MAX_GROUPS][E_GROUP_DATA_HASH] = YHash(YSI_g_scGlobalName);
  415. Bit_Let(YSI_g_sChildGroups[_MAX_GROUPS], _:_MAX_GROUPS);
  416. }
  417. #endif
  418. // Call the other group init functions.
  419. new
  420. ni = AMX_GetPublicPointerPrefix(0, YSI_g_sNextInitFunc, _A<_yGI>),
  421. na = AMX_GetPublicPointerPrefix(0, YSI_g_sNextAddFunc, _A<_yGA>),
  422. nu = AMX_GetPublicPointerPrefix(0, YSI_g_sNextUpdFunc, _A<_yGU>);
  423. //printf("Group_OnScriptInit: %d, %d, %d", ni, na, nu);
  424. P:5("Group_OnScriptInit: %d, %d, %d", ni, na, nu);
  425. GROUP_CHAIN?<YSI_g_sNextInitFunc>(ni, na, nu);
  426. //CallLocalFunction("_Group_SpecialInit", "");
  427. return _Group_SpecialInit();
  428. }
  429. #undef OnScriptInit
  430. #define OnScriptInit(%0) _Group_SpecialInit(%0) <_ALS_:hooked>
  431. forward _Group_SpecialInit();public _Group_SpecialInit()<_ALS_:unhooked>{return 1;}public _Group_SpecialInit()<>{return 1;}
  432. /*----------------------------------------------------------------------------*\
  433. Function:
  434. OnScriptExit
  435. Params:
  436. -
  437. Return:
  438. -
  439. Notes:
  440. Destroy all this script's groups. This is an instance of "_YSI_SpecialExit"
  441. which can't be y_hooked and is called after (almost) every other callback,
  442. at least after every one controlled via y_scriptinit.
  443. \*----------------------------------------------------------------------------*/
  444. public _YSI_SpecialExit()
  445. {
  446. _Group_TryRemove();
  447. //CallLocalFunction("_Group_SpecialExit", "");
  448. return _Group_SpecialExit();
  449. }
  450. #undef _YSI_SpecialExit
  451. #define _YSI_SpecialExit(%0) _Group_SpecialExit(%0) <_ALS_:hooked>
  452. forward _Group_SpecialExit();public _Group_SpecialExit()<_ALS_:unhooked>{return 1;}public _Group_SpecialExit()<>{return 1;}
  453. /*----------------------------------------------------------------------------*\
  454. FunctiOn:
  455. _Group_TryRemove
  456. Params:
  457. -
  458. Return:
  459. -
  460. Notes:
  461. Removes all groups purely owned by the calling script.
  462. \*----------------------------------------------------------------------------*/
  463. @foreign void:_Group_TryRemove();
  464. @global void:_Group_TryRemove()
  465. {
  466. for (new i = 0; i != _MAX_GROUPS; ++i)
  467. {
  468. MASTER_REMOVE<i>
  469. MASTER_EMPTY<i>
  470. {
  471. broadcastfunc _Group_Destroy(i, Iter_InternalArray(GroupPlayers[i]), Iter_InternalSize(GroupPlayers[i]));
  472. YSI_gGroupData[i][E_GROUP_DATA_FLAGS] = e_GROUP_FLAGS:0;
  473. YSI_gGroupData[i][E_GROUP_DATA_HASH] = 0;
  474. Iter_Clear(GroupPlayers[i]);
  475. }
  476. }
  477. //return 1;
  478. }
  479. /*----------------------------------------------------------------------------*\
  480. Function:
  481. OnPlayerDisconnect
  482. Params:
  483. playerid - The player that left.
  484. reason - Why they left (unused).
  485. Return:
  486. -
  487. Notes:
  488. Removes this player from all groups. Unfortunately there's no way to
  489. combine multiple iterator removals to improve their efficiency - currently
  490. they have to loop through all previous ones to find the one to modify to
  491. skip over that player. I did debate updating foreach to doubly-linked
  492. lists for this reason - that would make reverse traversal and removal faster
  493. by doubling memory consumption but only very slightly affecting adds.
  494. \*----------------------------------------------------------------------------*/
  495. hook OnPlayerDisconnect(playerid, reason)
  496. {
  497. #pragma unused reason
  498. P:2("hook OnPlayerDisconnect called: %d, %d", playerid, reason);
  499. // Can't - can't what? Don't stop typing mid comment!
  500. //foreach (new Group:g : PlayerGroups(playerid))
  501. #if !(YSIM_HAS_MASTER && (_YSIM_IS_STUB || _YSIM_IS_CLIENT))
  502. #if _YSIM_IS_CLOUD
  503. if (_YCM@y)
  504. #endif
  505. {
  506. foreach (new g : Bits(YSI_gGroupPlayers[playerid]))
  507. {
  508. Iter_Remove(GroupPlayers[g], playerid);
  509. Bit_Vet(YSI_gGroupPlayers[playerid], g);
  510. }
  511. }
  512. #endif
  513. // Remove them from everything ever.
  514. //static const
  515. // BitArray:scEmpty<_MAX_GROUPS_G>;
  516. //GROUP_CHAIN?<YSI_g_sNextUpdFunc>(playerid, YSI_gGroupPlayers[p], scEmpty);
  517. YSI_gGroupPlayers[playerid] = YSI_g_cEmptyGroups;
  518. }
  519. /*----------------------------------------------------------------------------*\
  520. Function:
  521. OnPlayerConnect
  522. Params:
  523. playerid - The player that joined.
  524. Return:
  525. -
  526. Notes:
  527. The player may not have ACTUALLY joined the server, they may have just been
  528. added to this newly loaded script. In that case we need to initialise the
  529. locally stored group data to the new data. Of course, if this script is the
  530. group master, then we need to do significantly more! This is more complex
  531. than other scripts with master as they don't have some things to do in non-
  532. master scripts as well, whereas this one does.
  533. \*----------------------------------------------------------------------------*/
  534. hook OnPlayerConnect9(playerid)
  535. {
  536. #if !(YSIM_HAS_MASTER && (_YSIM_IS_STUB || _YSIM_IS_CLIENT))
  537. #if _YSIM_IS_CLOUD
  538. if (_YCM@y)
  539. #endif
  540. {
  541. P:6("Group_OnPlayerConnect: Master %d", playerid);
  542. // Is master. ALWAYS reset all players - if they start screwing
  543. // around with loading orders then that's their own fault!
  544. //_Group_InitPlayer(playerid);
  545. broadcastfunc _Group_FakePlayer(playerid, YSI_g_sChildGroups[_MAX_GROUPS], bits<_MAX_GROUPS_G>);
  546. }
  547. #if _YSIM_IS_CLOUD
  548. else
  549. #endif
  550. #endif
  551. #if YSIM_HAS_MASTER
  552. {
  553. P:6("Group_OnPlayerConnect: Slave %d", playerid);
  554. static const
  555. BitArray:scF<_MAX_GROUPS_G> = {Bit:-1, ...};
  556. _GROUPS_CHECK_ANY(scF, YSI_gGroupPlayers[playerid])
  557. {
  558. // Already been set up - return.
  559. return 1;
  560. }
  561. //_Group_
  562. _Group_InitPlayer(playerid, _@);
  563. }
  564. #endif
  565. return 1;
  566. }
  567. /*----------------------------------------------------------------------------*\
  568. Function:
  569. _Group_InitPlayer
  570. Params:
  571. p - The player that joined.
  572. master - The script that just started.
  573. Return:
  574. -
  575. Notes:
  576. Request all a player's groups from the master system.
  577. \*----------------------------------------------------------------------------*/
  578. foreign void:_Group_InitPlayer(p, master);
  579. global void:_Group_InitPlayer(p, master)
  580. {
  581. targetfunc _Group_FakePlayer<master>(p, YSI_gGroupPlayers[p], bits<_MAX_GROUPS_G>);
  582. //Set their groups to the global group.
  583. //foreach (new i : Bits(YSI_gGroupData[_MAX_GROUPS]))
  584. //{
  585. // Iter_Add(GroupPlayers[i], playerid);
  586. //}
  587. //YSI_gGroupPlayers[playerid] = YSI_gGroupData[_MAX_GROUPS];
  588. //return 1;
  589. }
  590. /*----------------------------------------------------------------------------*\
  591. Function:
  592. _Group_SetSome
  593. Params:
  594. playerid - Player to add to multiple groups.
  595. group - Parent group to add to.
  596. Return:
  597. A new array of groups.
  598. Notes:
  599. Takes a group and adds a player to that group and every child group of
  600. which they are not already a member.
  601. \*----------------------------------------------------------------------------*/
  602. static stock Bit:_Group_SetSome(playerid, group)
  603. {
  604. // If you overflow this stack there is something VERY wrong! The manual
  605. // stack is intended to help us combat very long inheritance chains. This
  606. // code also neatly ignores recursion by only doing any one group if the
  607. // player doesn't already have it.
  608. static
  609. sStack[128][2];//,
  610. //BitArray:n<_MAX_GROUPS_G>;
  611. new
  612. g = -1,
  613. s = 0;
  614. YSI_gTempGroups = YSI_gGroupPlayers[playerid];
  615. Bit_Let(YSI_gTempGroups, group);
  616. for ( ; ; )
  617. {
  618. g = Bits@YSII_Ag(YSI_g_sChildGroups[group], g, bits<_MAX_GROUPS_G>);
  619. if (g == -1)
  620. {
  621. // Finished this child group, pop off the stack.
  622. if (s--)
  623. {
  624. g = sStack[s][0];
  625. group = sStack[s][1];
  626. }
  627. else break;
  628. }
  629. else if (!Bit_Get(YSI_gTempGroups, g)) //_Group_HasPlayer(g, playerid))
  630. {
  631. // This player isn't in this group, add them.
  632. Bit_Let(YSI_gTempGroups, g);
  633. sStack[s][0] = g;
  634. sStack[s][1] = group;
  635. ++s;
  636. group = g;
  637. g = -1;
  638. }
  639. }
  640. return YSI_gTempGroups;
  641. }
  642. /*----------------------------------------------------------------------------*\
  643. Function:
  644. Group_SetPlayer
  645. Params:
  646. Group:g - Group to modify.
  647. p - Player to modify the group for.
  648. bool:s - Add the player (true) or remove them (false).
  649. Return:
  650. -
  651. Notes:
  652. Will in some cases update all settings, unless they are being added through
  653. a recursive call due to being added to child groups.
  654. There is an internal version that ONLY adds them to the group and DOES NOT
  655. update any of their other settings. As a result it has less checks in it.
  656. \*----------------------------------------------------------------------------*/
  657. foreign void:Group_SetPlayer(Group:g,p,bool:s);
  658. global void:Group_SetPlayer(Group:g,p,bool:s)
  659. {
  660. if (_Group_IsValid(g) && 0 <= p < MAX_PLAYERS)
  661. {
  662. GROUP_FIX(g);
  663. //static
  664. // BitArray:n<_MAX_GROUPS_G>;
  665. if (s)
  666. {
  667. if (!_Group_HasPlayer(g, p))
  668. {
  669. // Added to a group they don't already have. Make a new list of
  670. // groups they're in, taking in to account the new groups
  671. // hierarchy and pass that new array about.
  672. broadcastfunc _Group_SetPlayer(p, _Group_SetSome(p, _:g), sizeof (YSI_gTempGroups));
  673. return; //1;
  674. }
  675. }
  676. else
  677. {
  678. if (_Group_HasPlayer(g, p))
  679. {
  680. YSI_gTempGroups = YSI_gGroupPlayers[p];
  681. Bit_Vet(YSI_gTempGroups, _:g);
  682. broadcastfunc _Group_SetPlayer(p, YSI_gTempGroups, sizeof (YSI_gTempGroups));
  683. return; //1;
  684. }
  685. }
  686. }
  687. //return 0;
  688. }
  689. /*----------------------------------------------------------------------------*\
  690. Function:
  691. _Group_FakePlayer
  692. Params:
  693. p - Player who connected.
  694. Bit:g[] - The player's new groups.
  695. s - Size of "g".
  696. Return:
  697. -
  698. Notes:
  699. Pretend the player is in all the groups they won't be in shortly so that
  700. they have a complete blank slate when they connect - the system KNOWS they
  701. are not in some groups and are in others.
  702. Uses an unusual size in "g" to reduce the string length.
  703. \*----------------------------------------------------------------------------*/
  704. static remotefunc void:_Group_FakePlayer(p,Bit:g[sizeof RG@],s)
  705. {
  706. for (new i = 0; i != s; ++i)
  707. {
  708. // Set their current groups to the inverse of what they are now in.
  709. YSI_gGroupPlayers[p][i] = ~g[i];
  710. }
  711. _Group_SetPlayer(p, g, s);
  712. }
  713. //#endinput
  714. /*----------------------------------------------------------------------------*\
  715. Function:
  716. _Group_SetPlayer
  717. Params:
  718. p - Player to set.
  719. Bit:g[bits<_MAX_GROUPS_G>] - The player's new groups.
  720. s - Size of "g".
  721. Return:
  722. -
  723. Notes:
  724. Pass a list of groups that the player is now in or not in. This is a
  725. complete replacement for their existing list of groups, and so multiple
  726. updates can be done at once.
  727. \*----------------------------------------------------------------------------*/
  728. static remotefunc void:_Group_SetPlayer(p, Bit:g[sizeof RG@], s)
  729. {
  730. #pragma unused s
  731. #if !(YSIM_HAS_MASTER && (_YSIM_IS_STUB || _YSIM_IS_CLIENT))
  732. #if _YSIM_IS_CLOUD
  733. if (_YCM@y)
  734. #endif
  735. {
  736. P:2("Group_SetPlayer called: %i, %s, %s, %i", p, Bit_Display(YSI_gGroupPlayers[p]), Bit_Display(g), s);
  737. // http://supertech.csail.mit.edu/papers/debruijn.pdf
  738. static const
  739. scDeBruijn[] =
  740. {
  741. 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
  742. 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
  743. };
  744. new
  745. Bit:cur,
  746. Bit:exor,
  747. Bit:bit,
  748. group;
  749. //sOld = YSI_gGroupPlayers[p];
  750. for (new i = 0; i != sizeof (g); ++i)
  751. {
  752. // Get the difference between the old and new groups.
  753. cur = YSI_gGroupPlayers[p][i];
  754. exor = g[i] ^ cur;
  755. P:7("_Group_SetPlayer: Loop %d %d %d", i, _:cur, _:exor);
  756. // Low-level bit twiddling.
  757. while ((bit = exor & -exor))
  758. {
  759. group = i * cellbits + (scDeBruijn[(_:bit * 0x077CB531) >>> 27]);
  760. P:7("_Group_SetPlayer: Add %d %d %d", p, group, _:(cur & bit));
  761. if (cur & bit)
  762. {
  763. // Used to have this group, now don't.
  764. //printf("=============");
  765. //printf("%d", Iter_Count(GroupPlayers[group]));
  766. Iter_Remove(GroupPlayers[group], p);
  767. //printf("%d", Iter_Count(GroupPlayers[group]));
  768. //printf("=============");
  769. }
  770. else
  771. {
  772. // Didn't have this group, now do.
  773. Iter_Add(GroupPlayers[group], p);
  774. }
  775. exor ^= bit;
  776. }
  777. }
  778. }
  779. #endif
  780. #pragma tabsize 4
  781. //printf("chain");
  782. GROUP_CHAIN?<YSI_g_sNextUpdFunc>(p, YSI_gGroupPlayers[p], g);
  783. // NOW save the new version, after everything else has had a chance to
  784. // update according to the changes.
  785. YSI_gGroupPlayers[p] = g;
  786. }
  787. /*----------------------------------------------------------------------------*\
  788. Function:
  789. Group_SetBalancedInternal
  790. Params:
  791. p - Player to add to the smallest group.
  792. Group:gs[] - An array of possible groups.
  793. c - The number of USED items in the array.
  794. Return:
  795. The group they have been added to.
  796. Notes:
  797. Chains the call with "Group_SetPlayer" to use its hierarchy code.
  798. \*----------------------------------------------------------------------------*/
  799. foreign Group:Group_SetBalancedInternal(p,Group:gs[],c);
  800. global Group:Group_SetBalancedInternal(p,Group:gs[],c)
  801. {
  802. // Find which of the listed groups has the least players in.
  803. //#pragma unused s
  804. new
  805. count = cellmax,
  806. Group:id = INVALID_GROUP;
  807. for (new i = 0; i != c; ++i)
  808. {
  809. // Find the group with the least players.
  810. new
  811. gi = _:gs[i];
  812. if (_Group_IsValid(Group:gi))
  813. {
  814. gi = _:GROUP_TEMP_FIX(Group:gi);
  815. //GROUP_FIX(gi);
  816. new
  817. cc = Iter_Count(GroupPlayers[gi]);
  818. if (Bit_Get(YSI_gGroupPlayers[p], gi))
  819. {
  820. // The player is already in this group - prefer it to others.
  821. --cc;
  822. }
  823. if (cc < count)
  824. {
  825. count = cc;
  826. id = Group:gi;
  827. }
  828. }
  829. }
  830. Group_SetPlayer(id, p, true);
  831. return id;
  832. }
  833. /*----------------------------------------------------------------------------*\
  834. Function:
  835. Group_SetBalanced
  836. Params:
  837. playerid - Player to put in one of a number of groups
  838. {Group, _}:... - Either an array size then array, or a list of groups.
  839. Return:
  840. -
  841. Notes:
  842. Puts a player in whichever of the given groups currently has the least
  843. players.
  844. \*----------------------------------------------------------------------------*/
  845. stock Group:Group_SetBalanced(playerid, {Group, _}:...)
  846. {
  847. if (!(0 < p <= MAX_PLAYERS))
  848. {
  849. return INVALID_GROUP;
  850. }
  851. new
  852. Group:possible[_MAX_GROUPS_G],
  853. count = numargs();
  854. switch (count)
  855. {
  856. case 1, 2:
  857. {
  858. P:W("Group_AddBalanced requires at least 2 groups or an array.");
  859. }
  860. case 3:
  861. {
  862. new
  863. third = getarg(2);
  864. if (third & _:GROUP_MASK)
  865. {
  866. // Two groups.
  867. possible[0] = Group:getarg(1);
  868. possible[1] = Group:third;
  869. return Group_SetBalancedInternal(playerid, possible, 2);
  870. }
  871. else
  872. {
  873. third = min(third, _MAX_GROUPS_G);
  874. // Array of groups.
  875. for (new i = 0; i != third; ++i)
  876. {
  877. possible[i] = getarg(1, i);
  878. }
  879. return Group_SetBalancedInternal(playerid, possible, third);
  880. }
  881. }
  882. default:
  883. {
  884. for (new i = 1; i != count; ++i)
  885. {
  886. possible[i - 1] = getarg(i);
  887. }
  888. return Group_SetBalancedInternal(playerid, possible, count - 1);
  889. }
  890. }
  891. return INVALID_GROUP;
  892. }
  893. /*----------------------------------------------------------------------------*\
  894. Function:
  895. Group_GetPlayer
  896. Params:
  897. Group:g - Group to check.
  898. p - Player to check.
  899. Return:
  900. Is this player in this group?
  901. Notes:
  902. -
  903. \*----------------------------------------------------------------------------*/
  904. foreign bool:Group_GetPlayer(Group:g,p);
  905. global bool:Group_GetPlayer(Group:g,p)
  906. {
  907. P:2("bool:Group_GetPlayer called: %i, %i", _:g, p);
  908. if (_Group_IsValid(g) && 0 <= p < MAX_PLAYERS)
  909. {
  910. GROUP_FIX(g);
  911. return Bit_Get(YSI_gGroupPlayers[p], _:g);
  912. //Bit_Set(YSI_gGroupPlayers[g], p, s, bits<MAX_PLAYERS>);
  913. }
  914. return false;
  915. }
  916. /*----------------------------------------------------------------------------*\
  917. Function:
  918. Params:
  919. Group:g - Group to set the name of.
  920. string:n[] - The new name of the group.
  921. Return:
  922. -
  923. Notes:
  924. Sets the name of a group.
  925. \*----------------------------------------------------------------------------*/
  926. foreign void:Group_SetName(Group:g,string:n[]);
  927. global void:Group_SetName(Group:g,string:n[])
  928. {
  929. P:2("Group_SetName called: %i, \"%s\"", _:g, n);
  930. if (_Group_IsValid(g))
  931. {
  932. GROUP_FIX(g);
  933. if (isnull(n))
  934. {
  935. YSI_gGroupData[_:g][E_GROUP_DATA_NAME][0] = 0;
  936. YSI_gGroupData[_:g][E_GROUP_DATA_HASH] = 0;
  937. }
  938. else
  939. {
  940. strpack(YSI_gGroupData[_:g][E_GROUP_DATA_NAME], n, MAX_GROUP_NAME char);
  941. YSI_gGroupData[_:g][E_GROUP_DATA_HASH] = YHash(n);
  942. }
  943. }
  944. //return 1;
  945. }
  946. /*----------------------------------------------------------------------------*\
  947. Function:
  948. Group_GetName
  949. Params:
  950. Group:g - Group to get the name of.
  951. Return:
  952. string:
  953. Notes:
  954. Gets the name of a group.
  955. \*----------------------------------------------------------------------------*/
  956. foreign string:Group_GetName(Group:g);
  957. global string:Group_GetName(Group:g)
  958. {
  959. P:2("Group_GetName called: %i", _:g);
  960. new
  961. ret[YSI_MAX_STRING];
  962. if (_Group_IsValid(g))
  963. {
  964. //return Bit_Get(YSI_gGroupPlayers[g], p);
  965. //Bit_Set(YSI_gGroupPlayers[g], p, s, bits<MAX_PLAYERS>);
  966. strunpack(ret, YSI_gGroupData[_:GROUP_TEMP_FIX(g)][E_GROUP_DATA_NAME], YSI_MAX_STRING);
  967. }
  968. return ret;
  969. }
  970. /*----------------------------------------------------------------------------*\
  971. Function:
  972. Group_GetID
  973. Params:
  974. string:name[] - Name of a group to get.
  975. Return:
  976. Group: - The ID of the group with this name.
  977. Notes:
  978. -
  979. \*----------------------------------------------------------------------------*/
  980. foreign Group:Group_GetID(string:name[]);
  981. global Group:Group_GetID(string:name[])
  982. {
  983. P:2("Group_GetID called: %s", name);
  984. new
  985. i,
  986. hash = YHash(name);
  987. while (i != _MAX_GROUPS)
  988. {
  989. if (_Group_IsActive(i) && YSI_gGroupData[i][E_GROUP_DATA_HASH] == hash)
  990. {
  991. break;
  992. }
  993. ++i;
  994. }
  995. if (i == _MAX_GROUPS) return INVALID_GROUP;
  996. return Group:i | GROUP_MASK;
  997. }
  998. /*----------------------------------------------------------------------------*\
  999. Function:
  1000. Group_SetGane
  1001. Params:
  1002. Group:g - Group to set for.
  1003. bool:n - Set or not?
  1004. Return:
  1005. -
  1006. Notes:
  1007. I actually can't remember what the "Gang" setting on a group does - I don't
  1008. think it actually does anything in the latest code version!
  1009. \*----------------------------------------------------------------------------*/
  1010. foreign void:Group_SetGang(Group:g,bool:n);
  1011. global void:Group_SetGang(Group:g,bool:n)
  1012. {
  1013. P:2("Group_SetGang called: %i, %i", _:g, n);
  1014. if (_Group_IsValid(g))
  1015. {
  1016. if (n)
  1017. {
  1018. _Group_LetGang(GROUP_TEMP_FIX(g));
  1019. }
  1020. else
  1021. {
  1022. _Group_VetGang(GROUP_TEMP_FIX(g));
  1023. }
  1024. }
  1025. //return 1;
  1026. }
  1027. /*----------------------------------------------------------------------------*\
  1028. Function:
  1029. Group_GetGang
  1030. Params:
  1031. Group:g - Group to get the gang status of.
  1032. Return:
  1033. bool:
  1034. Notes:
  1035. I still don't remember what this once did!
  1036. \*----------------------------------------------------------------------------*/
  1037. foreign bool:Group_GetGang(Group:g);
  1038. global bool:Group_GetGang(Group:g)
  1039. {
  1040. P:2("bool:Group_GetGang called: %i", _:g);
  1041. if (_Group_IsValid(g))
  1042. {
  1043. return _Group_GetGang(GROUP_TEMP_FIX(g));
  1044. }
  1045. return false;
  1046. }
  1047. /*----------------------------------------------------------------------------*\
  1048. Function:
  1049. Group_SetColor
  1050. Group_SetColour
  1051. Params:
  1052. Group:g - The group to set the colour of.
  1053. c - An RGBA colour.
  1054. Return:
  1055. -
  1056. Notes:
  1057. This colour is not actually currently used anywhere.
  1058. \*----------------------------------------------------------------------------*/
  1059. foreign void:Group_SetColour(Group:g,c);
  1060. global void:Group_SetColour(Group:g,c)
  1061. {
  1062. P:2("Group_SetColour called: %i, %i", _:g, c);
  1063. if (_Group_IsValid(g))
  1064. {
  1065. GROUP_FIX(g);
  1066. _Group_SetColor(g, c);
  1067. }
  1068. //return 1;
  1069. }
  1070. /*----------------------------------------------------------------------------*\
  1071. Function:
  1072. Group_GetColor
  1073. Group_GetColour
  1074. Params:
  1075. Group:g - The group to get the colour of.
  1076. Return:
  1077. An RGBA colour.
  1078. Notes:
  1079. This colour is not actually currently used anywhere.
  1080. \*----------------------------------------------------------------------------*/
  1081. foreign Group_GetColour(Group:g);
  1082. global Group_GetColour(Group:g)
  1083. {
  1084. P:2("Group_GetColour called: %i", _:g);
  1085. if (_Group_IsValid(g))
  1086. {
  1087. return _Group_GetColor(GROUP_TEMP_FIX(g));
  1088. //Bit_Set(YSI_gGroupPlayers[g], p, s, bits<MAX_PLAYERS>);
  1089. }
  1090. return 0;
  1091. }
  1092. #define Group_SetColor Group_SetColour
  1093. #define Group_GetColor Group_GetColour
  1094. /*----------------------------------------------------------------------------*\
  1095. Function:
  1096. Group_GetCount
  1097. Params:
  1098. Group:g - The group to get the membership for.
  1099. Return:
  1100. The number of players in the group.
  1101. Notes:
  1102. -
  1103. \*----------------------------------------------------------------------------*/
  1104. foreign Group_GetCount(Group:g);
  1105. global Group_GetCount(Group:g)
  1106. {
  1107. P:2("Group_GetCount called: %i", _:g);
  1108. if (_Group_IsValid(g))
  1109. {
  1110. GROUP_FIX(g);
  1111. return Iter_Count(GroupPlayers[_:g]);
  1112. }
  1113. return 0;
  1114. }
  1115. /*----------------------------------------------------------------------------*\
  1116. Function:
  1117. Group_Create
  1118. Params:
  1119. string:name[] - The optional name of the new group.
  1120. Return:
  1121. The group ID with a tag of "Group:", or "INVALID_GROUP".
  1122. Notes:
  1123. Group_Create - Local function to detect and "NULL"ify empty strings.
  1124. _Group_Create - Global function that does most of the work.
  1125. _Group_CreateChain - Remote function that updates all master scripts with
  1126. the new group's existence.
  1127. \*----------------------------------------------------------------------------*/
  1128. @foreign Group:_Group_Create(string:name[]);
  1129. @global Group:_Group_Create(string:name[])
  1130. {
  1131. P:2("Group:Group_Create called: \"%s\"", name);
  1132. P:2("Group_Create called in %d", _@);
  1133. new
  1134. i;
  1135. if (!isnull(name))
  1136. {
  1137. // Get a group of the same name if it already exists.
  1138. i = _:Group_GetID(name);
  1139. if (i != _:INVALID_GROUP)
  1140. {
  1141. MASTER_ADD<_:GROUP_TEMP_FIX(Group:i)>
  1142. return Group:i;
  1143. }
  1144. }
  1145. i = 0;
  1146. while (i != _MAX_GROUPS && _Group_IsActive(i))
  1147. {
  1148. ++i;
  1149. }
  1150. if (i == _MAX_GROUPS) return INVALID_GROUP;
  1151. if (isnull(name))
  1152. {
  1153. YSI_gGroupData[i][E_GROUP_DATA_NAME][0] = 0;
  1154. YSI_gGroupData[i][E_GROUP_DATA_FLAGS] = e_GROUP_FLAGS_TEMP | e_GROUP_FLAGS_ACTIVE;
  1155. YSI_gGroupData[i][E_GROUP_DATA_HASH] = 0;
  1156. }
  1157. else
  1158. {
  1159. strpack(YSI_gGroupData[i][E_GROUP_DATA_NAME], name, MAX_GROUP_NAME char);
  1160. YSI_gGroupData[i][E_GROUP_DATA_FLAGS] = e_GROUP_FLAGS_ACTIVE;
  1161. if (!(YSI_gGroupData[i][E_GROUP_DATA_HASH] = YHash(name)))
  1162. {
  1163. P:E("Group %d has hash 0.", name);
  1164. }
  1165. }
  1166. MASTER_SET<i>
  1167. ++YSI_g_sGroupCount;
  1168. // Reset the group members iterator.
  1169. //Iter_Clear(GroupPlayers[i]);
  1170. // Set the child groups to only this group - this is in theory recursive,
  1171. // but actually isn't.
  1172. //static const
  1173. // BitArray:scEmpty<_MAX_GROUPS_G>;
  1174. YSI_g_sChildGroups[i] = YSI_g_cEmptyGroups;
  1175. Bit_Let(YSI_g_sChildGroups[i], i);
  1176. //PA_Init(YSI_gGroupPlayers[i]);
  1177. // Add this group to other groups.
  1178. // TODO: CHAIN. Done
  1179. // TODO: Spread data over all other scripts. NO.
  1180. broadcastfunc _Group_CreateChain(Group:i);
  1181. return Group:i | GROUP_MASK;
  1182. }
  1183. static remotefunc void:_Group_CreateChain(Group:g)
  1184. {
  1185. GROUP_CHAIN?<YSI_g_sNextAddFunc>(g);
  1186. }
  1187. stock Group:Group_Create(string:name[] = "")
  1188. {
  1189. if (name[0])
  1190. {
  1191. return _Group_Create(name);
  1192. }
  1193. else
  1194. {
  1195. return _Group_Create(NULL);
  1196. }
  1197. }
  1198. /*----------------------------------------------------------------------------*\
  1199. Function:
  1200. Group_Destroy
  1201. Params:
  1202. Group:group - Group to destroy from the system.
  1203. Return:
  1204. -
  1205. Notes:
  1206. -
  1207. \*----------------------------------------------------------------------------*/
  1208. // Added for the fun of it.
  1209. foreign void:Group_Destroy(Group:group);
  1210. global void:Group_Destroy(Group:group)
  1211. {
  1212. // TODO: Remove this group from all players and all other groups.
  1213. P:2("Group_Destroy called: %i", _:group);
  1214. P:2("Group_Destroy called in %d", _@);
  1215. // You can't destroy the global group.
  1216. if (_Group_IsValid(group) && group != GROUP_GLOBAL)
  1217. {
  1218. GROUP_FIX(group);
  1219. broadcastfunc _Group_Destroy(_:group, Iter_InternalArray(GroupPlayers[_:group]), Iter_InternalSize(GroupPlayers[_:group]));
  1220. YSI_gGroupData[_:group][E_GROUP_DATA_FLAGS] = e_GROUP_FLAGS:0;
  1221. YSI_gGroupData[_:group][E_GROUP_DATA_HASH] = 0;
  1222. Iter_Clear(GroupPlayers[_:group]);
  1223. //return 1;
  1224. }
  1225. //return 0;
  1226. }
  1227. static remotefunc void:_Group_Destroy(g, gp@YSII_Ag[MAX_PLAYERS + 1], s)
  1228. {
  1229. #pragma unused s
  1230. new
  1231. ps = Bit_Slot(g),
  1232. Bit:pm = ~Bit_Mask(g);
  1233. //static
  1234. // BitArray:sOld<_MAX_GROUPS_G>;
  1235. if (YSI_g_sNextUpdFunc)
  1236. {
  1237. // Update all players who were in this group as they may have lost
  1238. // some permissions. This is the simplest update because we don't
  1239. // need to worry about the effect of removing this group on the
  1240. // players' memberships in other groups. Maybe they were added to
  1241. // that other group as a direct result of being added to this group,
  1242. // but maybe they weren't - there's no way to know!
  1243. // Check it! Local parameter iterator!
  1244. foreach (new p : gp)
  1245. {
  1246. // TODO: SOMETHING!
  1247. YSI_gTempGroups = YSI_gGroupPlayers[p];
  1248. // If these parameters were the other way round I could do this:
  1249. //GROUP_CHAIN<YSI_g_sNextUpdFunc>(p, (YSI_gGroupPlayers[p], YSI_gGroupPlayers[p][ps] &= pm), YSI_gGroupPlayers[p]);
  1250. // But they're currently not so I can't.
  1251. GROUP_CHAIN<YSI_g_sNextUpdFunc>(p, YSI_gTempGroups, YSI_gGroupPlayers[p]);
  1252. YSI_gGroupPlayers[p][ps] &= pm;
  1253. }
  1254. }
  1255. else
  1256. {
  1257. foreach (new p : gp)
  1258. {
  1259. // Remove all players from this group.
  1260. YSI_gGroupPlayers[p][ps] &= pm;
  1261. }
  1262. }
  1263. }
  1264. /*----------------------------------------------------------------------------*\
  1265. Function:
  1266. Group@YSII_Ag
  1267. Params:
  1268. Group:group - Group to loop over.
  1269. start - Last value.
  1270. Return:
  1271. The next player.
  1272. Notes:
  1273. Internal implementation of the "Group()" iterator for "foreach". Returns
  1274. all the players in a group one at a time. Now just wraps the "GroupPlayers"
  1275. iterator that is only stored in the GROUP master script.
  1276. \*----------------------------------------------------------------------------*/
  1277. foreign Group@YSII_Ag(Group:group, start);
  1278. global Group@YSII_Ag(Group:group, start)
  1279. {
  1280. return Iter_Next(GroupPlayers[_:GROUP_TEMP_FIX(group)], start);
  1281. }
  1282. /*----------------------------------------------------------------------------*\
  1283. Function:
  1284. _Y_G@C_0
  1285. _Y_G@C_1
  1286. _Y_G@C_2
  1287. _Y_G@C_3
  1288. Params:
  1289. func - Function to call.
  1290. ... - 0, 1, 2, or 3 parameters.
  1291. Return:
  1292. 0 - ALWAYS zero to make "_gchain" work properly.
  1293. Notes:
  1294. Basically function indirection, call a function through a pointer and use
  1295. the compiler to figure out the assembly to generate instead of having a
  1296. run-time loop inside a single instance of this function. Using just one
  1297. macro ("GROUP_CHAIN") one of these four functions are selected and called.
  1298. Adding more is fairly trivial too, the parameters are just:
  1299. #emit PUSH.S <16 + n * 4>
  1300. #emit PUSH.S ...
  1301. #emit PUSH.S 20
  1302. #emit PUSH.S 16
  1303. #emit PUSH.C <n * 4>
  1304. \*----------------------------------------------------------------------------*/
  1305. stock _Y_G@C_0(func)
  1306. {
  1307. #emit PUSH.C 0
  1308. #emit LCTRL 6
  1309. #emit ADD.C 28
  1310. #emit PUSH.pri
  1311. #emit LOAD.S.pri func
  1312. #emit SCTRL 6
  1313. // ALWAYS return 0;
  1314. return 0;
  1315. }
  1316. stock _Y_G@C_1(func, GLOBAL_TAG_TYPES:...)
  1317. {
  1318. #emit PUSH.S 16
  1319. #emit PUSH.C 4
  1320. #emit LCTRL 6
  1321. #emit ADD.C 28
  1322. #emit PUSH.pri
  1323. #emit LOAD.S.pri func
  1324. #emit SCTRL 6
  1325. //#emit RETN
  1326. return 0;
  1327. }
  1328. stock _Y_G@C_2(func, GLOBAL_TAG_TYPES:...)
  1329. {
  1330. #emit PUSH.S 20
  1331. #emit PUSH.S 16
  1332. #emit PUSH.C 8
  1333. #emit LCTRL 6
  1334. #emit ADD.C 28
  1335. #emit PUSH.pri
  1336. #emit LOAD.S.pri func
  1337. #emit SCTRL 6
  1338. //#emit RETN
  1339. return 0;
  1340. }
  1341. stock _Y_G@C_3(func, GLOBAL_TAG_TYPES:...)
  1342. {
  1343. #emit PUSH.S 24
  1344. #emit PUSH.S 20
  1345. #emit PUSH.S 16
  1346. #emit PUSH.C 12
  1347. #emit LCTRL 6
  1348. #emit ADD.C 28
  1349. #emit PUSH.pri
  1350. #emit LOAD.S.pri func
  1351. #emit SCTRL 6
  1352. //#emit RETN
  1353. return 0;
  1354. }
  1355. /*----------------------------------------------------------------------------*\
  1356. Function:
  1357. Group_SetGroup
  1358. Params:
  1359. Group:g - Group to set for.
  1360. el - Element to set.
  1361. bool:s - Set or unset?
  1362. Return:
  1363. -
  1364. Notes:
  1365. IMPORTANT NOTE: Groups are SLIGHTLY different to other systems - if you
  1366. REMOVE a group from another group then players WILL NOT be removed from
  1367. that second group, or any child groups.
  1368. \*----------------------------------------------------------------------------*/
  1369. foreign void:Group_SetGroup(Group:g,Group:el,bool:s);
  1370. global void:Group_SetGroup(Group:g,Group:el,bool:s)
  1371. {
  1372. P:2(#Group_SetGroup " called: %i, %i, %i", _:g, _:el, s);
  1373. // Set wether a group can use this item.
  1374. if (g != el && _Group_IsValid(g) && _Group_IsValid(el))
  1375. {
  1376. GROUP_FIX(g);
  1377. GROUP_FIX(el);
  1378. if (s)
  1379. {
  1380. if (Bit_Get(YSI_g_sChildGroups[_:g], _:el))
  1381. {
  1382. // Child is already part of parent.
  1383. return; //1;
  1384. }
  1385. Bit_Let(YSI_g_sChildGroups[_:g], _:el);
  1386. foreach (new p : GroupPlayers[_:g])
  1387. {
  1388. if (!_Group_HasPlayer(el, p))
  1389. {
  1390. broadcastfunc _Group_SetPlayer(p, _Group_SetSome(p, _:el), bits<_MAX_GROUPS_G>);
  1391. }
  1392. }
  1393. //return 1;
  1394. }
  1395. else
  1396. {
  1397. if (Bit_Get(YSI_g_sChildGroups[_:g], _:el))
  1398. {
  1399. // Child is a part of parent.
  1400. Bit_Vet(YSI_g_sChildGroups[_:g], _:el);
  1401. //return 1;
  1402. }
  1403. // DO NOT REMOVE PLAYERS.
  1404. //return 1;
  1405. }
  1406. }
  1407. //return 0;
  1408. }
  1409. /*----------------------------------------------------------------------------*\
  1410. Function:
  1411. Group_SetGlobalGroup
  1412. Params:
  1413. el - Element to set.
  1414. bool:s - Set or unset?
  1415. Return:
  1416. -
  1417. Notes:
  1418. If "s" is true, then one element is added to the global group. False it is
  1419. removed.
  1420. \*----------------------------------------------------------------------------*/
  1421. foreign void:Group_SetGlobalGroup(Group:el,bool:s);
  1422. global void:Group_SetGlobalGroup(Group:el,bool:s)
  1423. {
  1424. P:2(#Group_SetGlobalGroup " called: %i, %i", _:el, s);
  1425. Group_SetGroup(GROUP_GLOBAL, el, s);
  1426. }
  1427. /*----------------------------------------------------------------------------*\
  1428. Function:
  1429. Group_Get...
  1430. Params:
  1431. Group:g - Group to get from.
  1432. Group:el - Element to get.
  1433. Return:
  1434. bool: Does the group have the element?
  1435. Notes:
  1436. -
  1437. \*----------------------------------------------------------------------------*/
  1438. foreign bool:Group_GetGroup(Group:g,Group:el);
  1439. global bool:Group_GetGroup(Group:g,Group:el)
  1440. {
  1441. P:2(#Group_GetGroup " called: %i, %i", _:g, _:el);
  1442. return (GROUP_MASK <= el <= GROUP_GLOBAL && GROUP_MASK <= g <= GROUP_GLOBAL && Bit_Get(YSI_g_sChildGroups[_:GROUP_TEMP_FIX(g)], _:GROUP_TEMP_FIX(el)));
  1443. }
  1444. /*----------------------------------------------------------------------------*\
  1445. Function:
  1446. Group_GetGlobal...
  1447. Params:
  1448. Group:el - Element to get.
  1449. Return:
  1450. bool: Does the global group have the element?
  1451. Notes:
  1452. -
  1453. \*----------------------------------------------------------------------------*/
  1454. foreign Group_GetGlobalGroup(Group:el);
  1455. global Group_GetGlobalGroup(Group:el)
  1456. {
  1457. P:2(#Group_GetGlobalGroup " called: %i", _:el);
  1458. return Group_GetGroup(GROUP_GLOBAL, el);
  1459. }
  1460. #define _YSIM_RESET_USER
  1461. #include "..\y_master"