y_classes.inc 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  1. /*----------------------------------------------------------------------------*-
  2. ======================================
  3. y_classes - Advanced class selection
  4. ======================================
  5. Description:
  6. Allows greater control over classes so not everyone has every class. Uses
  7. a form of compression for locations.
  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 SA:MP script information include.
  19. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  20. Portions created by the Initial Developer are Copyright (C) 2008
  21. the Initial Developer. All Rights Reserved.
  22. Contributors:
  23. ZeeX, koolk
  24. Thanks:
  25. Peter, Cam - Support.
  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.
  40. Kye/Kalcor - SA:MP.
  41. SA:MP Team past, present and future - SA:MP.
  42. Version:
  43. 0.1
  44. Changelog:
  45. 02/01/08:
  46. First '08 edit - Fixed minus numbers in spawn points.
  47. 18/11/07:
  48. Improved location compression to allow larger areas.
  49. Moved position code to Class_OnPlayerSpawn to reduce overhead.
  50. 10/10/07:
  51. Fixed spawn data problem.
  52. 31/08/07:
  53. Added cheap master system - YSI_SLAVE_CLASSs can't be master.
  54. 05/08/07:
  55. Fixed a few bugs with repeated selection.
  56. 04/08/07:
  57. First version.
  58. Functions:
  59. Public:
  60. Class_AddRemote - Adds a class to the remote master.
  61. Class_Remote - Updates settings remotely.
  62. Core:
  63. Class_Class - Sets up the system.
  64. Class_OnPlayerRequestSpawn - Called when a player requests a spawn.
  65. Class_OnPlayerRequestClass - Called when a player requests a class.
  66. Class_OnPlayerConnect - Called when a player connects.
  67. Stock:
  68. Class_Delete - Removes a class.
  69. Class_SetPlayer - Sets whether or not a player can use a class.
  70. Class_Disable - Disables a class.
  71. Class_Enable - Enables a disabled class.
  72. Class_AddForGroup - Adds a class to the system for only one group.
  73. Class_Add - Adds a class to the system.
  74. Class_AddEx - Adds a class to the system with group selection and setting.
  75. Class_AddWithGroupSet - Adds a class and sets their group on selection.
  76. Class_AllowReselection - Allows or disallows people to return to reselect a class.
  77. Class_RequireSpawnLogin - Require people to login before spawning.
  78. Class_RequireSelectionLogin - Require people to login before selecting.
  79. Class_RequireSelectionReg - Require people to register before selecting.
  80. Class_RequireSpawnReg - Require people to register before spawning.
  81. Static:
  82. Class_AddClass - Adds a class, wrapped by API and remote functions.
  83. Inline:
  84. Class_IsActive - Checks a class is active.
  85. Class_Enabled - Checks a class is enabled.
  86. Class_IsValid - Checks a class is valid.
  87. Class_X - Gets a classes x position.
  88. Class_Y - Gets a classes y position.
  89. Class_Z - Gets a classes z position.
  90. Class_A - Gets a classes angle.
  91. Class_Skin - Gets a classes skin.
  92. API:
  93. -
  94. Callbacks:
  95. -
  96. Definitions:
  97. MAX_CLASSES - Maximum number of classes storeable by the system.
  98. CLASS_LEFT - Flag for last internal class viewed.
  99. CLASS_MIDDLE - Flag for last internal class viewed.
  100. CLASS_RIGHT - Flag for last internal class viewed.
  101. Enums:
  102. e_CLASS_FLAGS - Small data for individual classes.
  103. E_CLASS - Class data structure.
  104. Macros:
  105. -
  106. Tags:
  107. -
  108. Variables:
  109. Global:
  110. -
  111. Static:
  112. YSI_g_sClasses - Data for classes.
  113. YSI_g_sPlayerClass - Player's current classes.
  114. YSI_g_sLeft - Handle for the first internal class.
  115. YSI_g_sMiddle - Handle for the second internal class.
  116. YSI_g_sRight - Handle for the third internal class.
  117. YSI_g_sClassCount - Number of classes stored.
  118. Commands:
  119. -
  120. Compile options:
  121. -
  122. Operators:
  123. -
  124. -*----------------------------------------------------------------------------*/
  125. #include <YSI\internal\y_version>
  126. #include <YSI\y_bit>
  127. #include <YSI\y_debug>
  128. // Simple hookable callbacks.
  129. #define ALS_PREFIX Class
  130. #include <YSI\y_als>
  131. // Only the gamemode can run this.
  132. #if defined FILTERSCRIPT
  133. #define YSIM_C_ENABLE
  134. #define OnPlayerRequestClassEx OnPlayerRequestClassExFS
  135. #define OnPlayerRequestSpawnEx OnPlayerRequestSpawnExFS
  136. #else
  137. #define YSIM_S_ENABLE
  138. #define OnPlayerRequestClassEx OnPlayerRequestClassExGM
  139. #define OnPlayerRequestSpawnEx OnPlayerRequestSpawnExGM
  140. #endif
  141. #include <YSI\y_master>
  142. #if !defined MAX_CLASSES
  143. #define MAX_CLASSES (256)
  144. #endif
  145. #if !defined MAX_CLASS_SPAWN_WEAPONS
  146. #define MAX_CLASS_SPAWN_WEAPONS (13)
  147. #endif
  148. #if !defined WEAPON_ARMOUR
  149. #define WEAPON_ARMOUR (100)
  150. #endif
  151. #define INFINATE_ARMOUR (0x00800000)
  152. #define _CLASS_WEAPON_CODE if((n-w)&0x01)while(w!=n&&s<MAX_CLASS_SPAWN_WEAPONS){cw=getarg(w++);if(cw==WEAPON_ARMOUR)weapons[MAX_CLASS_SPAWN_WEAPONS]=WEAPON_ARMOUR|(100<<8);else if(w==n)printf("*** Internal Error: Insufficient class weapon data.");else weapons[s++]=(cw&0xFF)|(getarg(w++)<<8);}else while(w!=n&&s<MAX_CLASS_SPAWN_WEAPONS){cw=getarg(w++);if(cw==WEAPON_ARMOUR)weapons[MAX_CLASS_SPAWN_WEAPONS]=WEAPON_ARMOUR|(getarg(w++)<<8);else weapons[s++]=(cw&0xFF)|(getarg(w++)<<8);}
  153. #define _GROUP_MAKE_NAME_CLASSES<%0...%1> %0Class%1
  154. #define _GROUP_MAKE_LIMIT_CLASSES MAX_CLASSES
  155. //forward Class_ResolveGroups(class, Group:forgroup, bool:cp);
  156. #include <YSI\y_groups>
  157. #include <YSI\y_playerarray>
  158. #include <YSI\y_iterate>
  159. enum e_CLASS_FLAGS (<<= 1)
  160. {
  161. e_CLASS_FLAGS_SKIN = 0x0000FFFF,
  162. e_CLASS_FLAGS_ACTIVE = 0x01000000,
  163. e_CLASS_FLAGS_ENABLED,
  164. e_CLASS_FLAGS_DEFAULT
  165. }
  166. enum E_CLASS
  167. {
  168. e_CLASS_FLAGS:E_CLASS_FLAGS,
  169. Float:E_CLASS_X,
  170. Float:E_CLASS_Y,
  171. Float:E_CLASS_Z,
  172. Float:E_CLASS_A,
  173. E_CLASS_WEAPONS[MAX_CLASS_SPAWN_WEAPONS + 1],
  174. //#if defined _YSI_SYSTEM_GROUPS
  175. E_CLASS_GROUP,
  176. //#endif
  177. PlayerArray:E_CLASS_PLAYERS<MAX_PLAYERS>
  178. //Bit:E_CLASS_PLAYERS[PLAYER_BIT_ARRAY]
  179. }
  180. enum e_CLASS_OPTION (<<= 1)
  181. {
  182. e_CLASS_OPTION_NORE = 1,
  183. e_CLASS_OPTION_LOGIN_SELECT,
  184. e_CLASS_OPTION_LOGIN_SPAWN,
  185. e_CLASS_OPTION_REG_SELECT,
  186. e_CLASS_OPTION_REG_SPAWN,
  187. e_CLASS_OPTION_HAS_RC_CALLBACK,
  188. e_CLASS_OPTION_HAS_RS_CALLBACK
  189. }
  190. enum e_PLAYER_CLASS (<<= 1)
  191. {
  192. e_PLAYER_CLASS_SKIN = 0x000FFFFF,
  193. e_PLAYER_CLASS_PRESS = 0x00E00000,
  194. e_PLAYER_CLASS_RIGHT = 0x00200000,
  195. e_PLAYER_CLASS_MIDDLE,
  196. e_PLAYER_CLASS_LEFT,
  197. e_PLAYER_CLASS_EVER,
  198. e_PLAYER_CLASS_DENY,
  199. e_PLAYER_CLASS_SPAWNED,
  200. e_PLAYER_CLASS_SELECT,
  201. e_PLAYER_CLASS_RETURN,
  202. e_PLAYER_CLASS_AFTER_RETURN,
  203. e_PLAYER_CLASS_TEMP_SPAWN
  204. }
  205. #define e_PLAYER_CLASS_SPAWN_CHECK (e_PLAYER_CLASS_AFTER_RETURN|e_PLAYER_CLASS_TEMP_SPAWN)
  206. #define CLASS_MOVE_LEFT (e_PLAYER_CLASS:-1)
  207. #define CLASS_MOVE_RIGHT (e_PLAYER_CLASS:1)
  208. static stock
  209. YSI_g_sClasses[MAX_CLASSES][E_CLASS],
  210. e_PLAYER_CLASS:YSI_g_sPlayerClass[MAX_PLAYERS],
  211. YSI_g_sLeft,
  212. YSI_g_sMiddle,
  213. YSI_g_sRight,
  214. YSI_g_sClassCount,
  215. e_CLASS_OPTION:YSI_g_sClassOptions,
  216. YSI_g_sLastRefuse[MAX_PLAYERS];
  217. forward OnPlayerRequestSpawnEx(playerid, classid);
  218. forward OnPlayerRequestClassEx(playerid, classid);
  219. ALS_DATA<>
  220. /*----------------------------------------------------------------------------*-
  221. Function:
  222. Class_IsActive
  223. Params:
  224. classid - Class to check.
  225. Return:
  226. -
  227. Notes:
  228. Checks if a class is currently in use.
  229. -*----------------------------------------------------------------------------*/
  230. #define Class_IsActive(%1) \
  231. (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_ACTIVE)
  232. /*----------------------------------------------------------------------------*-
  233. Function:
  234. Class_Enabled
  235. Params:
  236. classid - Class to check.
  237. Return:
  238. -
  239. Notes:
  240. Checks if a class is currently available for viewing.
  241. -*----------------------------------------------------------------------------*/
  242. #define Class_Enabled(%1) \
  243. (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_ENABLED)
  244. /*----------------------------------------------------------------------------*-
  245. Function:
  246. Class_IsValid
  247. Params:
  248. classid - Class to check.
  249. Return:
  250. -
  251. Notes:
  252. Checks if a number is a valid classid and active.
  253. -*----------------------------------------------------------------------------*/
  254. #define Class_IsValid(%1) \
  255. ((%1) >= 0 && (%1) < MAX_CLASSES && Class_IsActive((%1)))
  256. /*----------------------------------------------------------------------------*-
  257. Function:
  258. Class_X
  259. Params:
  260. classid - Class to get X location for.
  261. Return:
  262. -
  263. Notes:
  264. -
  265. -*----------------------------------------------------------------------------*/
  266. #define Class_X(%1) \
  267. YSI_g_sClasses[(%1)][E_CLASS_X]
  268. //(float(YSI_g_sClasses[(%1)][E_CLASS_XY] >> 16) / 10.0)
  269. /*----------------------------------------------------------------------------*-
  270. Function:
  271. Class_Y
  272. Params:
  273. classid - Class to get Y location for.
  274. Return:
  275. -
  276. Notes:
  277. -
  278. -*----------------------------------------------------------------------------*/
  279. #define Class_Y(%1) \
  280. YSI_g_sClasses[(%1)][E_CLASS_Y]
  281. //(float((YSI_g_sClasses[(%1)][E_CLASS_XY] & 0x7FFF) | ((YSI_g_sClasses[(%1)][E_CLASS_XY] & 0x8000) ? (0xFFFF8000) : (0))) / 10.0)
  282. /*----------------------------------------------------------------------------*-
  283. Function:
  284. Class_Z
  285. Params:
  286. classid - Class to get Z location for.
  287. Return:
  288. -
  289. Notes:
  290. -
  291. -*----------------------------------------------------------------------------*/
  292. #define Class_Z(%1) \
  293. YSI_g_sClasses[(%1)][E_CLASS_Z]
  294. //(float(YSI_g_sClasses[(%1)][E_CLASS_ZA] >> 16) / 10.0)
  295. /*----------------------------------------------------------------------------*-
  296. Function:
  297. Class_A
  298. Params:
  299. classid - Class to get angle for.
  300. Return:
  301. -
  302. Notes:
  303. -
  304. -*----------------------------------------------------------------------------*/
  305. #define Class_A(%1) \
  306. YSI_g_sClasses[(%1)][E_CLASS_A]
  307. //(float((YSI_g_sClasses[(%1)][E_CLASS_ZA] & 0x7FFF) | (YSI_g_sClasses[(%1)][E_CLASS_ZA] & 0x8000) ? (0xFFFF8000) : (0)) / 10.0)
  308. /*----------------------------------------------------------------------------*-
  309. Function:
  310. Class_Skin
  311. Params:
  312. classid - Class to get skin for.
  313. Return:
  314. -
  315. Notes:
  316. -
  317. -*----------------------------------------------------------------------------*/
  318. #define Class_Skin(%1) \
  319. (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_SKIN)
  320. /*----------------------------------------------------------------------------*-
  321. Function:
  322. Class_Class
  323. Params:
  324. -
  325. Return:
  326. -
  327. Notes:
  328. Creates three real player classes so you can scroll correctly with the
  329. direction being detected.
  330. -*----------------------------------------------------------------------------*/
  331. #if defined FILTERSCRIPT
  332. public OnFilterScriptInit()
  333. {
  334. #else
  335. public OnGameModeInit()
  336. {
  337. // This code placement is not generic.
  338. YSI_g_sLeft = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  339. YSI_g_sMiddle = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  340. YSI_g_sRight = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  341. YSI_g_sClassOptions = ((funcidx("OnPlayerRequestClassExGM") == -1) ? (e_CLASS_OPTION:0) : (e_CLASS_OPTION_HAS_RC_CALLBACK)) | ((funcidx("OnPlayerRequestSpawnExGM") == -1) ? (e_CLASS_OPTION:0) : (e_CLASS_OPTION_HAS_RS_CALLBACK));
  342. #endif
  343. ALS_DETECT<PlayerConnect>
  344. //ALS_DETECT<PlayerRequestClass>
  345. //ALS_DETECT<PlayerRequestSpawn>
  346. ALS_DETECT<PlayerSpawn>
  347. ALS_DETECT<PlayerDeath>
  348. CallLocalFunction("Class_OnScriptInit", "");
  349. return 1;
  350. }
  351. #if defined FILTERSCRIPT
  352. #if defined _ALS_OnFilterScriptInit
  353. #undef OnFilterScriptInit
  354. #else
  355. #define _ALS_OnFilterScriptInit
  356. #endif
  357. #define OnFilterScriptInit Class_OnScriptInit
  358. #else
  359. #if defined _ALS_OnGameModeInit
  360. #undef OnGameModeInit
  361. #else
  362. #define _ALS_OnGameModeInit
  363. #endif
  364. #define OnGameModeInit Class_OnScriptInit
  365. #endif
  366. forward Class_OnScriptInit();
  367. /*----------------------------------------------------------------------------*-
  368. Function:
  369. Class_OnPlayerRequestSpawn
  370. Params:
  371. playerid - Player who selected a spawn.
  372. Return:
  373. -
  374. Notes:
  375. Has inbuilt protection for a bug where selections aren't correctly
  376. debounced so you can press shift twice at once which can mess up some
  377. scripts (e.g. the example team selection script). Calls
  378. OnPlayerRequestSpawnEx with an additional class parameter.
  379. -*----------------------------------------------------------------------------*/
  380. stock Class_ResolveGroups(class, Group:forgroup, bool:cp) <YSI_has_groups:n>
  381. {
  382. P:3("Class_AddClass<n>: call Resolve %d %d %d", class, forgroup, cp);
  383. if (!cp) PA_Init(YSI_g_sClasses[class][E_CLASS_PLAYERS], true);
  384. else if (forgroup) {}
  385. //Bit_SetAll(YSI_g_sClasses[class][E_CLASS_PLAYERS], true, bits<MAX_PLAYERS>);
  386. }
  387. stock Class_ResolveGroups(class, Group:forgroup, bool:cp) <>
  388. {
  389. P:3("Class_AddClass<>: call Resolve %d %d %d", class, forgroup, cp);
  390. if (!cp) PA_Init(YSI_g_sClasses[class][E_CLASS_PLAYERS], true);
  391. else if (forgroup) {}
  392. //Bit_SetAll(YSI_g_sClasses[class][E_CLASS_PLAYERS], true, bits<MAX_PLAYERS>);
  393. }
  394. RA:Class_OnPlayerRequestSpawn(playerid)
  395. {
  396. P:2("Class_OnPlayerRequestSpawn called");
  397. if (YSI_g_sClassCount)
  398. {
  399. new
  400. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN;
  401. if (!Class_Enabled(playerclass) || PA!(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid))
  402. {
  403. ALS_CALL<PlayerRequestSpawn>
  404. }
  405. // Don't need this line anymore - it's all done in OnPlayerRequestClass
  406. // OnPlayerSpawn.
  407. //SetSpawnInfo(playerid, NO_TEAM, Class_Skin(playerclass), Class_X(playerclass), Class_Y(playerclass), Class_Z(playerclass), Class_A(playerclass), 0, 0, 0, 0, 0, 0);
  408. new
  409. time = GetTickCount();
  410. if ((time - YSI_g_sLastRefuse[playerid]) >= 1000)
  411. {
  412. CallRemoteFunction("OnPlayerRequestSpawnExFS", "ii", playerid, playerclass);
  413. new
  414. ret = !(YSI_g_sClassOptions & e_CLASS_OPTION_HAS_RS_CALLBACK)|| CallLocalFunction("OnPlayerRequestSpawnExGM", "ii", playerid, playerclass);
  415. P:4("Class_OnPlayerRequestSpawn() return: %d", ret);
  416. if (ret)
  417. {
  418. //#if defined _YSI_SYSTEM_GROUPS
  419. new
  420. Group:newgroup = YSI_g_sClasses[playerclass][E_CLASS_GROUP];
  421. P:4("Class_OnPlayerRequestSpawn() newgroup: %d", newgroup);
  422. if (newgroup != -1) Class_ResolveGroups(playerid, newgroup, true); //Group_AddPlayer(newgroup, playerid);
  423. //#endif
  424. if (ret == 1)
  425. {
  426. //ALS_CALL<PlayerRequestSpawn>
  427. return 1;
  428. }
  429. else if(ret == -1)
  430. {
  431. YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_SKIN;
  432. // The order is VERY important here - this will actually
  433. // call the function further down (directly below in fact).
  434. OnPlayerRequestClass(playerid, YSI_g_sLeft);
  435. }
  436. }
  437. }
  438. YSI_g_sLastRefuse[playerid] = time;
  439. return 0;
  440. }
  441. //ALS_CALL<PlayerRequestSpawn>
  442. return 1;
  443. }
  444. /*#if defined _ALS_OnPlayerRequestSpawn
  445. #undef OnPlayerRequestSpawn
  446. #else
  447. #define _ALS_OnPlayerRequestSpawn
  448. #endif
  449. #define OnPlayerRequestSpawn Class_OnPlayerRequestSpawn
  450. ALS_FORWARD<PlayerRequestSpawn>*/
  451. #if defined _ALS_OnPlayerRequestSpawn
  452. #undef OnPlayerRequestSpawn
  453. #else
  454. #define _ALS_OnPlayerRequestSpawn
  455. #endif
  456. #define OnPlayerRequestSpawn(%0) OnPlayerRequestSpawnEx(%0,classid)
  457. /*----------------------------------------------------------------------------*-
  458. Function:
  459. Class_OnPlayerRequestClass
  460. Params:
  461. playerid - Player who requested a class.
  462. class - Class they requested.
  463. Return:
  464. -
  465. Notes:
  466. The input is one of the three real classes used to detect selected
  467. direction of alteration. Scans for a class the player is allowed to use
  468. and hot swaps it out. Uses SetPlayerSkin AND SetSpawnInfo to combat bugs
  469. with calling this from OnPlayerRequestSpawn (e.g. the example team script).
  470. Calls OnPlayerRequestClassEx with the current internal class not the real
  471. one.
  472. -*----------------------------------------------------------------------------*/
  473. static stock e_PLAYER_CLASS:Class_FindNew(playerid, e_PLAYER_CLASS:playerclass, e_PLAYER_CLASS:dir)
  474. {
  475. if (playerclass >= e_PLAYER_CLASS:YSI_g_sClassCount)
  476. {
  477. playerclass = -dir;
  478. }
  479. new
  480. e_PLAYER_CLASS:old = playerclass % e_PLAYER_CLASS:YSI_g_sClassCount;
  481. do
  482. {
  483. playerclass = (playerclass + dir) % e_PLAYER_CLASS:YSI_g_sClassCount;
  484. //P:4("Class_OnPlayerRequestClass() playerclass: %d", playerclass);
  485. /*if (playerclass < e_PLAYER_CLASS:0)
  486. {
  487. playerclass = e_PLAYER_CLASS:(YSI_g_sClassCount - 1);
  488. }
  489. else if (playerclass >= e_PLAYER_CLASS:YSI_g_sClassCount)
  490. {
  491. playerclass = e_PLAYER_CLASS:0;
  492. }*/
  493. P:4("Class_FindNew: %d %d", playerclass, playerid);
  494. }
  495. while (playerclass != old && (!Class_Enabled(playerclass) || PA!(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid)));
  496. return playerclass;
  497. }
  498. RA:Class_OnPlayerRequestClass(playerid, classid)
  499. {
  500. P:2("Class_OnPlayerRequestClass() start");
  501. //YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_SELECT;
  502. new
  503. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid],
  504. e_PLAYER_CLASS:dir = CLASS_MOVE_RIGHT;
  505. if ((YSI_g_sClassOptions & e_CLASS_OPTION_NORE) && (playerclass & e_PLAYER_CLASS_SPAWNED))
  506. {
  507. //YSI_g_sPlayerClass[playerid] &= ~e_PLAYER_CLASS_AFTER_RETURN;
  508. // People aren't allowed to return to class selection.
  509. SpawnPlayer(playerid);
  510. return 1;
  511. }
  512. // Spawned from returning to class selection but not meant to.
  513. P:3("Class_OnPlayerRequestClass(): Spawn check %d %d", (playerclass & e_PLAYER_CLASS_SPAWN_CHECK), e_PLAYER_CLASS_SPAWN_CHECK);
  514. if ((playerclass & e_PLAYER_CLASS_SPAWN_CHECK) == e_PLAYER_CLASS_SPAWN_CHECK)
  515. {
  516. YSI_g_sPlayerClass[playerid] &= ~e_PLAYER_CLASS_SPAWN_CHECK;
  517. // People aren't allowed to return to class selection.
  518. playerclass &= e_PLAYER_CLASS_SKIN;
  519. SetSpawnInfo(playerid, NO_TEAM, Class_Skin(e_PLAYER_CLASS:playerclass), Class_X(e_PLAYER_CLASS:playerclass), Class_Y(e_PLAYER_CLASS:playerclass), Class_Z(e_PLAYER_CLASS:playerclass), Class_A(e_PLAYER_CLASS:playerclass), 0, 0, 0, 0, 0, 0);
  520. SpawnPlayer(playerid);
  521. return 1;
  522. }
  523. if (playerclass & e_PLAYER_CLASS_DENY)
  524. {
  525. TogglePlayerControllable(playerid, false);
  526. TogglePlayerSpectating(playerid, true);
  527. return 0;
  528. }
  529. switch (playerclass & e_PLAYER_CLASS_PRESS)
  530. {
  531. case e_PLAYER_CLASS_RIGHT:
  532. {
  533. if (classid == YSI_g_sMiddle)
  534. {
  535. // Went from the right to the middle - that's a move left.
  536. dir = CLASS_MOVE_LEFT;
  537. }
  538. }
  539. case e_PLAYER_CLASS_MIDDLE:
  540. {
  541. if (classid == YSI_g_sLeft)
  542. {
  543. // Went from the middle to the left - that's a move left.
  544. dir = CLASS_MOVE_LEFT;
  545. }
  546. }
  547. default:
  548. {
  549. if (classid == YSI_g_sRight)
  550. {
  551. // Went from the left to the right - that's a wrap move left.
  552. dir = CLASS_MOVE_LEFT;
  553. }
  554. }
  555. }
  556. if (classid == YSI_g_sMiddle) YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_MIDDLE | (playerclass & (e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_EVER));
  557. else if (classid == YSI_g_sLeft) YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_LEFT | (playerclass & (e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_EVER));
  558. else if (classid == YSI_g_sRight) YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_RIGHT | (playerclass & (e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_EVER));
  559. if (playerclass & (e_PLAYER_CLASS_SPAWNED | e_PLAYER_CLASS_RETURN))
  560. {
  561. playerclass = e_PLAYER_CLASS_SKIN;
  562. }
  563. else
  564. {
  565. playerclass &= e_PLAYER_CLASS_SKIN;
  566. }
  567. if (!YSI_g_sClassCount)
  568. {
  569. SetSpawnInfo(playerid, NO_TEAM, 0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  570. SetPlayerSkin(playerid, 0);
  571. P:1("*** Internal Error! No YSI classes found");
  572. }
  573. else
  574. {
  575. // Find the next available skin for this player. I'm still not sure how
  576. // this handles the case where you can't use any skin. I'll have to
  577. // look in to that.
  578. playerclass = Class_FindNew(playerid, playerclass, dir);
  579. P:4("Class_OnPlayerRequestClass() selected: %d", playerclass);
  580. }
  581. return Class_Goto(playerid, _:playerclass);
  582. //ALS_CALL_EX<PlayerRequestClass, ret>
  583. }
  584. /*#if defined _ALS_OnPlayerRequestClass
  585. #undef OnPlayerRequestClass
  586. #else
  587. #define _ALS_OnPlayerRequestClass
  588. #endif
  589. #define OnPlayerRequestClass Class_OnPlayerRequestClass
  590. ALS_FORWARD<PlayerRequestClass>*/
  591. #if defined _ALS_OnPlayerRequestClass
  592. #undef OnPlayerRequestClass
  593. #else
  594. #define _ALS_OnPlayerRequestClass
  595. #endif
  596. #define OnPlayerRequestClass OnPlayerRequestClassEx
  597. RF:Class_Goto[ii](playerid, playerclass)
  598. {
  599. // This now sets the REAL spawn information, including spawn location.
  600. // 0.2 code
  601. //SetSpawnInfo(playerid, NO_TEAM, Class_Skin(e_PLAYER_CLASS:playerclass), Class_X(e_PLAYER_CLASS:playerclass), Class_Y(e_PLAYER_CLASS:playerclass), Class_Z(e_PLAYER_CLASS:playerclass), Class_A(e_PLAYER_CLASS:playerclass), weapon1 & 0xFF, weapon1 >>> 8, weapon2 & 0xFF, weapon2 >>> 8, weapon3 & 0xFF, weapon3 >>> 8);
  602. // 0.3 code
  603. SetSpawnInfo(playerid, NO_TEAM, Class_Skin(e_PLAYER_CLASS:playerclass), Class_X(e_PLAYER_CLASS:playerclass), Class_Y(e_PLAYER_CLASS:playerclass), Class_Z(e_PLAYER_CLASS:playerclass), Class_A(e_PLAYER_CLASS:playerclass), 0, 0, 0, 0, 0, 0);
  604. SetPlayerSkin(playerid, Class_Skin(e_PLAYER_CLASS:playerclass));
  605. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & (e_PLAYER_CLASS_PRESS | e_PLAYER_CLASS_EVER | e_PLAYER_CLASS_AFTER_RETURN)) | e_PLAYER_CLASS:playerclass | e_PLAYER_CLASS_SELECT;
  606. // Save the last viewed class so that we know which direction the person
  607. // went next time OnPlayerRequestClass is called.
  608. P:2("Class_Goto() end");
  609. // Call the OnPlayerRequestClassEx functions.
  610. CallRemoteFunction("OnPlayerRequestClassExFS", "ii", playerid, playerclass);
  611. return !(YSI_g_sClassOptions & e_CLASS_OPTION_HAS_RC_CALLBACK) || CallLocalFunction("OnPlayerRequestClassExGM", "ii", playerid, playerclass);
  612. }
  613. /*----------------------------------------------------------------------------*-
  614. Function:
  615. Class_OnPlayerConnect
  616. Params:
  617. playerid - Player who joined.
  618. Return:
  619. -
  620. Notes:
  621. Resets the player's current class.
  622. -*----------------------------------------------------------------------------*/
  623. RA:Class_OnPlayerConnect(playerid)
  624. {
  625. P:3("Class_OnPlayerConnect called");
  626. YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_SKIN;
  627. ALS_CALL<PlayerConnect>
  628. }
  629. #if defined _ALS_OnPlayerConnect
  630. #undef OnPlayerConnect
  631. #else
  632. #define _ALS_OnPlayerConnect
  633. #endif
  634. #define OnPlayerConnect Class_OnPlayerConnect
  635. ALS_FORWARD<PlayerConnect>
  636. RF@v:Class_ReturnToSelection[i](playerid)
  637. {
  638. // All of these lines are required to correctly send the player back to the
  639. // class selection, unfortunately they also cause nasty side effects.
  640. //TogglePlayerControllable(playerid, true);
  641. /*if (YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_EVER)
  642. {
  643. //TogglePlayerControllable(playerid, true);
  644. //YSI_g_sPlayerClass[playerid] &= e_PLAYER_CLASS_SPAWNED;
  645. //SetPlayerHealth(playerid, 0.0);
  646. }*/
  647. ForceClassSelection(playerid);
  648. //YSI_g_sPlayerClass[playerid] &= ~(e_PLAYER_CLASS_DENY | e_PLAYER_CLASS_SPAWNED);
  649. //TogglePlayerControllable(playerid, true);
  650. //YSI_g_sPlayerClass[playerid] &= e_PLAYER_CLASS_SPAWNED;
  651. //ForceClassSelection(playerid);
  652. TogglePlayerSpectating(playerid, false);
  653. SetPlayerHealth(playerid, 0.0);
  654. TogglePlayerControllable(playerid, false);
  655. //YSI_g_sPlayerClass[playerid] = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_PRESS | e_PLAYER_CLASS_SKIN;
  656. Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS_SKIN, CLASS_MOVE_RIGHT));
  657. YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_RETURN | e_PLAYER_CLASS_AFTER_RETURN;
  658. }
  659. RF@v:Class_DenySelection[i](playerid)
  660. {
  661. //SpawnPlayer(playerid);
  662. //TogglePlayerControllable(playerid, false);
  663. TogglePlayerSpectating(playerid, true);
  664. SetSpawnInfo(playerid, 0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0);
  665. SpawnPlayer(playerid);
  666. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] | e_PLAYER_CLASS_DENY) & ~e_PLAYER_CLASS_SELECT;
  667. }
  668. /*----------------------------------------------------------------------------*-
  669. Function:
  670. Class_OnPlayerDeath
  671. Params:
  672. playerid - Player who dies.
  673. reason - The reason they died.
  674. Return:
  675. -
  676. Notes:
  677. Catches and hides fake deaths caused by the spawn system.
  678. -*----------------------------------------------------------------------------*/
  679. RA:Class_OnPlayerDeath(playerid, killerid, reason)
  680. {
  681. P:2("Class_OnPlayerDeath called");
  682. //new
  683. // time = GetTickCount();
  684. if ((YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SPAWN_CHECK) == e_PLAYER_CLASS_SPAWN_CHECK)// || (time - YSI_g_sLastRefuse[playerid]) < 200)
  685. {
  686. P:3("Class_OnPlayerDeath: Inner");
  687. new
  688. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN;
  689. // Fake death to get the ForceClassSelection out the system.
  690. SetSpawnInfo(playerid, NO_TEAM, Class_Skin(e_PLAYER_CLASS:playerclass), Class_X(e_PLAYER_CLASS:playerclass), Class_Y(e_PLAYER_CLASS:playerclass), Class_Z(e_PLAYER_CLASS:playerclass), Class_A(e_PLAYER_CLASS:playerclass), 0, 0, 0, 0, 0, 0);
  691. //SpawnPlayer(playerid);
  692. //SetPlayerHealth(playerid, 100.0);
  693. //YSI_g_sPlayerClass[playerid] &= ~e_PLAYER_CLASS_SPAWN_CHECK;
  694. //YSI_g_sLastRefuse[playerid] = time;
  695. return 1;
  696. }
  697. ALS_CALL<PlayerDeath>
  698. }
  699. #if defined _ALS_OnPlayerDeath
  700. #undef OnPlayerDeath
  701. #else
  702. #define _ALS_OnPlayerDeath
  703. #endif
  704. #define OnPlayerDeath Class_OnPlayerDeath
  705. ALS_FORWARD<PlayerDeath>
  706. /*----------------------------------------------------------------------------*-
  707. Function:
  708. Class_OnPlayerSpawn
  709. Params:
  710. playerid - Player who spawned.
  711. Return:
  712. -
  713. Notes:
  714. Sets a player's position based on skin.
  715. -*----------------------------------------------------------------------------*/
  716. RA:Class_OnPlayerSpawn(playerid)
  717. {
  718. P:2("Class_OnPlayerSpawn called: %d %d", YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_AFTER_RETURN, e_PLAYER_CLASS_AFTER_RETURN);
  719. if (YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_AFTER_RETURN)
  720. {
  721. // Fake spawn.
  722. //SetPlayer
  723. YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_TEMP_SPAWN;
  724. return 1;
  725. }
  726. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] | e_PLAYER_CLASS_SPAWNED | e_PLAYER_CLASS_EVER) & ~e_PLAYER_CLASS_SELECT;
  727. new
  728. playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN,
  729. weapon;
  730. for (new i = 0; i != MAX_CLASS_SPAWN_WEAPONS; ++i)
  731. {
  732. weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][i];
  733. //if (weapon == WEAPON_ARMOUR) SetPlayerArmour(playerid, 100.0);
  734. if (weapon)
  735. {
  736. GivePlayerWeapon(playerid, weapon & 0xFF, weapon >>> 8);
  737. }
  738. else
  739. {
  740. break;
  741. }
  742. }
  743. weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][MAX_CLASS_SPAWN_WEAPONS];
  744. P:5("Class_OnPlayerSpawn: Armour %d %d %d", weapon, weapon & 0xFF, WEAPON_ARMOUR);
  745. if ((weapon & 0xFF) == WEAPON_ARMOUR)
  746. {
  747. weapon >>>= 8;
  748. if (weapon == 0x00800000)
  749. {
  750. // INFINITY
  751. SetPlayerArmour(playerid, Float:0x7F800000);
  752. }
  753. else
  754. {
  755. SetPlayerArmour(playerid, weapon);
  756. }
  757. }
  758. ALS_CALL<PlayerSpawn>
  759. }
  760. #if defined _ALS_OnPlayerSpawn
  761. #undef OnPlayerSpawn
  762. #else
  763. #define _ALS_OnPlayerSpawn
  764. #endif
  765. #define OnPlayerSpawn Class_OnPlayerSpawn
  766. ALS_FORWARD<PlayerSpawn>
  767. /*----------------------------------------------------------------------------*-
  768. Function:
  769. Class_Add
  770. Params:
  771. skin - Skin of the class.
  772. Float:x - X spawn location.
  773. Float:y - Y spawn location.
  774. Float:z - Z spawn location.
  775. Float:a - A spawn location.
  776. ... - Spawn weapons and ammo (weapon then ammo)
  777. Return:
  778. -
  779. Notes:
  780. Pretty much AddPlayerClass but allows greater control over the classes.
  781. Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons. This is one of
  782. the few API functions which is not entirely remote. This is because it has
  783. variable parameters which is need to collect in to a single array to pass to
  784. the remote function.
  785. -*----------------------------------------------------------------------------*/
  786. stock Class_Add(skin, Float:x, Float:y, Float:z, Float:a, ...)
  787. {
  788. new
  789. n = numargs(),
  790. w = 5,
  791. s,
  792. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  793. cw;
  794. // Should have an odd number of parameters
  795. //if (!(num & 0x01)) --num;
  796. // Armour now has a parameter - how much armour to give them!
  797. _CLASS_WEAPON_CODE
  798. /*if (num & 0x01)
  799. {
  800. // Odd number of parameters - good.
  801. while (weap != num && slot < MAX_CLASS_SPAWN_WEAPONS)
  802. {
  803. cw = getarg(weap++);
  804. if (cw == WEAPON_ARMOUR)
  805. {
  806. // Default armour value.
  807. weapons[MAX_CLASS_SPAWN_WEAPONS] = WEAPON_ARMOUR | (getarg(weap++) << 8);
  808. }
  809. else
  810. {
  811. // Store both weapon data and ammo data in one variable.
  812. weapons[slot++] = (cw & 0xFF) | (getarg(weap++) << 8);
  813. }
  814. }
  815. }
  816. else
  817. {
  818. // Got an even number of parameters - look for the odd one being armour.
  819. while (weap != num && slot < MAX_CLASS_SPAWN_WEAPONS)
  820. {
  821. cw = getarg(weap++);
  822. if (cw == WEAPON_ARMOUR)
  823. {
  824. // Default armour value.
  825. weapons[MAX_CLASS_SPAWN_WEAPONS] = WEAPON_ARMOUR | (100 << 8);
  826. }
  827. else if (weap == num)
  828. {
  829. // Something went wrong - there was no armour but was also not
  830. // enough data for the other weapons.
  831. printf("*** Internal Error: Insufficient class weapon data.");
  832. }
  833. else
  834. {
  835. // Store both weapon data and ammo data in one variable.
  836. weapons[slot++] = (cw & 0xFF) | (getarg(weap++) << 8);
  837. }
  838. }
  839. }*/
  840. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, -1, -1);
  841. }
  842. /*----------------------------------------------------------------------------*-
  843. Function:
  844. Class_AddEx
  845. Params:
  846. forgroup - Group that can use the skin.
  847. setgroup - Group to add the player to on selection.
  848. skin - Skin of the class.
  849. Float:x - X spawn location.
  850. Float:y - Y spawn location.
  851. Float:z - Z spawn location.
  852. Float:a - A spawn location.
  853. ... - Spawn weapons and ammo (weapon then ammo)
  854. Return:
  855. -
  856. Notes:
  857. Pretty much AddPlayerClass but allows greater control over the classes.
  858. Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons.
  859. -*----------------------------------------------------------------------------*/
  860. stock Class_AddEx(Group:forgroup, Group:setgroup, skin, Float:x, Float:y, Float:z, Float:a, ...)
  861. {
  862. new
  863. n = numargs(),
  864. w = 7,
  865. s,
  866. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  867. cw;
  868. _CLASS_WEAPON_CODE
  869. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, forgroup, asgroup);
  870. }
  871. /*----------------------------------------------------------------------------*-
  872. Function:
  873. Class_AddClass
  874. Params:
  875. skin - Skin of the class.
  876. Float:x - X spawn location.
  877. Float:y - Y spawn location.
  878. Float:z - Z spawn location.
  879. Float:a - A spawn location.
  880. weapons[] - Array of spawn weapon data.
  881. count - Number of weapons added.
  882. forgroup - Group that can use the class.
  883. asgroup - Group to assign people to with this class.
  884. Return:
  885. -
  886. Notes:
  887. Does the hard work.
  888. -*----------------------------------------------------------------------------*/
  889. RF@pc:Class_AddClass[iffffaiii](s,Float:x,Float:y,Float:z,Float:a,w[],c,Group:f,Group:g)<s,x,y,z,a,w,c,f,g>
  890. {
  891. new
  892. i;
  893. while (i < MAX_CLASSES)
  894. {
  895. if (!Class_IsActive(i)) break;
  896. i++;
  897. }
  898. if (i == MAX_CLASSES) return -1;
  899. YSI_g_sClasses[i][E_CLASS_FLAGS] = e_CLASS_FLAGS_ACTIVE | e_CLASS_FLAGS_ENABLED | e_CLASS_FLAGS:s;
  900. YSI_g_sClasses[i][E_CLASS_X] = x;
  901. YSI_g_sClasses[i][E_CLASS_Y] = y;
  902. YSI_g_sClasses[i][E_CLASS_Z] = z;
  903. YSI_g_sClasses[i][E_CLASS_A] = a;
  904. new
  905. j;
  906. // This may be better with a memcpy.
  907. while (j < c)
  908. {
  909. P:5("Class_AddClass: weapon %d %d %d", j, c, w[j]);
  910. YSI_g_sClasses[i][E_CLASS_WEAPONS][j] = w[j];
  911. ++j;
  912. }
  913. //Bit_SetAll(YSI_g_sClasses[class][E_CLASS_PLAYERS], false, bits<MAX_PLAYERS>);
  914. PA_Init(YSI_g_sClasses[i][E_CLASS_PLAYERS]);
  915. Class_ResolveGroups(i, f, false);
  916. YSI_g_sClasses[i][E_CLASS_GROUP] = g;
  917. //YSI_g_sClasses[i][E_CLASS_WEAPONS][MAX_CLASS_SPAWN_WEAPONS] = w[MAX_CLASS_SPAWN_WEAPONS];
  918. YSI_g_sClassCount++;
  919. //setproperty(0, "LReqClass", i);
  920. //#if !defined YSI_CLASS_INVERT
  921. // Bit_SetAll(YSI_g_sClasses[i][E_CLASS_PLAYERS], true, bits<MAX_PLAYERS>);
  922. //#endif
  923. return i;
  924. }
  925. /*----------------------------------------------------------------------------*-
  926. Function:
  927. Class_AddForGroup
  928. Params:
  929. group - Group to allow to use the class.
  930. skin - Skin of the class.
  931. Float:x - X spawn location.
  932. Float:y - Y spawn location.
  933. Float:z - Z spawn location.
  934. Float:a - A spawn location.
  935. ... - Weapon data.
  936. Return:
  937. -
  938. Notes:
  939. Adds a class only people in the specified group can use.
  940. -*----------------------------------------------------------------------------*/
  941. //#if defined _YSI_SYSTEM_GROUPS
  942. stock Class_AddForGroup(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
  943. {
  944. new
  945. n = numargs(),
  946. w = 6,
  947. s,
  948. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  949. cw;
  950. _CLASS_WEAPON_CODE
  951. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, group, -1);
  952. }
  953. /*#else
  954. #define Class_AddForGroup(%1,%2) \
  955. Class_Add(%2)
  956. #endif*/
  957. /*----------------------------------------------------------------------------*-
  958. Function:
  959. Class_AddWithGroupSet
  960. Params:
  961. group - Group to make players who use this group.
  962. skin - Skin of the class.
  963. Float:x - X spawn location.
  964. Float:y - Y spawn location.
  965. Float:z - Z spawn location.
  966. Float:a - A spawn location.
  967. ... - Spawn weapons.
  968. Return:
  969. -
  970. Notes:
  971. Adds a class which puts you in the specified group when selected.
  972. -*----------------------------------------------------------------------------*/
  973. //#if defined _YSI_SYSTEM_GROUPS
  974. stock Class_AddWithGroupSet(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
  975. {
  976. new
  977. n = numargs(),
  978. w = 6,
  979. s,
  980. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  981. cw;
  982. _CLASS_WEAPON_CODE
  983. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, -1, group);
  984. }
  985. /*#else
  986. #define Class_AddWithGroupSet(%1,%2) \
  987. Class_Add(%2)
  988. #endif*/
  989. /*----------------------------------------------------------------------------*-
  990. Function:
  991. Class_Enable
  992. Params:
  993. classid - Class to re-enable.
  994. Return:
  995. -
  996. Notes:
  997. Reallow use of this class.
  998. -*----------------------------------------------------------------------------*/
  999. RF@v:Class_Enable[i](classid)
  1000. {
  1001. if (Class_IsValid(classid)) YSI_g_sClasses[classid][E_CLASS_FLAGS] |= e_CLASS_FLAGS_ENABLED;
  1002. }
  1003. /*----------------------------------------------------------------------------*-
  1004. Function:
  1005. Class_Disable
  1006. Params:
  1007. classid - Class to disable.
  1008. Return:
  1009. -
  1010. Notes:
  1011. Stop people being able to use this class.
  1012. -*----------------------------------------------------------------------------*/
  1013. RF@v:Class_Disable[i](classid)
  1014. {
  1015. if (Class_IsValid(classid))
  1016. {
  1017. YSI_g_sClasses[classid][E_CLASS_FLAGS] &= ~e_CLASS_FLAGS_ENABLED;
  1018. foreach (Player, playerid)
  1019. {
  1020. new
  1021. e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[playerid];
  1022. if (curclass & e_PLAYER_CLASS_SELECT)
  1023. {
  1024. if (e_PLAYER_CLASS:classid == curclass & e_PLAYER_CLASS_SKIN) Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS:classid, CLASS_MOVE_RIGHT));
  1025. }
  1026. }
  1027. }
  1028. }
  1029. /*----------------------------------------------------------------------------*-
  1030. Function:
  1031. Class_Remote
  1032. Params:
  1033. allow - Wether or not to allow changing class.
  1034. Return:
  1035. -
  1036. Notes:
  1037. Sets wether or not people can change class after first spawning.
  1038. -*----------------------------------------------------------------------------*/
  1039. RF@v:Class_AllowReselection[i](allow)
  1040. {
  1041. if (allow) YSI_g_sClassOptions &= ~e_CLASS_OPTION_NORE;
  1042. else YSI_g_sClassOptions |= e_CLASS_OPTION_NORE;
  1043. }
  1044. /*----------------------------------------------------------------------------*-
  1045. Function:
  1046. Class_Delete
  1047. Params:
  1048. classid - Class to delete.
  1049. Return:
  1050. -
  1051. Notes:
  1052. Completely removes a class from the system.
  1053. -*----------------------------------------------------------------------------*/
  1054. RF@v:Class_Delete[i](classid)
  1055. {
  1056. if (Class_IsValid(classid))
  1057. {
  1058. YSI_g_sClasses[classid][E_CLASS_FLAGS] = e_CLASS_FLAGS:0;
  1059. foreach (Player, playerid)
  1060. {
  1061. new
  1062. e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[playerid];
  1063. P:4("Class_Delete: %d %d %d", playerid, curclass, e_PLAYER_CLASS_SELECT);
  1064. if (curclass & e_PLAYER_CLASS_SELECT)
  1065. {
  1066. if (e_PLAYER_CLASS:classid == curclass & e_PLAYER_CLASS_SKIN) Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS:classid, CLASS_MOVE_RIGHT));
  1067. }
  1068. }
  1069. }
  1070. }
  1071. /*----------------------------------------------------------------------------*-
  1072. Function:
  1073. Class_SetPlayer
  1074. Params:
  1075. classid - Class to set permissions for.
  1076. playerid - Player to set for.
  1077. set - Whether or not they can use this class.
  1078. Return:
  1079. -
  1080. Notes:
  1081. -
  1082. -*----------------------------------------------------------------------------*/
  1083. RF@pv:Class_SetPlayer[iii](cl,pid,bool:s)<cl,pid,s>
  1084. {
  1085. P:5("Class_SetPlayer %d %d %d", cl, pid, s);
  1086. if (Class_IsValid(cl) && 0 <= pid < MAX_PLAYERS)
  1087. {
  1088. if (s) PA+(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
  1089. else
  1090. {
  1091. PA-(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
  1092. new
  1093. e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[pid];
  1094. if (curclass & e_PLAYER_CLASS_SELECT)
  1095. {
  1096. P:1("WARNING");
  1097. if (e_PLAYER_CLASS:cl == curclass & e_PLAYER_CLASS_SKIN) Class_Goto(pid, Class_FindNew(pid, e_PLAYER_CLASS:cl, CLASS_MOVE_RIGHT));
  1098. }
  1099. }
  1100. }
  1101. }
  1102. /*----------------------------------------------------------------------------*-
  1103. Function:
  1104. Class_GetPlayer
  1105. Params:
  1106. classid - Class to set permissions for.
  1107. playerid - Player to set for.
  1108. Return:
  1109. -
  1110. Notes:
  1111. -
  1112. -*----------------------------------------------------------------------------*/
  1113. RF@t:bool:Class_GetPlayer[ii](cl,pid)
  1114. {
  1115. if (Class_IsValid(cl) && 0 <= pid < MAX_PLAYERS)
  1116. {
  1117. return PA=(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
  1118. }
  1119. return false;
  1120. }
  1121. /*----------------------------------------------------------------------------*-
  1122. Function:
  1123. Class_RequireSelectionLogin
  1124. Params:
  1125. allow - Wether or not people must login.
  1126. Return:
  1127. -
  1128. Notes:
  1129. Don't let registered people select a class till they log in.
  1130. -*----------------------------------------------------------------------------*/
  1131. RF@v:Class_RequireSelectionLogin[i](allow)
  1132. {
  1133. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_LOGIN_SELECT;
  1134. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_LOGIN_SELECT;
  1135. }
  1136. /*----------------------------------------------------------------------------*-
  1137. Function:
  1138. Class_RequireSpawnLogin
  1139. Params:
  1140. allow - Wether or not people must login.
  1141. Return:
  1142. -
  1143. Notes:
  1144. Don't let registered people spawn till they log in.
  1145. -*----------------------------------------------------------------------------*/
  1146. RF@v:Class_RequireSpawnLogin[i](allow)
  1147. {
  1148. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_LOGIN_SPAWN;
  1149. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_LOGIN_SPAWN;
  1150. }
  1151. /*----------------------------------------------------------------------------*-
  1152. Function:
  1153. Class_RequireSelectionReg
  1154. Params:
  1155. allow - Wether or not people must register.
  1156. Return:
  1157. -
  1158. Notes:
  1159. Don't let people select a class till they register.
  1160. -*----------------------------------------------------------------------------*/
  1161. RF@v:Class_RequireSelectionReg[i](allow)
  1162. {
  1163. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_REG_SELECT;
  1164. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_REG_SELECT;
  1165. }
  1166. #define Class_RequireSelectionRegistration Class_RequireSelectionReg
  1167. /*----------------------------------------------------------------------------*-
  1168. Function:
  1169. Class_RequireSpawnReg
  1170. Params:
  1171. allow - Wether or not people must register.
  1172. Return:
  1173. -
  1174. Notes:
  1175. Don't let people spawn till they register.
  1176. -*----------------------------------------------------------------------------*/
  1177. RF@v:Class_RequireSpawnReg[i](allow)
  1178. {
  1179. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_REG_SPAWN;
  1180. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_REG_SPAWN;
  1181. }
  1182. #define Class_RequireSpawnRegistration Class_RequireSpawnReg
  1183. // Clean up - there's no way to do this like in the master system as people can
  1184. // use any arbitrary string here, not just a restricted set of numbers.
  1185. #undef ALS_PREFIX
  1186. #define YSI_GROUPS_LAST 22
  1187. #include <YSI\internal\y_grouprevert>