y_classes 3.inc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  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 YSI classes 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. 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 "internal\y_version"
  126. #include "y_bit"
  127. #include "y_debug"
  128. #define YSIM_U_DISABLE
  129. #include "y_master"
  130. #include "y_iterate"
  131. #include "y_hooks"
  132. #if !defined MAX_CLASSES
  133. #define MAX_CLASSES (256)
  134. #endif
  135. #if !defined MAX_CLASS_SPAWN_WEAPONS
  136. #define MAX_CLASS_SPAWN_WEAPONS (13)
  137. #endif
  138. #if !defined WEAPON_ARMOUR
  139. #define WEAPON_ARMOUR (100)
  140. #endif
  141. #define OnPlayerRequestClassEx(%0) OnPlayerRequestClassEx_(%0)if(!YSI_gOPRCE)return 0;else
  142. #define OnPlayerRequestSpawnEx(%0) OnPlayerRequestSpawnEx_(%0)if(!YSI_gOPRSE)return 0;else
  143. #define INFINATE_ARMOUR (0x00800000)
  144. #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)P:E(": 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);}
  145. #define _GROUP_MAKE_NAME_CLASSES<%0...%1> %0Class%1
  146. #define _GROUP_MAKE_LIMIT_CLASSES MAX_CLASSES
  147. //forward Class_ResolveGroups(class, Group:forgroup, bool:cp);
  148. #include "y_groups"
  149. #include "y_playerarray"
  150. #include "y_iterate"
  151. enum e_CLASS_FLAGS (<<= 1)
  152. {
  153. e_CLASS_FLAGS_SKIN = 0x0000FFFF,
  154. e_CLASS_FLAGS_ENABLED = 0x00010000,
  155. e_CLASS_FLAGS_ACTIVE
  156. }
  157. enum E_CLASS
  158. {
  159. e_CLASS_FLAGS:E_CLASS_FLAGS,
  160. Float:E_CLASS_X,
  161. Float:E_CLASS_Y,
  162. Float:E_CLASS_Z,
  163. Float:E_CLASS_A,
  164. E_CLASS_WEAPONS[MAX_CLASS_SPAWN_WEAPONS + 1],
  165. Group:E_CLASS_GROUP,
  166. PlayerArray:E_CLASS_PLAYERS<MAX_PLAYERS>
  167. }
  168. enum e_PLAYER_CLASS (<<= 1)
  169. {
  170. e_PLAYER_CLASS_SKIN = 0x000FFFFF,
  171. e_PLAYER_CLASS_PRESS = 0x00E00000,
  172. e_PLAYER_CLASS_RIGHT = 0x00200000,
  173. e_PLAYER_CLASS_MIDDLE,
  174. e_PLAYER_CLASS_LEFT,
  175. e_PLAYER_CLASS_NO_RESEL, // Can't reselect a class.
  176. e_PLAYER_CLASS_IS_SPAWNED,
  177. e_PLAYER_CLASS_DENIED, // Can't spawn just yet.
  178. //e_PLAYER_CLASS_FIRST_DEATH,
  179. e_PLAYER_CLASS_NOT_FIRST, // Already seen one class this time.
  180. e_PLAYER_CLASS_ALLOW_ONE, // Allowed to reselect once.
  181. e_PLAYER_CLASS_HAS_EVER_SPAWNED // Has ever spawned.
  182. }
  183. enum e_CLASS_SETTINGS (<<= 1)
  184. {
  185. e_CLASS_SETTING_NORE
  186. }
  187. #define CLASS_MOVE_LEFT (e_PLAYER_CLASS:-1)
  188. #define CLASS_MOVE_RIGHT (e_PLAYER_CLASS:1)
  189. static stock
  190. YSI_g_sClasses[MAX_CLASSES][E_CLASS],
  191. e_PLAYER_CLASS:YSI_g_sPlayerClass[MAX_PLAYERS],
  192. YSI_g_sLeft,
  193. YSI_g_sMiddle,
  194. YSI_g_sRight,
  195. e_CLASS_SETTINGS:YSI_g_sSettings,
  196. YSI_g_sClassCount;
  197. /*----------------------------------------------------------------------------*\
  198. Function:
  199. Class_IsValid
  200. Params:
  201. classid - Class to check if valid.
  202. Return:
  203. -
  204. Notes:
  205. -
  206. \*----------------------------------------------------------------------------*/
  207. #define Class_IsValid(%1) (0<=(%1)<MAX_CLASSES&&Class_IsActive(%1))
  208. /*----------------------------------------------------------------------------*\
  209. Function:
  210. Class_IsValid
  211. Params:
  212. classid - Class to check if active.
  213. Return:
  214. -
  215. Notes:
  216. -
  217. \*----------------------------------------------------------------------------*/
  218. #define Class_IsActive(%1) (YSI_g_sClasses[(%1)][E_CLASS_FLAGS]&e_CLASS_FLAGS_ACTIVE)
  219. /*----------------------------------------------------------------------------*\
  220. Function:
  221. Class_Enabled
  222. Params:
  223. classid - Class to check.
  224. Return:
  225. -
  226. Notes:
  227. -
  228. \*----------------------------------------------------------------------------*/
  229. #define Class_Enabled(%1) (YSI_g_sClasses[(%1)][E_CLASS_FLAGS]&e_CLASS_FLAGS_ENABLED)
  230. /*----------------------------------------------------------------------------*\
  231. Function:
  232. Class_X
  233. Params:
  234. classid - Class to get X location for.
  235. Return:
  236. -
  237. Notes:
  238. -
  239. \*----------------------------------------------------------------------------*/
  240. #define Class_X(%1) YSI_g_sClasses[(%1)][E_CLASS_X]
  241. /*----------------------------------------------------------------------------*\
  242. Function:
  243. Class_Y
  244. Params:
  245. classid - Class to get Y location for.
  246. Return:
  247. -
  248. Notes:
  249. -
  250. \*----------------------------------------------------------------------------*/
  251. #define Class_Y(%1) YSI_g_sClasses[(%1)][E_CLASS_Y]
  252. /*----------------------------------------------------------------------------*\
  253. Function:
  254. Class_Z
  255. Params:
  256. classid - Class to get Z location for.
  257. Return:
  258. -
  259. Notes:
  260. -
  261. \*----------------------------------------------------------------------------*/
  262. #define Class_Z(%1) YSI_g_sClasses[(%1)][E_CLASS_Z]
  263. /*----------------------------------------------------------------------------*\
  264. Function:
  265. Class_A
  266. Params:
  267. classid - Class to get angle for.
  268. Return:
  269. -
  270. Notes:
  271. -
  272. \*----------------------------------------------------------------------------*/
  273. #define Class_A(%1) YSI_g_sClasses[(%1)][E_CLASS_A]
  274. /*----------------------------------------------------------------------------*\
  275. Function:
  276. Class_Skin
  277. Params:
  278. classid - Class to get skin for.
  279. Return:
  280. -
  281. Notes:
  282. -
  283. \*----------------------------------------------------------------------------*/
  284. #define Class_Skin(%1) (YSI_g_sClasses[(%1)][E_CLASS_FLAGS]&e_CLASS_FLAGS_SKIN)
  285. /*----------------------------------------------------------------------------*\
  286. Function:
  287. Class_Class
  288. Params:
  289. -
  290. Return:
  291. -
  292. Notes:
  293. Creates three real player classes so you can scroll correctly with the
  294. direction being detected.
  295. \*----------------------------------------------------------------------------*/
  296. hook OnScriptInit()
  297. {
  298. #if !_YSIM_IS_CLIENT
  299. if (!YSI_FILTERSCRIPT)
  300. {
  301. // This code placement is not generic.
  302. YSI_g_sLeft = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  303. YSI_g_sMiddle = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  304. YSI_g_sRight = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  305. //YSI_g_sClassOptions = ((funcidx("OnPlayerRequestClassEx_") == -1) ? (e_CLASS_OPTION:0) : (e_CLASS_OPTION_HAS_RC_CALLBACK)) | ((funcidx("OnPlayerRequestSpawnEx_") == -1) ? (e_CLASS_OPTION:0) : (e_CLASS_OPTION_HAS_RS_CALLBACK));
  306. #if !defined YSI_NO_MASTER
  307. // Steal the master system.
  308. _Master_Get(#_YCM, true);
  309. #if _YSIM_IS_CLOUD
  310. // Set to uninitialised.
  311. state _YCM:u;
  312. #endif
  313. CallRemoteFunction(#_YCM, "");
  314. #if _YSIM_IS_CLOUD
  315. // Fully master.
  316. state _YCM:y;
  317. #endif
  318. #endif
  319. }
  320. #endif
  321. return 1;
  322. }
  323. /*----------------------------------------------------------------------------*\
  324. Function:
  325. Class_OnPlayerRequestClass
  326. Params:
  327. playerid - Player who requested a class.
  328. class - Class they requested.
  329. Return:
  330. -
  331. Notes:
  332. The input is one of the three real classes used to detect selected
  333. direction of alteration. Scans for a class the player is allowed to use
  334. and hot swaps it out. Uses SetPlayerSkin AND SetSpawnInfo to combat bugs
  335. with calling this from OnPlayerRequestSpawn (e.g. the example team script).
  336. Calls OnPlayerRequestClassEx with the current internal class not the real
  337. one.
  338. \*----------------------------------------------------------------------------*/
  339. static stock e_PLAYER_CLASS:Class_FindNew(playerid, e_PLAYER_CLASS:playerclass, e_PLAYER_CLASS:dir)
  340. {
  341. P:4("e_PLAYER_CLASS:Class_FindNew called: %i, %i, %i", playerid, _:playerclass, _:dir);
  342. if (playerclass >= e_PLAYER_CLASS:YSI_g_sClassCount)
  343. {
  344. playerclass = -dir;
  345. }
  346. new
  347. e_PLAYER_CLASS:old = playerclass % e_PLAYER_CLASS:YSI_g_sClassCount;
  348. do
  349. {
  350. playerclass = (playerclass + dir) % e_PLAYER_CLASS:YSI_g_sClassCount;
  351. P:4("Class_FindNew: %d %d", playerclass, playerid);
  352. }
  353. while (playerclass != old && !(Class_Enabled(playerclass) && PA_Get(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid)));
  354. return playerclass;
  355. }
  356. forward _Class_DoSpawn(playerid);
  357. public _Class_DoSpawn(playerid)
  358. {
  359. // So that they don't briefly see the class selection screen.
  360. TogglePlayerSpectating(playerid, false);
  361. SpawnPlayer(playerid);
  362. printf("3) Hi");
  363. }
  364. mhook OnPlayerRequestClass(playerid, classid)
  365. {
  366. SetPlayerHealth(playerid, 100.0);
  367. SetPlayerSpecialAction(playerid, 0);
  368. P:2("hook OnPlayerRequestClass called: %d, %d", playerid, classid);
  369. new
  370. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid];
  371. // Default to previous settings always.
  372. printf("1) %d %d %d", YSI_g_sPlayerClass[playerid], (e_PLAYER_CLASS_ALLOW_ONE | e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL), (e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL));
  373. if (YSI_g_sPlayerClass[playerid] & (e_PLAYER_CLASS_ALLOW_ONE | e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL) == (e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL))
  374. {
  375. printf("2) %d %d %d", YSI_g_sPlayerClass[playerid], (e_PLAYER_CLASS_ALLOW_ONE | e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL), (e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL));
  376. playerclass &= e_PLAYER_CLASS_SKIN;
  377. 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);
  378. SetPlayerSkin(playerid, Class_Skin(e_PLAYER_CLASS:playerclass));
  379. //printf("hmm...");
  380. //TogglePlayerSpectating(playerid, true);
  381. SetTimerEx("_Class_DoSpawn", 5, 0, "i", playerid);
  382. //SpawnPlayer(playerid);
  383. //SetPlayerHealth(playerid, 0.0);
  384. TogglePlayerSpectating(playerid, true);
  385. return -1;
  386. }
  387. new
  388. e_PLAYER_CLASS:dir = CLASS_MOVE_RIGHT;
  389. // Spawned from returning to class selection but not meant to.
  390. P:5("Class_OnPlayerRequestClass(): Spawn check %d %d", (playerclass & e_PLAYER_CLASS_SPAWN_CHECK), e_PLAYER_CLASS_SPAWN_CHECK);
  391. switch (playerclass & e_PLAYER_CLASS_PRESS)
  392. {
  393. case e_PLAYER_CLASS_RIGHT:
  394. {
  395. if (classid == YSI_g_sMiddle)
  396. {
  397. // Went from the right to the middle - that's a move left.
  398. dir = CLASS_MOVE_LEFT;
  399. }
  400. }
  401. case e_PLAYER_CLASS_MIDDLE:
  402. {
  403. if (classid == YSI_g_sLeft)
  404. {
  405. // Went from the middle to the left - that's a move left.
  406. dir = CLASS_MOVE_LEFT;
  407. }
  408. }
  409. default:
  410. {
  411. if (classid == YSI_g_sRight)
  412. {
  413. // Went from the left to the right - that's a wrap move left.
  414. dir = CLASS_MOVE_LEFT;
  415. }
  416. }
  417. }
  418. if (classid == YSI_g_sMiddle)
  419. {
  420. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & ~e_PLAYER_CLASS_PRESS) | e_PLAYER_CLASS_MIDDLE | e_PLAYER_CLASS_NOT_FIRST; // | playerclass;
  421. }
  422. else if (classid == YSI_g_sLeft)
  423. {
  424. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & ~e_PLAYER_CLASS_PRESS) | e_PLAYER_CLASS_LEFT | e_PLAYER_CLASS_NOT_FIRST; // | playerclass;
  425. }
  426. else if (classid == YSI_g_sRight)
  427. {
  428. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & ~e_PLAYER_CLASS_PRESS) | e_PLAYER_CLASS_RIGHT | e_PLAYER_CLASS_NOT_FIRST; // | playerclass;
  429. }
  430. if (playerclass & e_PLAYER_CLASS_NOT_FIRST)
  431. {
  432. playerclass &= e_PLAYER_CLASS_SKIN;
  433. // Is the first time the spawn has been re-called.
  434. }
  435. else
  436. {
  437. // So that we get the same skin to begin with when returning.
  438. playerclass = (playerclass & e_PLAYER_CLASS_SKIN) - dir;
  439. }
  440. if (YSI_g_sClassCount)
  441. {
  442. // Find the next available skin for this player. I'm still not sure how
  443. // this handles the case where you can't use any skin. I'll have to
  444. // look in to that.
  445. playerclass = Class_FindNew(playerid, playerclass, dir);
  446. P:5("Class_OnPlayerRequestClass() selected: %d", playerclass);
  447. return Class_Goto(playerid, _:playerclass);
  448. }
  449. //Class_ResumeRefresh(playerid);
  450. //YSI_g_sClassOptions &= ~(e_CLASS_OPTION_REFRESH_PAUSE | e_CLASS_OPTION_PAUSED);
  451. //ALS_CALL_EX<PlayerRequestClass, ret>
  452. SetSpawnInfo(playerid, NO_TEAM, 0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  453. SetPlayerSkin(playerid, 0);
  454. P:E("No YSI classes found");
  455. return 1;
  456. }
  457. foreign Class_Goto(playerid, playerclass);
  458. global Class_Goto(playerid, playerclass)
  459. {
  460. P:2("Class_Goto called: %i, %i", playerid, playerclass);
  461. // This now sets the REAL spawn information, including spawn location.
  462. // 0.2 code
  463. //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);
  464. // 0.3 code
  465. 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);
  466. SetPlayerSkin(playerid, Class_Skin(e_PLAYER_CLASS:playerclass));
  467. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & ~e_PLAYER_CLASS_SKIN) | e_PLAYER_CLASS:playerclass;
  468. // Save the last viewed class so that we know which direction the person
  469. // went next time OnPlayerRequestClass is called.
  470. P:2("Class_Goto() end");
  471. // Call the OnPlayerRequestClassEx functions.
  472. /*YSI_gOPRCE = false;
  473. CallRemoteFunction("OnPlayerRequestClassEx_", "ii", playerid, playerclass);
  474. if (YSI_g_sClassOptions & e_CLASS_OPTION_HAS_RC_CALLBACK)
  475. {
  476. YSI_gOPRCE = true;
  477. CallLocalFunction("OnPlayerRequestClassEx_", "ii", playerid, playerclass);
  478. }*/
  479. return 1;
  480. }
  481. /*----------------------------------------------------------------------------*\
  482. Function:
  483. Class_OnPlayerSpawn
  484. Params:
  485. playerid - Player who spawned.
  486. Return:
  487. -
  488. Notes:
  489. Sets a player's position based on skin.
  490. \*----------------------------------------------------------------------------*/
  491. mhook OnPlayerSpawn(playerid)
  492. {
  493. P:2("Class_OnPlayerSpawn called: %d", playerid);
  494. //P:2("Class_OnPlayerSpawn called: %d %d", YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_AFTER_RETURN, e_PLAYER_CLASS_AFTER_RETURN);
  495. new
  496. playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN,
  497. weapon;
  498. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & ~(e_PLAYER_CLASS_NOT_FIRST | e_PLAYER_CLASS_ALLOW_ONE)) | e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_IS_SPAWNED;
  499. for (new i = 0; i != MAX_CLASS_SPAWN_WEAPONS; ++i)
  500. {
  501. weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][i];
  502. //if (weapon == WEAPON_ARMOUR) SetPlayerArmour(playerid, 100.0);
  503. if (weapon)
  504. {
  505. GivePlayerWeapon(playerid, weapon & 0xFF, weapon >>> 8);
  506. }
  507. else
  508. {
  509. break;
  510. }
  511. }
  512. weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][MAX_CLASS_SPAWN_WEAPONS];
  513. P:5("Class_OnPlayerSpawn: Armour %d %d %d", weapon, weapon & 0xFF, WEAPON_ARMOUR);
  514. if ((weapon & 0xFF) == WEAPON_ARMOUR)
  515. {
  516. weapon >>>= 8;
  517. if (weapon == 0x00800000)
  518. {
  519. // INFINITY
  520. SetPlayerArmour(playerid, Float:0x7F800000);
  521. }
  522. else
  523. {
  524. SetPlayerArmour(playerid, weapon);
  525. }
  526. }
  527. return 1;
  528. }
  529. mhook OnPlayerConnect(playerid)
  530. {
  531. P:2("Classes_OnPlayerConnect called");
  532. YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS:0;
  533. TogglePlayerSpectating(playerid, false);
  534. return 1;
  535. }
  536. mhook OnPlayerDeath(playerid, killerid, reason)
  537. {
  538. P:2("Classes_OnPlayerDeath called");
  539. // TogglePlayerSpectating(playerid, false);
  540. // if (YSI_g_sPlayerClass[playerid] & (e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL | e_PLAYER_CLASS_FIRST_DEATH) == (e_PLAYER_CLASS_HAS_EVER_SPAWNED | e_PLAYER_CLASS_NO_RESEL))
  541. // {
  542. // //YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_FIRST_DEATH;
  543. // SpawnPlayer(playerid);
  544. // //SetTimerEx("_Class_DoSpawn", 2500, 0, "i", playerid);
  545. // SetPlayerHealth(playerid, 100.0);
  546. // return -1;
  547. // }
  548. YSI_g_sPlayerClass[playerid] &= ~e_PLAYER_CLASS_IS_SPAWNED;
  549. return 1;
  550. }
  551. mhook OnPlayerRequestSpawn(playerid)
  552. {
  553. P:2("Classes_OnPlayerRequestSpawn called");
  554. return 1; //!(YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_DENIED);
  555. }
  556. mhook OnPlayerDisconnect(playerid, reason)
  557. {
  558. P:2("Classes_OnPlayerDisconnect called");
  559. TogglePlayerSpectating(playerid, true);
  560. return 1; //!(YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_DENIED);
  561. }
  562. /*----------------------------------------------------------------------------*\
  563. Function:
  564. Class_Add
  565. Params:
  566. skin - Skin of the class.
  567. Float:x - X spawn location.
  568. Float:y - Y spawn location.
  569. Float:z - Z spawn location.
  570. Float:a - A spawn location.
  571. ... - Spawn weapons and ammo (weapon then ammo)
  572. Return:
  573. -
  574. Notes:
  575. Pretty much AddPlayerClass but allows greater control over the classes.
  576. Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons. This is one of
  577. the few API functions which is not entirely remote. This is because it has
  578. variable parameters which is need to collect in to a single array to pass to
  579. the remote function.
  580. \*----------------------------------------------------------------------------*/
  581. stock Class_Add(skin, Float:x, Float:y, Float:z, Float:a, ...)
  582. {
  583. P:3("Class_Add called: %i, %i, %i, %i, %i, %i (+%i)", skin, x, y, z, a, numargs() - 5);
  584. new
  585. n = numargs(),
  586. w = 5,
  587. s,
  588. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  589. cw;
  590. _CLASS_WEAPON_CODE
  591. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, Group:-1, Group:-1);
  592. }
  593. /*----------------------------------------------------------------------------*\
  594. Function:
  595. Class_AddEx
  596. Params:
  597. forgroup - Group that can use the skin.
  598. setgroup - Group to add the player to on selection.
  599. skin - Skin of the class.
  600. Float:x - X spawn location.
  601. Float:y - Y spawn location.
  602. Float:z - Z spawn location.
  603. Float:a - A spawn location.
  604. ... - Spawn weapons and ammo (weapon then ammo)
  605. Return:
  606. -
  607. Notes:
  608. Pretty much AddPlayerClass but allows greater control over the classes.
  609. Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons.
  610. \*----------------------------------------------------------------------------*/
  611. stock Class_AddEx(Group:forgroup, Group:setgroup, skin, Float:x, Float:y, Float:z, Float:a, ...)
  612. {
  613. P:3("Class_AddEx called: %i, %i, %i, %f, %f, %f, %f (+%i)", _:forgroup, _:setgroup, skin, x, y, z, a, numargs() - 7);
  614. new
  615. n = numargs(),
  616. w = 7,
  617. s,
  618. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  619. cw;
  620. _CLASS_WEAPON_CODE
  621. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, forgroup, setgroup);
  622. }
  623. /*----------------------------------------------------------------------------*\
  624. Function:
  625. Class_AddForGroup
  626. Params:
  627. group - Group to allow to use the class.
  628. skin - Skin of the class.
  629. Float:x - X spawn location.
  630. Float:y - Y spawn location.
  631. Float:z - Z spawn location.
  632. Float:a - A spawn location.
  633. ... - Weapon data.
  634. Return:
  635. -
  636. Notes:
  637. Adds a class only people in the specified group can use.
  638. \*----------------------------------------------------------------------------*/
  639. stock Class_AddForGroup(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
  640. {
  641. P:3("Class_AddForGroup called: %i, %i, %f, %f, %f, %f (+%i)", _:group, skin, x, y, z, a, numargs() - 6);
  642. new
  643. n = numargs(),
  644. w = 6,
  645. s,
  646. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  647. cw;
  648. _CLASS_WEAPON_CODE
  649. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, group, Group:-1);
  650. }
  651. /*----------------------------------------------------------------------------*\
  652. Function:
  653. Class_AddWithGroupSet
  654. Params:
  655. group - Group to make players who use this group.
  656. skin - Skin of the class.
  657. Float:x - X spawn location.
  658. Float:y - Y spawn location.
  659. Float:z - Z spawn location.
  660. Float:a - A spawn location.
  661. ... - Spawn weapons.
  662. Return:
  663. -
  664. Notes:
  665. Adds a class which puts you in the specified group when selected.
  666. \*----------------------------------------------------------------------------*/
  667. stock Class_AddWithGroupSet(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
  668. {
  669. P:3("Class_AddWithGroupSet called: %i, %i, %f, %f, %f, %f (+%i)", _:group, skin, x, y, z, a, numargs() - 6);
  670. new
  671. n = numargs(),
  672. w = 6,
  673. s,
  674. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  675. cw;
  676. _CLASS_WEAPON_CODE
  677. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, Group:-1, group);
  678. }
  679. /*----------------------------------------------------------------------------*\
  680. Function:
  681. Class_AddClass
  682. Params:
  683. skin - Skin of the class.
  684. Float:x - X spawn location.
  685. Float:y - Y spawn location.
  686. Float:z - Z spawn location.
  687. Float:a - A spawn location.
  688. weapons[] - Array of spawn weapon data.
  689. count - Number of weapons added.
  690. forgroup - Group that can use the class.
  691. asgroup - Group to assign people to with this class.
  692. Return:
  693. -
  694. Notes:
  695. Does the hard work. This took a long time to get working correctly with the
  696. new master system, infact getting just this one function to compile took a
  697. major re-working of the macros to reduce the length of intermediate stages.
  698. \*----------------------------------------------------------------------------*/
  699. foreign Class_AddClass(s,Float:x,Float:y,Float:z,Float:a,w[],c,Group:f,Group:g);
  700. global Class_AddClass(s,Float:x,Float:y,Float:z,Float:a,w[],c,Group:f,Group:g)
  701. {
  702. P:2("Class_AddClass called: %i, %f, %f, %f, %f, %a, %i, %i, %i", s, x, y, z, a, w, c, _:f, _:g);
  703. new
  704. i;
  705. while (i < MAX_CLASSES)
  706. {
  707. if (!Class_IsActive(i)) break;
  708. i++;
  709. }
  710. if (i == MAX_CLASSES) return -1;
  711. YSI_g_sClasses[i][E_CLASS_FLAGS] = e_CLASS_FLAGS_ACTIVE | e_CLASS_FLAGS_ENABLED | e_CLASS_FLAGS:s;
  712. YSI_g_sClasses[i][E_CLASS_X] = x;
  713. YSI_g_sClasses[i][E_CLASS_Y] = y;
  714. YSI_g_sClasses[i][E_CLASS_Z] = z;
  715. YSI_g_sClasses[i][E_CLASS_A] = a;
  716. new
  717. j;
  718. // This may be better with a memcpy.
  719. while (j < c)
  720. {
  721. P:5("Class_AddClass: weapon %d %d %d", j, c, w[j]);
  722. YSI_g_sClasses[i][E_CLASS_WEAPONS][j] = w[j];
  723. ++j;
  724. }
  725. PA_FastInit(YSI_g_sClasses[i][E_CLASS_PLAYERS]);
  726. //Class_ResolveGroups(i, f, false);
  727. YSI_g_sClasses[i][E_CLASS_GROUP] = g;
  728. YSI_g_sClassCount++;
  729. return i;
  730. }
  731. /*----------------------------------------------------------------------------*\
  732. Function:
  733. Class_Delete
  734. Params:
  735. classid - Class to delete.
  736. Return:
  737. -
  738. Notes:
  739. Completely removes a class from the system.
  740. \*----------------------------------------------------------------------------*/
  741. foreign Class_Delete(classid);
  742. global Class_Delete(classid)
  743. {
  744. // P:2("Class_Delete called: %i", classid);
  745. // if (Class_IsValid(classid))
  746. // {
  747. // YSI_g_sClasses[classid][E_CLASS_FLAGS] = e_CLASS_FLAGS:0;
  748. // foreach (new playerid : Player)
  749. // {
  750. // new
  751. // e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[playerid];
  752. // P:4("Class_Delete: %d %d %d", playerid, curclass, e_PLAYER_CLASS_SELECT);
  753. // if (curclass & e_PLAYER_CLASS_SELECT)
  754. // {
  755. // if (e_PLAYER_CLASS:classid == curclass & e_PLAYER_CLASS_SKIN) Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS:classid, CLASS_MOVE_RIGHT));
  756. // }
  757. // }
  758. // }
  759. return 1;
  760. }
  761. /*----------------------------------------------------------------------------*\
  762. Function:
  763. Class_SetPlayer
  764. Params:
  765. classid - Class to set permissions for.
  766. playerid - Player to set for.
  767. set - Whether or not they can use this class.
  768. Return:
  769. -
  770. Notes:
  771. -
  772. \*----------------------------------------------------------------------------*/
  773. foreign Class_SetPlayer(cl, pid, bool:s);
  774. global Class_SetPlayer(cl, pid, bool:s)
  775. {
  776. return PA_Set(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid, s);
  777. }
  778. /*----------------------------------------------------------------------------*\
  779. Function:
  780. Class_GetPlayer
  781. Params:
  782. classid - Class to set permissions for.
  783. playerid - Player to set for.
  784. Return:
  785. -
  786. Notes:
  787. -
  788. \*----------------------------------------------------------------------------*/
  789. foreign bool:Class_GetPlayer(cl,pid);
  790. global bool:Class_GetPlayer(cl,pid)
  791. {
  792. return PA_Get(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
  793. }
  794. /*----------------------------------------------------------------------------*\
  795. Function:
  796. Class_Remote
  797. Params:
  798. allow - Wether or not to allow changing class.
  799. Return:
  800. -
  801. Notes:
  802. Sets wether or not people can change class after first spawning.
  803. \*----------------------------------------------------------------------------*/
  804. stock Class_AllowReselection(allow, playerid = INVALID_PLAYER_ID)
  805. {
  806. return _Class_AllowReselection(allow, playerid);
  807. }
  808. foreign _Class_AllowReselection(allow, playerid);
  809. global _Class_AllowReselection(allow, playerid)
  810. {
  811. P:2("Class_AllowReselection called: %i, %i", allow, playerid);
  812. if (allow)
  813. {
  814. if (playerid == INVALID_PLAYER_ID)
  815. {
  816. YSI_g_sSettings &= ~e_CLASS_SETTING_NORE;
  817. foreach (new i : Player)
  818. {
  819. YSI_g_sPlayerClass[i] &= ~e_PLAYER_CLASS_NO_RESEL;
  820. }
  821. }
  822. else
  823. {
  824. YSI_g_sPlayerClass[playerid] &= ~e_PLAYER_CLASS_NO_RESEL;
  825. }
  826. return 1;
  827. }
  828. else
  829. {
  830. if (playerid == INVALID_PLAYER_ID)
  831. {
  832. YSI_g_sSettings |= e_CLASS_SETTING_NORE;
  833. foreach (new i : Player)
  834. {
  835. YSI_g_sPlayerClass[i] |= e_PLAYER_CLASS_NO_RESEL;
  836. }
  837. }
  838. else
  839. {
  840. YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_NO_RESEL;
  841. }
  842. // ForceClassSelection(playerid);
  843. return 0;
  844. }
  845. }
  846. //#pragma deprecate Class_DenySelection
  847. foreign Class_DenySelection(playerid);
  848. global Class_DenySelection(playerid)
  849. {
  850. TogglePlayerSpectating(playerid, true);
  851. //return Class_
  852. if (YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_IS_SPAWNED)
  853. {
  854. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & ~e_PLAYER_CLASS_IS_SPAWNED) | e_PLAYER_CLASS_DENIED;
  855. }
  856. else
  857. {
  858. YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_DENIED;
  859. }
  860. TogglePlayerControllable(playerid, false);
  861. SetSpawnInfo(playerid, 0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0);
  862. SpawnPlayer(playerid);
  863. return 1;
  864. }
  865. foreign Class_ReturnToSelection(playerid);
  866. global Class_ReturnToSelection(playerid)
  867. {
  868. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] & ~e_PLAYER_CLASS_DENIED) | e_PLAYER_CLASS_ALLOW_ONE;
  869. if (YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_IS_SPAWNED)
  870. {
  871. ForceClassSelection(playerid);
  872. }//
  873. SetPlayerHealth(playerid, 0.0);
  874. TogglePlayerSpectating(playerid, true);
  875. TogglePlayerSpectating(playerid, false);
  876. // else
  877. // {
  878. // //ForceClassSelection(playerid);
  879. // //SetPlayerHealth(playerid, 0.0);
  880. // TogglePlayerSpectating(playerid, false);
  881. // //TogglePlayerControllable(playerid, false);
  882. // }
  883. return 1;
  884. }
  885. foreign Class_DisableSelection();
  886. global Class_DisableSelection()
  887. {
  888. return 1;
  889. }
  890. //#define YSI_SET_LAST_GROUP 22
  891. #include "internal\y_grouprevert"