1
0

y_classes - Copy.inc 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428
  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_ACTIVE = 0x01000000,
  155. e_CLASS_FLAGS_ENABLED,
  156. e_CLASS_FLAGS_DEFAULT
  157. }
  158. enum E_CLASS
  159. {
  160. e_CLASS_FLAGS:E_CLASS_FLAGS,
  161. Float:E_CLASS_X,
  162. Float:E_CLASS_Y,
  163. Float:E_CLASS_Z,
  164. Float:E_CLASS_A,
  165. E_CLASS_WEAPONS[MAX_CLASS_SPAWN_WEAPONS + 1],
  166. //#if defined _YSI_SYSTEM_GROUPS
  167. Group:E_CLASS_GROUP,
  168. //#endif
  169. PlayerArray:E_CLASS_PLAYERS<MAX_PLAYERS>
  170. //Bit:E_CLASS_PLAYERS[PLAYER_BIT_ARRAY]
  171. }
  172. enum e_CLASS_OPTION (<<= 1)
  173. {
  174. e_CLASS_OPTION_PAUSED = 0x0000FFFF,
  175. e_CLASS_OPTION_NORE = 0x00010000,
  176. e_CLASS_OPTION_LOGIN_SELECT,
  177. e_CLASS_OPTION_LOGIN_SPAWN,
  178. e_CLASS_OPTION_REG_SELECT,
  179. e_CLASS_OPTION_REG_SPAWN,
  180. e_CLASS_OPTION_HAS_RC_CALLBACK,
  181. e_CLASS_OPTION_HAS_RS_CALLBACK,
  182. e_CLASS_OPTION_REFRESH_PAUSE
  183. }
  184. enum e_PLAYER_CLASS (<<= 1)
  185. {
  186. e_PLAYER_CLASS_SKIN = 0x000FFFFF,
  187. e_PLAYER_CLASS_PRESS = 0x00E00000,
  188. e_PLAYER_CLASS_RIGHT = 0x00200000,
  189. e_PLAYER_CLASS_MIDDLE,
  190. e_PLAYER_CLASS_LEFT,
  191. e_PLAYER_CLASS_EVER, // Has this player EVER spawned?
  192. e_PLAYER_CLASS_DENY, // Is this player not allowed to see class selection?
  193. e_PLAYER_CLASS_SPAWNED, // Should this player NOT be allowed to reselect?
  194. e_PLAYER_CLASS_SELECT,
  195. e_PLAYER_CLASS_RETURN, // Player is returning to class selection.
  196. e_PLAYER_CLASS_AFTER_RETURN, // Prevent the double class selection screen.
  197. e_PLAYER_CLASS_TEMP_SPAWN // Player has spawned once, respawn them.
  198. }
  199. #define e_PLAYER_CLASS_SPAWN_CHECK (e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_TEMP_SPAWN)
  200. #define CLASS_MOVE_LEFT (e_PLAYER_CLASS:-1)
  201. #define CLASS_MOVE_RIGHT (e_PLAYER_CLASS:1)
  202. static stock
  203. YSI_g_sClasses[MAX_CLASSES][E_CLASS],
  204. e_PLAYER_CLASS:YSI_g_sPlayerClass[MAX_PLAYERS],
  205. YSI_g_sLeft,
  206. YSI_g_sMiddle,
  207. YSI_g_sRight,
  208. YSI_g_sClassCount,
  209. e_CLASS_OPTION:YSI_g_sClassOptions,
  210. YSI_g_sLastRefuse[MAX_PLAYERS];
  211. static
  212. bool:YSI_g_sIsFirst = false;
  213. stock
  214. bool:YSI_gOPRCE = true,
  215. bool:YSI_gOPRSE = true;
  216. forward OnPlayerRequestSpawnEx_(playerid, classid);
  217. forward OnPlayerRequestClassEx_(playerid, classid);
  218. // This is set to not have to repeatedly update a player in a large set of
  219. // group updates. It is set and cleared in the request callbacks.
  220. #define Class_PauseRefresh(%1) \
  221. (YSI_g_sClassOptions |= e_CLASS_OPTION_REFRESH_PAUSE | e_CLASS_OPTION:(%1))
  222. #define Class_IsPaused(%1) \
  223. ((YSI_g_sClassOptions & (e_CLASS_OPTION_REFRESH_PAUSE | e_CLASS_OPTION_PAUSED)) == (e_CLASS_OPTION_REFRESH_PAUSE | e_CLASS_OPTION:(%1)))
  224. /*----------------------------------------------------------------------------*\
  225. Function:
  226. Class_IsActive
  227. Params:
  228. classid - Class to check.
  229. Return:
  230. -
  231. Notes:
  232. Checks if a class is currently in use.
  233. \*----------------------------------------------------------------------------*/
  234. #define Class_IsActive(%1) \
  235. (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_ACTIVE)
  236. /*----------------------------------------------------------------------------*\
  237. Function:
  238. Class_Enabled
  239. Params:
  240. classid - Class to check.
  241. Return:
  242. -
  243. Notes:
  244. Checks if a class is currently available for viewing.
  245. \*----------------------------------------------------------------------------*/
  246. #define Class_Enabled(%1) \
  247. (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_ENABLED)
  248. /*----------------------------------------------------------------------------*\
  249. Function:
  250. Class_IsValid
  251. Params:
  252. classid - Class to check.
  253. Return:
  254. -
  255. Notes:
  256. Checks if a number is a valid classid and active.
  257. \*----------------------------------------------------------------------------*/
  258. #define Class_IsValid(%1) \
  259. ((%1) >= 0 && (%1) < MAX_CLASSES && Class_IsActive((%1)))
  260. /*----------------------------------------------------------------------------*\
  261. Function:
  262. Class_X
  263. Params:
  264. classid - Class to get X location for.
  265. Return:
  266. -
  267. Notes:
  268. -
  269. \*----------------------------------------------------------------------------*/
  270. #define Class_X(%1) \
  271. YSI_g_sClasses[(%1)][E_CLASS_X]
  272. //(float(YSI_g_sClasses[(%1)][E_CLASS_XY] >> 16) / 10.0)
  273. /*----------------------------------------------------------------------------*\
  274. Function:
  275. Class_Y
  276. Params:
  277. classid - Class to get Y location for.
  278. Return:
  279. -
  280. Notes:
  281. -
  282. \*----------------------------------------------------------------------------*/
  283. #define Class_Y(%1) \
  284. YSI_g_sClasses[(%1)][E_CLASS_Y]
  285. //(float((YSI_g_sClasses[(%1)][E_CLASS_XY] & 0x7FFF) | ((YSI_g_sClasses[(%1)][E_CLASS_XY] & 0x8000) ? (0xFFFF8000) : (0))) / 10.0)
  286. /*----------------------------------------------------------------------------*\
  287. Function:
  288. Class_Z
  289. Params:
  290. classid - Class to get Z location for.
  291. Return:
  292. -
  293. Notes:
  294. -
  295. \*----------------------------------------------------------------------------*/
  296. #define Class_Z(%1) \
  297. YSI_g_sClasses[(%1)][E_CLASS_Z]
  298. //(float(YSI_g_sClasses[(%1)][E_CLASS_ZA] >> 16) / 10.0)
  299. /*----------------------------------------------------------------------------*\
  300. Function:
  301. Class_A
  302. Params:
  303. classid - Class to get angle for.
  304. Return:
  305. -
  306. Notes:
  307. -
  308. \*----------------------------------------------------------------------------*/
  309. #define Class_A(%1) \
  310. YSI_g_sClasses[(%1)][E_CLASS_A]
  311. //(float((YSI_g_sClasses[(%1)][E_CLASS_ZA] & 0x7FFF) | (YSI_g_sClasses[(%1)][E_CLASS_ZA] & 0x8000) ? (0xFFFF8000) : (0)) / 10.0)
  312. /*----------------------------------------------------------------------------*\
  313. Function:
  314. Class_Skin
  315. Params:
  316. classid - Class to get skin for.
  317. Return:
  318. -
  319. Notes:
  320. -
  321. \*----------------------------------------------------------------------------*/
  322. #define Class_Skin(%1) \
  323. (YSI_g_sClasses[(%1)][E_CLASS_FLAGS] & e_CLASS_FLAGS_SKIN)
  324. /*----------------------------------------------------------------------------*\
  325. Function:
  326. Class_Class
  327. Params:
  328. -
  329. Return:
  330. -
  331. Notes:
  332. Creates three real player classes so you can scroll correctly with the
  333. direction being detected.
  334. \*----------------------------------------------------------------------------*/
  335. forward _Class_DetermineOrder();
  336. public _Class_DetermineOrder()
  337. {
  338. YSI_g_sIsFirst = false;
  339. if (getproperty(8, YSIM_HFIRST) == 1)
  340. {
  341. // This is the first script called by "__CallRemoteFunction", and this is
  342. // updated every time a new script is started.
  343. setproperty(8, YSIM_HFIRST, 0);
  344. YSI_g_sIsFirst = true;
  345. }
  346. }
  347. /*hook OnAnyScriptInit()
  348. {
  349. // A whole new callback created just for this! Should maybe pass an ID
  350. // parameter, but that would mean more binding with the master system.
  351. setproperty(8, YSIM_HFIRST, 1);
  352. CallRemoteFunction("_Class_DetermineOrder", "");
  353. }*/
  354. //mhook OnScriptInit()
  355. hook OnScriptInit()
  356. {
  357. setproperty(8, YSIM_HFIRST, 1);
  358. CallRemoteFunction("_Class_DetermineOrder", "");
  359. #if !_YSIM_IS_CLIENT
  360. if (!YSI_FILTERSCRIPT)
  361. {
  362. // This code placement is not generic.
  363. YSI_g_sLeft = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  364. YSI_g_sMiddle = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  365. YSI_g_sRight = AddPlayerClass(0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  366. 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));
  367. #if !defined YSI_NO_MASTER
  368. // Steal the master system.
  369. _Master_Get(#_YCM, true);
  370. #if _YSIM_IS_CLOUD
  371. // Set to uninitialised.
  372. state _YCM:u;
  373. #endif
  374. CallRemoteFunction(#_YCM, "");
  375. #if _YSIM_IS_CLOUD
  376. // Fully master.
  377. state _YCM:y;
  378. #endif
  379. #endif
  380. }
  381. #endif
  382. return 1;
  383. }
  384. stock Class_ResolveGroups(class, Group:forgroup, bool:cp) <YSI_has_groups : n>
  385. {
  386. #pragma unused forgroup
  387. P:2("Class_ResolveGroups<n>: call Resolve %d %d %d", class, _:forgroup, cp);
  388. if (!cp) PA_Init(YSI_g_sClasses[class][E_CLASS_PLAYERS], true);
  389. //else if (forgroup) {}
  390. //Bit_SetAll(YSI_g_sClasses[class][E_CLASS_PLAYERS], true, bits<MAX_PLAYERS>);
  391. }
  392. stock Class_ResolveGroups(class, Group:forgroup, bool:cp) <>
  393. {
  394. #pragma unused forgroup
  395. P:2("Class_ResolveGroups<>: call Resolve %d %d %d", class, _:forgroup, cp);
  396. if (!cp) PA_Init(YSI_g_sClasses[class][E_CLASS_PLAYERS], true);
  397. //else if (forgroup) {}
  398. //Bit_SetAll(YSI_g_sClasses[class][E_CLASS_PLAYERS], true, bits<MAX_PLAYERS>);
  399. }
  400. /*----------------------------------------------------------------------------*\
  401. Function:
  402. Class_OnPlayerRequestSpawn
  403. Params:
  404. playerid - Player who selected a spawn.
  405. Return:
  406. -
  407. Notes:
  408. Has inbuilt protection for a bug where selections aren't correctly
  409. debounced so you can press shift twice at once which can mess up some
  410. scripts (e.g. the example team selection script). Calls
  411. OnPlayerRequestSpawnEx with an additional class parameter.
  412. \*----------------------------------------------------------------------------*/
  413. mhook OnPlayerRequestSpawn(playerid)
  414. {
  415. P:2("hook Class_OnPlayerRequestSpawn called: %d", playerid);
  416. //P:2("Class_OnPlayerRequestSpawn called");
  417. Class_PauseRefresh(playerid);
  418. if (YSI_g_sClassCount)
  419. {
  420. P:5("Class_OnPlayerRequestSpawn: Has class count");
  421. new
  422. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN;
  423. if (!(Class_Enabled(playerclass) && PA_Get(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid)))
  424. {
  425. Class_ResumeRefresh(playerid);
  426. return 1;
  427. }
  428. P:5("Class_OnPlayerRequestSpawn: Can spawn");
  429. // Don't need this line anymore - it's all done in OnPlayerRequestClass
  430. // OnPlayerSpawn.
  431. //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);
  432. new
  433. time = GetTickCount();
  434. if ((time - YSI_g_sLastRefuse[playerid]) >= 1000)
  435. {
  436. YSI_gOPRSE = false;
  437. CallRemoteFunction("OnPlayerRequestSpawnEx_", "ii", playerid, playerclass);
  438. new
  439. ret = 1;
  440. if (YSI_g_sClassOptions & e_CLASS_OPTION_HAS_RS_CALLBACK)
  441. {
  442. YSI_gOPRSE = true;
  443. ret = CallLocalFunction("OnPlayerRequestSpawnEx_", "ii", playerid, playerclass);
  444. }
  445. P:4("Class_OnPlayerRequestSpawn() return: %d", ret);
  446. if (ret)
  447. {
  448. //#if defined _YSI_SYSTEM_GROUPS
  449. new
  450. Group:newgroup = YSI_g_sClasses[playerclass][E_CLASS_GROUP];
  451. P:4("Class_OnPlayerRequestSpawn() newgroup: %d", _:newgroup);
  452. if (newgroup != Group:-1) Class_ResolveGroups(playerid, newgroup, true); //Group_AddPlayer(newgroup, playerid);
  453. //#endif
  454. if (ret == 1)
  455. {
  456. //ALS_CALL<PlayerRequestSpawn>
  457. Class_ResumeRefresh(playerid);
  458. return 1;
  459. }
  460. else if(ret == -1)
  461. {
  462. YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_SKIN;
  463. // The order is VERY important here - this will actually
  464. // call the function further down (directly below in fact).
  465. //OnPlayerRequestClass(playerid, YSI_g_sLeft);
  466. Class_DoOnPlayerRequestClass(playerid, YSI_g_sLeft);
  467. }
  468. }
  469. }
  470. YSI_g_sLastRefuse[playerid] = time;
  471. Class_ResumeRefresh(playerid);
  472. P:5("Class_OnPlayerRequestSpawn: Return 0");
  473. return 0;
  474. }
  475. //ALS_CALL<PlayerRequestSpawn>
  476. Class_ResumeRefresh(playerid);
  477. P:5("Class_OnPlayerRequestSpawn: Return 1");
  478. return 1;
  479. }
  480. /*----------------------------------------------------------------------------*\
  481. Function:
  482. Class_OnPlayerRequestClass
  483. Params:
  484. playerid - Player who requested a class.
  485. class - Class they requested.
  486. Return:
  487. -
  488. Notes:
  489. The input is one of the three real classes used to detect selected
  490. direction of alteration. Scans for a class the player is allowed to use
  491. and hot swaps it out. Uses SetPlayerSkin AND SetSpawnInfo to combat bugs
  492. with calling this from OnPlayerRequestSpawn (e.g. the example team script).
  493. Calls OnPlayerRequestClassEx with the current internal class not the real
  494. one.
  495. \*----------------------------------------------------------------------------*/
  496. static stock e_PLAYER_CLASS:Class_FindNew(playerid, e_PLAYER_CLASS:playerclass, e_PLAYER_CLASS:dir)
  497. {
  498. P:4("e_PLAYER_CLASS:Class_FindNew called: %i, %i, %i", playerid, _:playerclass, _:dir);
  499. if (playerclass >= e_PLAYER_CLASS:YSI_g_sClassCount)
  500. {
  501. playerclass = -dir;
  502. }
  503. new
  504. e_PLAYER_CLASS:old = playerclass % e_PLAYER_CLASS:YSI_g_sClassCount;
  505. do
  506. {
  507. playerclass = (playerclass + dir) % e_PLAYER_CLASS:YSI_g_sClassCount;
  508. //P:4("Class_OnPlayerRequestClass() playerclass: %d", playerclass);
  509. /*if (playerclass < e_PLAYER_CLASS:0)
  510. {
  511. playerclass = e_PLAYER_CLASS:(YSI_g_sClassCount - 1);
  512. }
  513. else if (playerclass >= e_PLAYER_CLASS:YSI_g_sClassCount)
  514. {
  515. playerclass = e_PLAYER_CLASS:0;
  516. }*/
  517. P:4("Class_FindNew: %d %d", playerclass, playerid);
  518. }
  519. while (playerclass != old && !(Class_Enabled(playerclass) && PA_Get(YSI_g_sClasses[playerclass][E_CLASS_PLAYERS], playerid)));
  520. return playerclass;
  521. }
  522. static stock Class_ResumeRefresh(playerid)
  523. {
  524. P:4("Class_ResumeRefresh called: %i", playerid);
  525. YSI_g_sClassOptions &= ~(e_CLASS_OPTION_REFRESH_PAUSE | e_CLASS_OPTION_PAUSED);
  526. new
  527. e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN;
  528. if (!PA_Get(YSI_g_sClasses[curclass][E_CLASS_PLAYERS], playerid))
  529. {
  530. Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS:curclass, CLASS_MOVE_RIGHT));
  531. }
  532. /*if (YSI_g_sClassOptions & e_CLASS_OPTION_NORE)
  533. {
  534. // Yes, if they're NOT allowed to change class, send them back to class
  535. // selection! This is so the message doesn't appear.
  536. ForceClassSelection(playerid);
  537. }*/
  538. }
  539. #if !_YSIM_IS_CLIENT
  540. forward _Class_DoRespawn(playerid);
  541. public _Class_DoRespawn(playerid)
  542. {
  543. SpawnPlayer(playerid);
  544. }
  545. #endif
  546. mhook OnPlayerRequestClass(playerid, classid)
  547. {
  548. P:2("hook OnPlayerRequestClass called: %d, %d", playerid, classid);
  549. return Class_DoOnPlayerRequestClass(playerid, classid);
  550. }
  551. static stock Class_DoOnPlayerRequestClass(playerid, classid)
  552. {
  553. P:4("Class_DoOnPlayerRequestClass called: %d, %d", playerid, classid);
  554. //P:2("Class_OnPlayerRequestClass() start");
  555. Class_PauseRefresh(playerid);
  556. //YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_SELECT;
  557. new
  558. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid],
  559. e_PLAYER_CLASS:dir = CLASS_MOVE_RIGHT;
  560. if ((YSI_g_sClassOptions & e_CLASS_OPTION_NORE) && (playerclass & e_PLAYER_CLASS_SPAWNED))
  561. {
  562. //ForceClassSelection(playerid);
  563. YSI_g_sPlayerClass[playerid] &= ~e_PLAYER_CLASS_AFTER_RETURN;
  564. // People aren't allowed to return to class selection.
  565. //SpawnPlayer(playerid);
  566. SetTimerEx("_Class_DoRespawn", 0, 0, "i", playerid);
  567. //Class_ResumeRefresh(playerid);
  568. return -1;
  569. }
  570. // Spawned from returning to class selection but not meant to.
  571. P:5("Class_OnPlayerRequestClass(): Spawn check %d %d", (playerclass & e_PLAYER_CLASS_SPAWN_CHECK), e_PLAYER_CLASS_SPAWN_CHECK);
  572. /*if ((playerclass & e_PLAYER_CLASS_SPAWN_CHECK) == e_PLAYER_CLASS_SPAWN_CHECK)
  573. {
  574. YSI_g_sPlayerClass[playerid] &= ~e_PLAYER_CLASS_SPAWN_CHECK;
  575. // People aren't allowed to return to class selection.
  576. playerclass &= e_PLAYER_CLASS_SKIN;
  577. 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);
  578. //SpawnPlayer(playerid);
  579. SetTimerEx("_Class_DoRespawn", 0, 0, "i", playerid);
  580. //Class_ResumeRefresh(playerid);
  581. return 1;
  582. }*/
  583. if (playerclass & e_PLAYER_CLASS_DENY)
  584. {
  585. TogglePlayerControllable(playerid, false);
  586. TogglePlayerSpectating(playerid, true);
  587. Class_ResumeRefresh(playerid);
  588. return 0;
  589. }
  590. switch (playerclass & e_PLAYER_CLASS_PRESS)
  591. {
  592. case e_PLAYER_CLASS_RIGHT:
  593. {
  594. if (classid == YSI_g_sMiddle)
  595. {
  596. // Went from the right to the middle - that's a move left.
  597. dir = CLASS_MOVE_LEFT;
  598. }
  599. }
  600. case e_PLAYER_CLASS_MIDDLE:
  601. {
  602. if (classid == YSI_g_sLeft)
  603. {
  604. // Went from the middle to the left - that's a move left.
  605. dir = CLASS_MOVE_LEFT;
  606. }
  607. }
  608. default:
  609. {
  610. if (classid == YSI_g_sRight)
  611. {
  612. // Went from the left to the right - that's a wrap move left.
  613. dir = CLASS_MOVE_LEFT;
  614. }
  615. }
  616. }
  617. if (classid == YSI_g_sMiddle) YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_MIDDLE | (playerclass & (e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_EVER));
  618. else if (classid == YSI_g_sLeft) YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_LEFT | (playerclass & (e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_EVER));
  619. else if (classid == YSI_g_sRight) YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_RIGHT | (playerclass & (e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_EVER));
  620. if (playerclass & (e_PLAYER_CLASS_SPAWNED | e_PLAYER_CLASS_RETURN))
  621. {
  622. playerclass = e_PLAYER_CLASS_SKIN;
  623. }
  624. else
  625. {
  626. playerclass &= e_PLAYER_CLASS_SKIN;
  627. }
  628. if (!YSI_g_sClassCount)
  629. {
  630. SetSpawnInfo(playerid, NO_TEAM, 0, 1958.0, 1343.0, 15.0, 269.0, 0, 0, 0, 0, 0, 0);
  631. SetPlayerSkin(playerid, 0);
  632. P:E("No YSI classes found");
  633. }
  634. else
  635. {
  636. // Find the next available skin for this player. I'm still not sure how
  637. // this handles the case where you can't use any skin. I'll have to
  638. // look in to that.
  639. playerclass = Class_FindNew(playerid, playerclass, dir);
  640. P:5("Class_OnPlayerRequestClass() selected: %d", playerclass);
  641. }
  642. //Class_ResumeRefresh(playerid);
  643. YSI_g_sClassOptions &= ~(e_CLASS_OPTION_REFRESH_PAUSE | e_CLASS_OPTION_PAUSED);
  644. return Class_Goto(playerid, _:playerclass);
  645. //ALS_CALL_EX<PlayerRequestClass, ret>
  646. }
  647. foreign Class_Goto(playerid, playerclass);
  648. global Class_Goto(playerid, playerclass)
  649. {
  650. P:2("Class_Goto called: %i, %i", playerid, playerclass);
  651. // This now sets the REAL spawn information, including spawn location.
  652. // 0.2 code
  653. //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);
  654. // 0.3 code
  655. 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);
  656. SetPlayerSkin(playerid, Class_Skin(e_PLAYER_CLASS:playerclass));
  657. 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;
  658. // Save the last viewed class so that we know which direction the person
  659. // went next time OnPlayerRequestClass is called.
  660. P:2("Class_Goto() end");
  661. // Call the OnPlayerRequestClassEx functions.
  662. YSI_gOPRCE = false;
  663. CallRemoteFunction("OnPlayerRequestClassEx_", "ii", playerid, playerclass);
  664. if (YSI_g_sClassOptions & e_CLASS_OPTION_HAS_RC_CALLBACK)
  665. {
  666. YSI_gOPRCE = true;
  667. return CallLocalFunction("OnPlayerRequestClassEx_", "ii", playerid, playerclass);
  668. }
  669. return 0;
  670. }
  671. /*----------------------------------------------------------------------------*\
  672. Function:
  673. Class_OnPlayerConnect
  674. Params:
  675. playerid - Player who joined.
  676. Return:
  677. -
  678. Notes:
  679. Resets the player's current class.
  680. \*----------------------------------------------------------------------------*/
  681. mhook OnPlayerConnect(playerid)
  682. {
  683. P:2("Class_OnPlayerConnect called: %d", playerid);
  684. //P:2("Class_OnPlayerConnect called");
  685. YSI_g_sPlayerClass[playerid] = e_PLAYER_CLASS_SKIN;
  686. if (YSI_g_sClassOptions & e_CLASS_OPTION_LOGIN_SELECT)
  687. {
  688. Class_DenySelection(playerid);
  689. }
  690. return 1;
  691. }
  692. mhook OnPlayerLogin(playerid, yid)
  693. {
  694. if (YSI_g_sClassOptions & e_CLASS_OPTION_LOGIN_SELECT)
  695. {
  696. Class_ReturnToSelection(playerid);
  697. }
  698. return 1;
  699. }
  700. foreign Class_ReturnToSelection(playerid);
  701. global Class_ReturnToSelection(playerid)
  702. {
  703. P:2("Class_ReturnToSelection called: %i", playerid);
  704. // All of these lines are required to correctly send the player back to the
  705. // class selection, unfortunately they also cause nasty side effects.
  706. //TogglePlayerControllable(playerid, true);
  707. // if (YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_EVER)
  708. // {
  709. // //TogglePlayerControllable(playerid, true);
  710. // //YSI_g_sPlayerClass[playerid] &= e_PLAYER_CLASS_SPAWNED;
  711. // //SetPlayerHealth(playerid, 0.0);
  712. // ForceClassSelection(playerid);
  713. // SetPlayerHealth(playerid, 0.0);
  714. // TogglePlayerControllable(playerid, false);
  715. // }
  716. // else
  717. // {
  718. // TogglePlayerSpectating(playerid, false);
  719. ForceClassSelection(playerid);
  720. SetPlayerHealth(playerid, 0.0);
  721. // }
  722. // ForceClassSelection(playerid);
  723. TogglePlayerSpectating(playerid, false);
  724. // SetPlayerHealth(playerid, 0.0);
  725. // TogglePlayerControllable(playerid, true);
  726. //ForceClassSelection(playerid);
  727. //YSI_g_sPlayerClass[playerid] &= ~(e_PLAYER_CLASS_DENY | e_PLAYER_CLASS_SPAWNED);
  728. // TogglePlayerControllable(playerid, true);
  729. //YSI_g_sPlayerClass[playerid] &= e_PLAYER_CLASS_SPAWNED;
  730. //ForceClassSelection(playerid);
  731. //SetPlayerHealth(playerid, 0.0);
  732. //TogglePlayerControllable(playerid, false);
  733. //YSI_g_sPlayerClass[playerid] = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_PRESS | e_PLAYER_CLASS_SKIN;
  734. // Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS_SKIN, CLASS_MOVE_RIGHT));
  735. //YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_RETURN | e_PLAYER_CLASS_AFTER_RETURN;
  736. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] | e_PLAYER_CLASS_RETURN | e_PLAYER_CLASS_AFTER_RETURN) & ~(e_PLAYER_CLASS_DENY | e_PLAYER_CLASS_SPAWNED);
  737. //YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] | e_PLAYER_CLASS_RETURN) & ~e_PLAYER_CLASS_SPAWNED;
  738. return 1;
  739. }
  740. foreign Class_DenySelection(playerid);
  741. global Class_DenySelection(playerid)
  742. {
  743. P:2("Class_DenySelection called: %i", playerid);
  744. //SpawnPlayer(playerid);
  745. TogglePlayerControllable(playerid, false);
  746. TogglePlayerSpectating(playerid, true);
  747. SetSpawnInfo(playerid, 0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0);
  748. SpawnPlayer(playerid);
  749. // "e_PLAYER_CLASS_DENY" is unset by not being re-set in "Class_Goto".
  750. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] | e_PLAYER_CLASS_DENY) & ~e_PLAYER_CLASS_SELECT;
  751. //ForceClassSelection
  752. return 1;
  753. }
  754. /*----------------------------------------------------------------------------*\
  755. Function:
  756. Class_OnPlayerDeath
  757. Params:
  758. playerid - Player who dies.
  759. reason - The reason they died.
  760. Return:
  761. -1 on fake deaths.
  762. Notes:
  763. Catches and hides fake deaths caused by the spawn system. Called first.
  764. \*----------------------------------------------------------------------------*/
  765. // We need this definition as we are using "mhook" instead of "hook", which
  766. // can't handle the extra number used to force a call order.
  767. //#define ALS_R_PlayerDeath0 ALS_R_PlayerDeath
  768. hook OnPlayerDeath0(playerid, killerid, reason)
  769. {
  770. // For consistency all scripts return -1 if the class system thinks this is
  771. // a fake death caused by the weird respawn selection system.
  772. if (YSI_g_sIsFirst)
  773. {
  774. new
  775. ret = Class_DoPlayerDeath(playerid, killerid, reason);
  776. setproperty(8, YSIM_OPDRET, ret);
  777. return ret;
  778. }
  779. return getproperty(8, YSIM_OPDRET);
  780. }
  781. foreign Class_DoPlayerDeath(playerid, killerid, reason);
  782. global Class_DoPlayerDeath(playerid, killerid, reason)
  783. {
  784. P:2("Class_OnPlayerDeath called: %d, %d, %d", playerid, killerid, reason);
  785. #pragma unused killerid, reason
  786. P:2("Class_OnPlayerDeath called");
  787. //new
  788. // time = GetTickCount();
  789. //new
  790. // e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN;
  791. //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);
  792. //return -1;
  793. //if ((YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SPAWN_CHECK) == e_PLAYER_CLASS_SPAWN_CHECK)// || (time - YSI_g_sLastRefuse[playerid]) < 200)
  794. if ((YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_AFTER_RETURN) == e_PLAYER_CLASS_AFTER_RETURN)// || (time - YSI_g_sLastRefuse[playerid]) < 200)
  795. {
  796. P:2("Class_OnPlayerDeath: Inner");
  797. new
  798. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN;
  799. // Fake death to get the ForceClassSelection out the system.
  800. //SetTimerEx("_Class_DoRespawn", 0, 0, "i", playerid);
  801. //SetPlayerHealth(playerid, 100.0);
  802. if ((YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_TEMP_SPAWN) == e_PLAYER_CLASS_TEMP_SPAWN)
  803. {
  804. 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);
  805. SpawnPlayer(playerid);
  806. YSI_g_sPlayerClass[playerid] &= ~(e_PLAYER_CLASS_AFTER_RETURN | e_PLAYER_CLASS_TEMP_SPAWN);
  807. }
  808. //YSI_g_sLastRefuse[playerid] = time;
  809. // Cancel all other callbacks.
  810. return -1;
  811. }
  812. //TogglePlayerControllable(playerid, false);
  813. if (YSI_g_sClassOptions & e_CLASS_OPTION_NORE)
  814. {
  815. /*new
  816. e_PLAYER_CLASS:playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN;
  817. 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);
  818. SpawnPlayer(playerid);
  819. SetPlayerHealth(playerid, 100.0);*/
  820. SetTimerEx("_Class_DoRespawn", 2500, 0, "i", playerid);
  821. //ForceClassSelection(playerid);
  822. }
  823. return 1;
  824. }
  825. /*----------------------------------------------------------------------------*\
  826. Function:
  827. Class_OnPlayerSpawn
  828. Params:
  829. playerid - Player who spawned.
  830. Return:
  831. -
  832. Notes:
  833. Sets a player's position based on skin.
  834. \*----------------------------------------------------------------------------*/
  835. mhook OnPlayerSpawn(playerid)
  836. {
  837. P:2("Class_OnPlayerSpawn called: %d", playerid);
  838. //P:2("Class_OnPlayerSpawn called: %d %d", YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_AFTER_RETURN, e_PLAYER_CLASS_AFTER_RETURN);
  839. if (YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_AFTER_RETURN)
  840. {
  841. // Fake spawn.
  842. //SetPlayer
  843. YSI_g_sPlayerClass[playerid] |= e_PLAYER_CLASS_TEMP_SPAWN;
  844. return -1;
  845. }
  846. YSI_g_sPlayerClass[playerid] = (YSI_g_sPlayerClass[playerid] | e_PLAYER_CLASS_SPAWNED | e_PLAYER_CLASS_EVER) & ~e_PLAYER_CLASS_SELECT;
  847. new
  848. playerclass = YSI_g_sPlayerClass[playerid] & e_PLAYER_CLASS_SKIN,
  849. weapon;
  850. for (new i = 0; i != MAX_CLASS_SPAWN_WEAPONS; ++i)
  851. {
  852. weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][i];
  853. //if (weapon == WEAPON_ARMOUR) SetPlayerArmour(playerid, 100.0);
  854. if (weapon)
  855. {
  856. GivePlayerWeapon(playerid, weapon & 0xFF, weapon >>> 8);
  857. }
  858. else
  859. {
  860. break;
  861. }
  862. }
  863. weapon = YSI_g_sClasses[playerclass][E_CLASS_WEAPONS][MAX_CLASS_SPAWN_WEAPONS];
  864. P:5("Class_OnPlayerSpawn: Armour %d %d %d", weapon, weapon & 0xFF, WEAPON_ARMOUR);
  865. if ((weapon & 0xFF) == WEAPON_ARMOUR)
  866. {
  867. weapon >>>= 8;
  868. if (weapon == 0x00800000)
  869. {
  870. // INFINITY
  871. SetPlayerArmour(playerid, Float:0x7F800000);
  872. }
  873. else
  874. {
  875. SetPlayerArmour(playerid, weapon);
  876. }
  877. }
  878. /*if (YSI_g_sClassOptions & e_CLASS_OPTION_NORE)
  879. {
  880. // Yes, if they're NOT allowed to change class, send them back to class
  881. // selection! This is so the message doesn't appear.
  882. ForceClassSelection(playerid);
  883. }*/
  884. return 1;
  885. }
  886. /*----------------------------------------------------------------------------*\
  887. Function:
  888. Class_Add
  889. Params:
  890. skin - Skin of the class.
  891. Float:x - X spawn location.
  892. Float:y - Y spawn location.
  893. Float:z - Z spawn location.
  894. Float:a - A spawn location.
  895. ... - Spawn weapons and ammo (weapon then ammo)
  896. Return:
  897. -
  898. Notes:
  899. Pretty much AddPlayerClass but allows greater control over the classes.
  900. Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons. This is one of
  901. the few API functions which is not entirely remote. This is because it has
  902. variable parameters which is need to collect in to a single array to pass to
  903. the remote function.
  904. \*----------------------------------------------------------------------------*/
  905. stock Class_Add(skin, Float:x, Float:y, Float:z, Float:a, ...)
  906. {
  907. P:3("Class_Add called: %i, %i, %i, %i, %i, %i (+%i)", skin, x, y, z, a, numargs() - 5);
  908. new
  909. n = numargs(),
  910. w = 5,
  911. s,
  912. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  913. cw;
  914. _CLASS_WEAPON_CODE
  915. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, Group:-1, Group:-1);
  916. }
  917. /*----------------------------------------------------------------------------*\
  918. Function:
  919. Class_AddEx
  920. Params:
  921. forgroup - Group that can use the skin.
  922. setgroup - Group to add the player to on selection.
  923. skin - Skin of the class.
  924. Float:x - X spawn location.
  925. Float:y - Y spawn location.
  926. Float:z - Z spawn location.
  927. Float:a - A spawn location.
  928. ... - Spawn weapons and ammo (weapon then ammo)
  929. Return:
  930. -
  931. Notes:
  932. Pretty much AddPlayerClass but allows greater control over the classes.
  933. Now has infinate (MAX_CLASS_SPAWN_WEAPONS) spawn weapons.
  934. \*----------------------------------------------------------------------------*/
  935. stock Class_AddEx(Group:forgroup, Group:setgroup, skin, Float:x, Float:y, Float:z, Float:a, ...)
  936. {
  937. P:3("Class_AddEx called: %i, %i, %i, %f, %f, %f, %f (+%i)", _:forgroup, _:setgroup, skin, x, y, z, a, numargs() - 7);
  938. new
  939. n = numargs(),
  940. w = 7,
  941. s,
  942. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  943. cw;
  944. _CLASS_WEAPON_CODE
  945. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, forgroup, setgroup);
  946. }
  947. /*----------------------------------------------------------------------------*\
  948. Function:
  949. Class_AddClass
  950. Params:
  951. skin - Skin of the class.
  952. Float:x - X spawn location.
  953. Float:y - Y spawn location.
  954. Float:z - Z spawn location.
  955. Float:a - A spawn location.
  956. weapons[] - Array of spawn weapon data.
  957. count - Number of weapons added.
  958. forgroup - Group that can use the class.
  959. asgroup - Group to assign people to with this class.
  960. Return:
  961. -
  962. Notes:
  963. Does the hard work. This took a long time to get working correctly with the
  964. new master system, infact getting just this one function to compile took a
  965. major re-working of the macros to reduce the length of intermediate stages.
  966. \*----------------------------------------------------------------------------*/
  967. foreign Class_AddClass(s,Float:x,Float:y,Float:z,Float:a,w[],c,Group:f,Group:g);
  968. global Class_AddClass(s,Float:x,Float:y,Float:z,Float:a,w[],c,Group:f,Group:g)
  969. {
  970. P:2("Class_AddClass called: %i, %f, %f, %f, %f, %a, %i, %i, %i", s, x, y, z, a, w, c, _:f, _:g);
  971. new
  972. i;
  973. while (i < MAX_CLASSES)
  974. {
  975. if (!Class_IsActive(i)) break;
  976. i++;
  977. }
  978. if (i == MAX_CLASSES) return -1;
  979. YSI_g_sClasses[i][E_CLASS_FLAGS] = e_CLASS_FLAGS_ACTIVE | e_CLASS_FLAGS_ENABLED | e_CLASS_FLAGS:s;
  980. YSI_g_sClasses[i][E_CLASS_X] = x;
  981. YSI_g_sClasses[i][E_CLASS_Y] = y;
  982. YSI_g_sClasses[i][E_CLASS_Z] = z;
  983. YSI_g_sClasses[i][E_CLASS_A] = a;
  984. new
  985. j;
  986. // This may be better with a memcpy.
  987. while (j < c)
  988. {
  989. P:5("Class_AddClass: weapon %d %d %d", j, c, w[j]);
  990. YSI_g_sClasses[i][E_CLASS_WEAPONS][j] = w[j];
  991. ++j;
  992. }
  993. //Bit_SetAll(YSI_g_sClasses[class][E_CLASS_PLAYERS], false, bits<MAX_PLAYERS>);
  994. PA_FastInit(YSI_g_sClasses[i][E_CLASS_PLAYERS]);
  995. Class_ResolveGroups(i, f, false);
  996. YSI_g_sClasses[i][E_CLASS_GROUP] = g;
  997. //YSI_g_sClasses[i][E_CLASS_WEAPONS][MAX_CLASS_SPAWN_WEAPONS] = w[MAX_CLASS_SPAWN_WEAPONS];
  998. YSI_g_sClassCount++;
  999. //setproperty(0, "LReqClass", i);
  1000. //#if !defined YSI_CLASS_INVERT
  1001. // Bit_SetAll(YSI_g_sClasses[i][E_CLASS_PLAYERS], true, bits<MAX_PLAYERS>);
  1002. //#endif
  1003. return i;
  1004. }
  1005. /*----------------------------------------------------------------------------*\
  1006. Function:
  1007. Class_AddForGroup
  1008. Params:
  1009. group - Group to allow to use the class.
  1010. skin - Skin of the class.
  1011. Float:x - X spawn location.
  1012. Float:y - Y spawn location.
  1013. Float:z - Z spawn location.
  1014. Float:a - A spawn location.
  1015. ... - Weapon data.
  1016. Return:
  1017. -
  1018. Notes:
  1019. Adds a class only people in the specified group can use.
  1020. \*----------------------------------------------------------------------------*/
  1021. //#if defined _YSI_SYSTEM_GROUPS
  1022. stock Class_AddForGroup(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
  1023. {
  1024. P:3("Class_AddForGroup called: %i, %i, %f, %f, %f, %f (+%i)", _:group, skin, x, y, z, a, numargs() - 6);
  1025. new
  1026. n = numargs(),
  1027. w = 6,
  1028. s,
  1029. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  1030. cw;
  1031. _CLASS_WEAPON_CODE
  1032. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, group, Group:-1);
  1033. }
  1034. /*#else
  1035. #define Class_AddForGroup(%1,%2) \
  1036. Class_Add(%2)
  1037. #endif*/
  1038. /*----------------------------------------------------------------------------*\
  1039. Function:
  1040. Class_AddWithGroupSet
  1041. Params:
  1042. group - Group to make players who use this group.
  1043. skin - Skin of the class.
  1044. Float:x - X spawn location.
  1045. Float:y - Y spawn location.
  1046. Float:z - Z spawn location.
  1047. Float:a - A spawn location.
  1048. ... - Spawn weapons.
  1049. Return:
  1050. -
  1051. Notes:
  1052. Adds a class which puts you in the specified group when selected.
  1053. \*----------------------------------------------------------------------------*/
  1054. //#if defined _YSI_SYSTEM_GROUPS
  1055. stock Class_AddWithGroupSet(Group:group, skin, Float:x, Float:y, Float:z, Float:a, ...)
  1056. {
  1057. P:3("Class_AddWithGroupSet called: %i, %i, %f, %f, %f, %f (+%i)", _:group, skin, x, y, z, a, numargs() - 6);
  1058. new
  1059. n = numargs(),
  1060. w = 6,
  1061. s,
  1062. weapons[MAX_CLASS_SPAWN_WEAPONS + 1],
  1063. cw;
  1064. _CLASS_WEAPON_CODE
  1065. return Class_AddClass(skin, x, y, z, a, weapons, MAX_CLASS_SPAWN_WEAPONS + 1, Group:-1, group);
  1066. }
  1067. /*#else
  1068. #define Class_AddWithGroupSet(%1,%2) \
  1069. Class_Add(%2)
  1070. #endif*/
  1071. /*----------------------------------------------------------------------------*\
  1072. Function:
  1073. Class_Enable
  1074. Params:
  1075. classid - Class to re-enable.
  1076. Return:
  1077. -
  1078. Notes:
  1079. Reallow use of this class.
  1080. \*----------------------------------------------------------------------------*/
  1081. foreign Class_Enable(classid);
  1082. global Class_Enable(classid)
  1083. {
  1084. P:2("Class_Enable called: %i", classid);
  1085. if (Class_IsValid(classid)) YSI_g_sClasses[classid][E_CLASS_FLAGS] |= e_CLASS_FLAGS_ENABLED;
  1086. return 1;
  1087. }
  1088. /*----------------------------------------------------------------------------*\
  1089. Function:
  1090. Class_Disable
  1091. Params:
  1092. classid - Class to disable.
  1093. Return:
  1094. -
  1095. Notes:
  1096. Stop people being able to use this class.
  1097. \*----------------------------------------------------------------------------*/
  1098. foreign Class_Disable(classid);
  1099. global Class_Disable(classid)
  1100. {
  1101. P:2("Class_Disable called: %i", classid);
  1102. if (Class_IsValid(classid))
  1103. {
  1104. YSI_g_sClasses[classid][E_CLASS_FLAGS] &= ~e_CLASS_FLAGS_ENABLED;
  1105. foreach (new playerid : Player)
  1106. {
  1107. new
  1108. e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[playerid];
  1109. if (curclass & e_PLAYER_CLASS_SELECT)
  1110. {
  1111. if (e_PLAYER_CLASS:classid == curclass & e_PLAYER_CLASS_SKIN) Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS:classid, CLASS_MOVE_RIGHT));
  1112. }
  1113. }
  1114. }
  1115. return 1;
  1116. }
  1117. /*----------------------------------------------------------------------------*\
  1118. Function:
  1119. Class_Remote
  1120. Params:
  1121. allow - Wether or not to allow changing class.
  1122. Return:
  1123. -
  1124. Notes:
  1125. Sets wether or not people can change class after first spawning.
  1126. \*----------------------------------------------------------------------------*/
  1127. foreign Class_AllowReselection(allow);
  1128. global Class_AllowReselection(allow)
  1129. {
  1130. P:2("Class_AllowReselection called: %i", allow);
  1131. if (allow)
  1132. {
  1133. YSI_g_sClassOptions &= ~e_CLASS_OPTION_NORE;
  1134. }
  1135. else
  1136. {
  1137. YSI_g_sClassOptions |= e_CLASS_OPTION_NORE;
  1138. /*foreach (new playerid : Player)
  1139. {
  1140. // So they can't see any message if they press F4.
  1141. ForceClassSelection(playerid);
  1142. }*/
  1143. }
  1144. return 1;
  1145. }
  1146. /*----------------------------------------------------------------------------*\
  1147. Function:
  1148. Class_Delete
  1149. Params:
  1150. classid - Class to delete.
  1151. Return:
  1152. -
  1153. Notes:
  1154. Completely removes a class from the system.
  1155. \*----------------------------------------------------------------------------*/
  1156. foreign Class_Delete(classid);
  1157. global Class_Delete(classid)
  1158. {
  1159. P:2("Class_Delete called: %i", classid);
  1160. if (Class_IsValid(classid))
  1161. {
  1162. YSI_g_sClasses[classid][E_CLASS_FLAGS] = e_CLASS_FLAGS:0;
  1163. foreach (new playerid : Player)
  1164. {
  1165. new
  1166. e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[playerid];
  1167. P:4("Class_Delete: %d %d %d", playerid, curclass, e_PLAYER_CLASS_SELECT);
  1168. if (curclass & e_PLAYER_CLASS_SELECT)
  1169. {
  1170. if (e_PLAYER_CLASS:classid == curclass & e_PLAYER_CLASS_SKIN) Class_Goto(playerid, Class_FindNew(playerid, e_PLAYER_CLASS:classid, CLASS_MOVE_RIGHT));
  1171. }
  1172. }
  1173. }
  1174. return 1;
  1175. }
  1176. /*----------------------------------------------------------------------------*\
  1177. Function:
  1178. Class_SetPlayer
  1179. Params:
  1180. classid - Class to set permissions for.
  1181. playerid - Player to set for.
  1182. set - Whether or not they can use this class.
  1183. Return:
  1184. -
  1185. Notes:
  1186. -
  1187. \*----------------------------------------------------------------------------*/
  1188. foreign Class_SetPlayer(cl, pid, bool:s);
  1189. global Class_SetPlayer(cl, pid, bool:s)
  1190. {
  1191. P:2("Class_SetPlayer called: %i, %i, %i", cl, pid, s);
  1192. P:5("Class_SetPlayer %d %d %d", cl, pid, s);
  1193. if (Class_IsValid(cl) && 0 <= pid < MAX_PLAYERS)
  1194. {
  1195. if (s) PA_Let(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
  1196. else
  1197. {
  1198. PA_Vet(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
  1199. if (!Class_IsPaused(pid))
  1200. {
  1201. new
  1202. e_PLAYER_CLASS:curclass = YSI_g_sPlayerClass[pid];
  1203. if (curclass & e_PLAYER_CLASS_SELECT)
  1204. {
  1205. if (e_PLAYER_CLASS:cl == curclass & e_PLAYER_CLASS_SKIN) Class_Goto(pid, Class_FindNew(pid, e_PLAYER_CLASS:cl, CLASS_MOVE_RIGHT));
  1206. }
  1207. }
  1208. }
  1209. }
  1210. return 1;
  1211. }
  1212. /*----------------------------------------------------------------------------*\
  1213. Function:
  1214. Class_GetPlayer
  1215. Params:
  1216. classid - Class to set permissions for.
  1217. playerid - Player to set for.
  1218. Return:
  1219. -
  1220. Notes:
  1221. -
  1222. \*----------------------------------------------------------------------------*/
  1223. foreign bool:Class_GetPlayer(cl,pid);
  1224. global bool:Class_GetPlayer(cl,pid)
  1225. {
  1226. P:2("bool:Class_GetPlayer called: %i, %i", cl, pid);
  1227. if (Class_IsValid(cl) && 0 <= pid < MAX_PLAYERS)
  1228. {
  1229. return PA_Get(YSI_g_sClasses[cl][E_CLASS_PLAYERS], pid);
  1230. }
  1231. return false;
  1232. }
  1233. /*----------------------------------------------------------------------------*\
  1234. Function:
  1235. Class_RequireSelectionLogin
  1236. Params:
  1237. allow - Wether or not people must login.
  1238. Return:
  1239. -
  1240. Notes:
  1241. Don't let registered people select a class till they log in.
  1242. \*----------------------------------------------------------------------------*/
  1243. foreign Class_RequireSelectionLogin(allow);
  1244. global Class_RequireSelectionLogin(allow)
  1245. {
  1246. P:2("Class_RequireSelectionLogin called: %i", allow);
  1247. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_LOGIN_SELECT;
  1248. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_LOGIN_SELECT;
  1249. return 1;
  1250. }
  1251. /*----------------------------------------------------------------------------*\
  1252. Function:
  1253. Class_RequireSpawnLogin
  1254. Params:
  1255. allow - Wether or not people must login.
  1256. Return:
  1257. -
  1258. Notes:
  1259. Don't let registered people spawn till they log in.
  1260. \*----------------------------------------------------------------------------*/
  1261. foreign Class_RequireSpawnLogin(allow);
  1262. global Class_RequireSpawnLogin(allow)
  1263. {
  1264. P:2("Class_RequireSpawnLogin called: %i", allow);
  1265. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_LOGIN_SPAWN;
  1266. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_LOGIN_SPAWN;
  1267. return 1;
  1268. }
  1269. /*----------------------------------------------------------------------------*\
  1270. Function:
  1271. Class_RequireSelectionReg
  1272. Params:
  1273. allow - Wether or not people must register.
  1274. Return:
  1275. -
  1276. Notes:
  1277. Don't let people select a class till they register.
  1278. \*----------------------------------------------------------------------------*/
  1279. foreign Class_RequireSelectionReg(allow);
  1280. global Class_RequireSelectionReg(allow)
  1281. {
  1282. P:2("Class_RequireSelectionReg called: %i", allow);
  1283. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_REG_SELECT;
  1284. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_REG_SELECT;
  1285. return 1;
  1286. }
  1287. #define Class_RequireSelectionRegistration Class_RequireSelectionReg
  1288. /*----------------------------------------------------------------------------*\
  1289. Function:
  1290. Class_RequireSpawnReg
  1291. Params:
  1292. allow - Wether or not people must register.
  1293. Return:
  1294. -
  1295. Notes:
  1296. Don't let people spawn till they register.
  1297. \*----------------------------------------------------------------------------*/
  1298. foreign Class_RequireSpawnReg(allow);
  1299. global Class_RequireSpawnReg(allow)
  1300. {
  1301. P:2("Class_RequireSpawnReg called: %i", allow);
  1302. if (allow) YSI_g_sClassOptions |= e_CLASS_OPTION_REG_SPAWN;
  1303. else YSI_g_sClassOptions &= ~e_CLASS_OPTION_REG_SPAWN;
  1304. return 1;
  1305. }
  1306. #define Class_RequireSpawnRegistration Class_RequireSpawnReg
  1307. // Clean up - there's no way to do this like in the master system as people can
  1308. // use any arbitrary string here, not just a restricted set of numbers.
  1309. //#define YSI_SET_LAST_GROUP 22
  1310. #include "internal\y_grouprevert"