mSelection.inc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. //
  2. // Model Selection using previews. For SA-MP 0.3x and above.
  3. // - D0erfler 2013
  4. // - Kye 2013
  5. //
  6. // Version 1.1 R2
  7. /*Functions to be used
  8. LoadModelSelectionMenu(f_name[])
  9. HideModelSelectionMenu(playerid)
  10. ShowModelSelectionMenu(playerid, ListID, header_text[], dialogBGcolor = 0x4A5A6BBB, previewBGcolor = 0x88888899 , tdSelectionColor = 0xFFFF00AA)
  11. ShowModelSelectionMenuEx(playerid, items_array[], item_amount, header_text[], extraid, Float:Xrot = 0.0, Float:Yrot = 0.0, Float:Zrot = 0.0, Float:mZoom = 1.0, dialogBGcolor = 0x4A5A6BBB, previewBGcolor = 0x88888899 , tdSelectionColor = 0xFFFF00AA)
  12. */
  13. // Callbacks
  14. forward OnPlayerModelSelection(playerid, response, listid, modelid);
  15. forward OnPlayerModelSelectionEx(playerid, response, extraid, modelid);
  16. // settings static lists
  17. #define mS_TOTAL_ITEMS 1000 // Max amount of items from all lists
  18. #define mS_TOTAL_LISTS 20 // Max amount of lists
  19. #define mS_TOTAL_ROT_ZOOM 100 // Max amount of items using extra information like zoom or rotations
  20. // settings dynamic per player lists
  21. #define mS_CUSTOM_MAX_ITEMS 300
  22. new gCustomList[MAX_PLAYERS][mS_CUSTOM_MAX_ITEMS];
  23. #define mS_INVALID_LISTID mS_TOTAL_LISTS
  24. #define mS_CUSTOM_LISTID (mS_TOTAL_LISTS+1)
  25. #define mS_NEXT_TEXT ">"
  26. #define mS_PREV_TEXT "<"
  27. #define mS_CANCEL_TEXT "X"
  28. #define mS_SELECTION_ITEMS 21
  29. #define mS_ITEMS_PER_LINE 7
  30. #define mS_DIALOG_BASE_X 75.0
  31. #define mS_DIALOG_BASE_Y 130.0
  32. #define mS_DIALOG_WIDTH 550.0
  33. #define mS_DIALOG_HEIGHT 180.0
  34. #define mS_SPRITE_DIM_X 60.0
  35. #define mS_SPRITE_DIM_Y 70.0
  36. new PlayerText:gCurrentPageTextDrawId[MAX_PLAYERS];
  37. new PlayerText:gHeaderTextDrawId[MAX_PLAYERS];
  38. new PlayerText:gBackgroundTextDrawId[MAX_PLAYERS];
  39. new PlayerText:gNextButtonTextDrawId[MAX_PLAYERS];
  40. new PlayerText:gPrevButtonTextDrawId[MAX_PLAYERS];
  41. new PlayerText:gCancelButtonTextDrawId[MAX_PLAYERS];
  42. new PlayerText:gSelectionItems[MAX_PLAYERS][mS_SELECTION_ITEMS];
  43. new gSelectionItemsTag[MAX_PLAYERS][mS_SELECTION_ITEMS];
  44. new gItemAt[MAX_PLAYERS];
  45. #define mS_LIST_START 0
  46. #define mS_LIST_END 1
  47. new gLists[mS_TOTAL_LISTS][2]; // list information start/end index
  48. #define mS_ITEM_MODEL 0
  49. #define mS_ITEM_ROT_ZOOM_ID 1
  50. new gItemList[mS_TOTAL_ITEMS][2];
  51. new Float:gRotZoom[mS_TOTAL_ROT_ZOOM][4]; // Array for saving rotation and zoom info
  52. new gItemAmount = 0; // Amount of items used
  53. new gListAmount = 0; // Amount of lists used
  54. new gRotZoomAmount = 0; // Amount of Rotation/Zoom informations used
  55. //------------------------------------------------
  56. stock mS_GetNumberOfPages(ListID)
  57. {
  58. new ItemAmount = mS_GetAmountOfListItems(ListID);
  59. if((ItemAmount >= mS_SELECTION_ITEMS) && (ItemAmount % mS_SELECTION_ITEMS) == 0)
  60. {
  61. return (ItemAmount / mS_SELECTION_ITEMS);
  62. }
  63. else return (ItemAmount / mS_SELECTION_ITEMS) + 1;
  64. }
  65. //------------------------------------------------
  66. stock mS_GetNumberOfPagesEx(playerid)
  67. {
  68. new ItemAmount = mS_GetAmountOfListItemsEx(playerid);
  69. if((ItemAmount >= mS_SELECTION_ITEMS) && (ItemAmount % mS_SELECTION_ITEMS) == 0)
  70. {
  71. return (ItemAmount / mS_SELECTION_ITEMS);
  72. }
  73. else return (ItemAmount / mS_SELECTION_ITEMS) + 1;
  74. }
  75. //------------------------------------------------
  76. stock mS_GetAmountOfListItems(ListID)
  77. {
  78. return (gLists[ListID][mS_LIST_END] - gLists[ListID][mS_LIST_START])+1;
  79. }
  80. //------------------------------------------------
  81. stock mS_GetAmountOfListItemsEx(playerid)
  82. {
  83. return GetPVarInt(playerid, "mS_custom_item_amount");
  84. }
  85. //------------------------------------------------
  86. stock mS_GetPlayerCurrentListID(playerid)
  87. {
  88. if(GetPVarInt(playerid, "mS_list_active") == 1) return GetPVarInt(playerid, "mS_list_id");
  89. else return mS_INVALID_LISTID;
  90. }
  91. //------------------------------------------------
  92. stock PlayerText:mS_CreateCurrentPageTextDraw(playerid, Float:Xpos, Float:Ypos)
  93. {
  94. new PlayerText:txtInit;
  95. txtInit = CreatePlayerTextDraw(playerid, Xpos, Ypos, "0/0");
  96. PlayerTextDrawUseBox(playerid, txtInit, 0);
  97. PlayerTextDrawLetterSize(playerid, txtInit, 0.4, 1.1);
  98. PlayerTextDrawFont(playerid, txtInit, 1);
  99. PlayerTextDrawSetShadow(playerid, txtInit, 0);
  100. PlayerTextDrawSetOutline(playerid, txtInit, 1);
  101. PlayerTextDrawColor(playerid, txtInit, 0xACCBF1FF);
  102. PlayerTextDrawShow(playerid, txtInit);
  103. return txtInit;
  104. }
  105. //------------------------------------------------
  106. // Creates a button textdraw and returns the textdraw ID.
  107. stock PlayerText:mS_CreatePlayerDialogButton(playerid, Float:Xpos, Float:Ypos, Float:Width, Float:Height, button_text[])
  108. {
  109. new PlayerText:txtInit;
  110. txtInit = CreatePlayerTextDraw(playerid, Xpos, Ypos, button_text);
  111. PlayerTextDrawUseBox(playerid, txtInit, 1);
  112. PlayerTextDrawBoxColor(playerid, txtInit, 0x000000FF);
  113. PlayerTextDrawBackgroundColor(playerid, txtInit, 0x000000FF);
  114. PlayerTextDrawLetterSize(playerid, txtInit, 0.4, 1.1);
  115. PlayerTextDrawFont(playerid, txtInit, 1);
  116. PlayerTextDrawSetShadow(playerid, txtInit, 0); // no shadow
  117. PlayerTextDrawSetOutline(playerid, txtInit, 0);
  118. PlayerTextDrawColor(playerid, txtInit, 0x4A5A6BFF);
  119. PlayerTextDrawSetSelectable(playerid, txtInit, 1);
  120. PlayerTextDrawAlignment(playerid, txtInit, 2);
  121. PlayerTextDrawTextSize(playerid, txtInit, Height, Width); // The width and height are reversed for centering.. something the game does <g>
  122. PlayerTextDrawShow(playerid, txtInit);
  123. return txtInit;
  124. }
  125. //------------------------------------------------
  126. stock PlayerText:mS_CreatePlayerHeaderTextDraw(playerid, Float:Xpos, Float:Ypos, header_text[])
  127. {
  128. new PlayerText:txtInit;
  129. txtInit = CreatePlayerTextDraw(playerid, Xpos, Ypos, header_text);
  130. PlayerTextDrawUseBox(playerid, txtInit, 0);
  131. PlayerTextDrawLetterSize(playerid, txtInit, 1.25, 3.0);
  132. PlayerTextDrawFont(playerid, txtInit, 0);
  133. PlayerTextDrawSetShadow(playerid, txtInit, 0);
  134. PlayerTextDrawSetOutline(playerid, txtInit, 1);
  135. PlayerTextDrawColor(playerid, txtInit, 0xACCBF1FF);
  136. PlayerTextDrawShow(playerid, txtInit);
  137. return txtInit;
  138. }
  139. //------------------------------------------------
  140. stock PlayerText:mS_CreatePlayerBGTextDraw(playerid, Float:Xpos, Float:Ypos, Float:Width, Float:Height, bgcolor)
  141. {
  142. new PlayerText:txtBackground = CreatePlayerTextDraw(playerid, Xpos, Ypos," ~n~"); // enough space for everyone
  143. PlayerTextDrawUseBox(playerid, txtBackground, 1);
  144. PlayerTextDrawBoxColor(playerid, txtBackground, bgcolor);
  145. PlayerTextDrawLetterSize(playerid, txtBackground, 5.0, 5.0);
  146. PlayerTextDrawFont(playerid, txtBackground, 0);
  147. PlayerTextDrawSetShadow(playerid, txtBackground, 0);
  148. PlayerTextDrawSetOutline(playerid, txtBackground, 0);
  149. PlayerTextDrawColor(playerid, txtBackground,0x000000FF);
  150. PlayerTextDrawTextSize(playerid, txtBackground, Width, Height);
  151. PlayerTextDrawBackgroundColor(playerid, txtBackground, bgcolor);
  152. PlayerTextDrawShow(playerid, txtBackground);
  153. return txtBackground;
  154. }
  155. //------------------------------------------------
  156. // Creates a model preview sprite
  157. stock PlayerText:mS_CreateMPTextDraw(playerid, modelindex, Float:Xpos, Float:Ypos, Float:Xrot, Float:Yrot, Float:Zrot, Float:mZoom, Float:width, Float:height, bgcolor)
  158. {
  159. new PlayerText:txtPlayerSprite = CreatePlayerTextDraw(playerid, Xpos, Ypos, ""); // it has to be set with SetText later
  160. PlayerTextDrawFont(playerid, txtPlayerSprite, TEXT_DRAW_FONT_MODEL_PREVIEW);
  161. PlayerTextDrawColor(playerid, txtPlayerSprite, 0xFFFFFFFF);
  162. PlayerTextDrawBackgroundColor(playerid, txtPlayerSprite, bgcolor);
  163. PlayerTextDrawTextSize(playerid, txtPlayerSprite, width, height); // Text size is the Width:Height
  164. PlayerTextDrawSetPreviewModel(playerid, txtPlayerSprite, modelindex);
  165. PlayerTextDrawSetPreviewRot(playerid,txtPlayerSprite, Xrot, Yrot, Zrot, mZoom);
  166. PlayerTextDrawSetSelectable(playerid, txtPlayerSprite, 1);
  167. PlayerTextDrawShow(playerid,txtPlayerSprite);
  168. return txtPlayerSprite;
  169. }
  170. //------------------------------------------------
  171. stock mS_DestroyPlayerMPs(playerid)
  172. {
  173. new x=0;
  174. while(x != mS_SELECTION_ITEMS) {
  175. if(gSelectionItems[playerid][x] != PlayerText:INVALID_TEXT_DRAW) {
  176. PlayerTextDrawDestroy(playerid, gSelectionItems[playerid][x]);
  177. gSelectionItems[playerid][x] = PlayerText:INVALID_TEXT_DRAW;
  178. }
  179. x++;
  180. }
  181. }
  182. //------------------------------------------------
  183. stock mS_ShowPlayerMPs(playerid)
  184. {
  185. new bgcolor = GetPVarInt(playerid, "mS_previewBGcolor");
  186. new x=0;
  187. new Float:BaseX = mS_DIALOG_BASE_X;
  188. new Float:BaseY = mS_DIALOG_BASE_Y - (mS_SPRITE_DIM_Y * 0.33); // down a bit
  189. new linetracker = 0;
  190. new mS_listID = mS_GetPlayerCurrentListID(playerid);
  191. if(mS_listID == mS_CUSTOM_LISTID)
  192. {
  193. new itemat = (GetPVarInt(playerid, "mS_list_page") * mS_SELECTION_ITEMS);
  194. new Float:rotzoom[4];
  195. rotzoom[0] = GetPVarFloat(playerid, "mS_custom_Xrot");
  196. rotzoom[1] = GetPVarFloat(playerid, "mS_custom_Yrot");
  197. rotzoom[2] = GetPVarFloat(playerid, "mS_custom_Zrot");
  198. rotzoom[3] = GetPVarFloat(playerid, "mS_custom_Zoom");
  199. new itemamount = mS_GetAmountOfListItemsEx(playerid);
  200. // Destroy any previous ones created
  201. mS_DestroyPlayerMPs(playerid);
  202. while(x != mS_SELECTION_ITEMS && itemat < (itemamount)) {
  203. if(linetracker == 0) {
  204. BaseX = mS_DIALOG_BASE_X + 25.0; // in a bit from the box
  205. BaseY += mS_SPRITE_DIM_Y + 1.0; // move on the Y for the next line
  206. }
  207. gSelectionItems[playerid][x] = mS_CreateMPTextDraw(playerid, gCustomList[playerid][itemat], BaseX, BaseY, rotzoom[0], rotzoom[1], rotzoom[2], rotzoom[3], mS_SPRITE_DIM_X, mS_SPRITE_DIM_Y, bgcolor);
  208. gSelectionItemsTag[playerid][x] = gCustomList[playerid][itemat];
  209. BaseX += mS_SPRITE_DIM_X + 1.0; // move on the X for the next sprite
  210. linetracker++;
  211. if(linetracker == mS_ITEMS_PER_LINE) linetracker = 0;
  212. itemat++;
  213. x++;
  214. }
  215. }
  216. else
  217. {
  218. new itemat = (gLists[mS_listID][mS_LIST_START] + (GetPVarInt(playerid, "mS_list_page") * mS_SELECTION_ITEMS));
  219. // Destroy any previous ones created
  220. mS_DestroyPlayerMPs(playerid);
  221. while(x != mS_SELECTION_ITEMS && itemat < (gLists[mS_listID][mS_LIST_END]+1)) {
  222. if(linetracker == 0) {
  223. BaseX = mS_DIALOG_BASE_X + 25.0; // in a bit from the box
  224. BaseY += mS_SPRITE_DIM_Y + 1.0; // move on the Y for the next line
  225. }
  226. new rzID = gItemList[itemat][mS_ITEM_ROT_ZOOM_ID]; // avoid long line
  227. if(rzID > -1) gSelectionItems[playerid][x] = mS_CreateMPTextDraw(playerid, gItemList[itemat][mS_ITEM_MODEL], BaseX, BaseY, gRotZoom[rzID][0], gRotZoom[rzID][1], gRotZoom[rzID][2], gRotZoom[rzID][3], mS_SPRITE_DIM_X, mS_SPRITE_DIM_Y, bgcolor);
  228. else gSelectionItems[playerid][x] = mS_CreateMPTextDraw(playerid, gItemList[itemat][mS_ITEM_MODEL], BaseX, BaseY, 0.0, 0.0, 0.0, 1.0, mS_SPRITE_DIM_X, mS_SPRITE_DIM_Y, bgcolor);
  229. gSelectionItemsTag[playerid][x] = gItemList[itemat][mS_ITEM_MODEL];
  230. BaseX += mS_SPRITE_DIM_X + 1.0; // move on the X for the next sprite
  231. linetracker++;
  232. if(linetracker == mS_ITEMS_PER_LINE) linetracker = 0;
  233. itemat++;
  234. x++;
  235. }
  236. }
  237. }
  238. //------------------------------------------------
  239. stock mS_UpdatePageTextDraw(playerid)
  240. {
  241. new PageText[64+1];
  242. new listID = mS_GetPlayerCurrentListID(playerid);
  243. if(listID == mS_CUSTOM_LISTID)
  244. {
  245. format(PageText, 64, "%d/%d", GetPVarInt(playerid,"mS_list_page") + 1, mS_GetNumberOfPagesEx(playerid));
  246. PlayerTextDrawSetString(playerid, gCurrentPageTextDrawId[playerid], PageText);
  247. }
  248. else
  249. {
  250. format(PageText, 64, "%d/%d", GetPVarInt(playerid,"mS_list_page") + 1, mS_GetNumberOfPages(listID));
  251. PlayerTextDrawSetString(playerid, gCurrentPageTextDrawId[playerid], PageText);
  252. }
  253. }
  254. //------------------------------------------------
  255. stock ShowModelSelectionMenu(playerid, ListID, header_text[], dialogBGcolor = 0x4A5A6BBB, previewBGcolor = 0x88888899 , tdSelectionColor = 0xFFFF00AA)
  256. {
  257. if(!(0 <= ListID < mS_TOTAL_LISTS && gLists[ListID][mS_LIST_START] != gLists[ListID][mS_LIST_END])) return 0;
  258. mS_DestroySelectionMenu(playerid);
  259. SetPVarInt(playerid, "mS_list_page", 0);
  260. SetPVarInt(playerid, "mS_list_id", ListID);
  261. SetPVarInt(playerid, "mS_list_active", 1);
  262. SetPVarInt(playerid, "mS_list_time", GetTickCount());
  263. gBackgroundTextDrawId[playerid] = mS_CreatePlayerBGTextDraw(playerid, mS_DIALOG_BASE_X, mS_DIALOG_BASE_Y + 20.0, mS_DIALOG_WIDTH, mS_DIALOG_HEIGHT, dialogBGcolor);
  264. gHeaderTextDrawId[playerid] = mS_CreatePlayerHeaderTextDraw(playerid, mS_DIALOG_BASE_X, mS_DIALOG_BASE_Y, header_text);
  265. gCurrentPageTextDrawId[playerid] = mS_CreateCurrentPageTextDraw(playerid, mS_DIALOG_WIDTH - 30.0, mS_DIALOG_BASE_Y + 15.0);
  266. gNextButtonTextDrawId[playerid] = mS_CreatePlayerDialogButton(playerid, mS_DIALOG_WIDTH - 30.0, mS_DIALOG_BASE_Y+mS_DIALOG_HEIGHT+100.0, 50.0, 16.0, mS_NEXT_TEXT);
  267. gPrevButtonTextDrawId[playerid] = mS_CreatePlayerDialogButton(playerid, mS_DIALOG_WIDTH - 90.0, mS_DIALOG_BASE_Y+mS_DIALOG_HEIGHT+100.0, 50.0, 16.0, mS_PREV_TEXT);
  268. gCancelButtonTextDrawId[playerid] = mS_CreatePlayerDialogButton(playerid, mS_DIALOG_WIDTH - 150.0, mS_DIALOG_BASE_Y+mS_DIALOG_HEIGHT+100.0, 50.0, 16.0, mS_CANCEL_TEXT);
  269. SetPVarInt(playerid, "mS_previewBGcolor", previewBGcolor);
  270. mS_ShowPlayerMPs(playerid);
  271. mS_UpdatePageTextDraw(playerid);
  272. SelectTextDraw(playerid, tdSelectionColor);
  273. return 1;
  274. }
  275. //------------------------------------------------------------
  276. stock ShowModelSelectionMenuEx(playerid, items_array[], item_amount, header_text[], extraid, Float:Xrot = 0.0, Float:Yrot = 0.0, Float:Zrot = 0.0, Float:mZoom = 1.0, dialogBGcolor = 0x4A5A6BBB, previewBGcolor = 0x88888899 , tdSelectionColor = 0xFFFF00AA)
  277. {
  278. mS_DestroySelectionMenu(playerid);
  279. if(item_amount > mS_CUSTOM_MAX_ITEMS)
  280. {
  281. item_amount = mS_CUSTOM_MAX_ITEMS;
  282. print("-mSelection- WARNING: Too many items given to \"ShowModelSelectionMenuEx\", increase \"mS_CUSTOM_MAX_ITEMS\" to fix this");
  283. }
  284. if(item_amount > 0)
  285. {
  286. for(new i=0;i<item_amount;i++)
  287. {
  288. gCustomList[playerid][i] = items_array[i];
  289. }
  290. SetPVarInt(playerid, "mS_list_page", 0);
  291. SetPVarInt(playerid, "mS_list_id", mS_CUSTOM_LISTID);
  292. SetPVarInt(playerid, "mS_list_active", 1);
  293. SetPVarInt(playerid, "mS_list_time", GetTickCount());
  294. SetPVarInt(playerid, "mS_custom_item_amount", item_amount);
  295. SetPVarFloat(playerid, "mS_custom_Xrot", Xrot);
  296. SetPVarFloat(playerid, "mS_custom_Yrot", Yrot);
  297. SetPVarFloat(playerid, "mS_custom_Zrot", Zrot);
  298. SetPVarFloat(playerid, "mS_custom_Zoom", mZoom);
  299. SetPVarInt(playerid, "mS_custom_extraid", extraid);
  300. gBackgroundTextDrawId[playerid] = mS_CreatePlayerBGTextDraw(playerid, mS_DIALOG_BASE_X, mS_DIALOG_BASE_Y + 20.0, mS_DIALOG_WIDTH, mS_DIALOG_HEIGHT, dialogBGcolor);
  301. gHeaderTextDrawId[playerid] = mS_CreatePlayerHeaderTextDraw(playerid, mS_DIALOG_BASE_X, mS_DIALOG_BASE_Y, header_text);
  302. gCurrentPageTextDrawId[playerid] = mS_CreateCurrentPageTextDraw(playerid, mS_DIALOG_WIDTH - 30.0, mS_DIALOG_BASE_Y + 15.0);
  303. gNextButtonTextDrawId[playerid] = mS_CreatePlayerDialogButton(playerid, mS_DIALOG_WIDTH - 30.0, mS_DIALOG_BASE_Y+mS_DIALOG_HEIGHT+100.0, 50.0, 16.0, mS_NEXT_TEXT);
  304. gPrevButtonTextDrawId[playerid] = mS_CreatePlayerDialogButton(playerid, mS_DIALOG_WIDTH - 90.0, mS_DIALOG_BASE_Y+mS_DIALOG_HEIGHT+100.0, 50.0, 16.0, mS_PREV_TEXT);
  305. gCancelButtonTextDrawId[playerid] = mS_CreatePlayerDialogButton(playerid, mS_DIALOG_WIDTH - 150.0, mS_DIALOG_BASE_Y+mS_DIALOG_HEIGHT+100.0, 50.0, 16.0, mS_CANCEL_TEXT);
  306. SetPVarInt(playerid, "mS_previewBGcolor", previewBGcolor);
  307. mS_ShowPlayerMPs(playerid);
  308. mS_UpdatePageTextDraw(playerid);
  309. SelectTextDraw(playerid, tdSelectionColor);
  310. return 1;
  311. }
  312. return 0;
  313. }
  314. //------------------------------------------------
  315. stock HideModelSelectionMenu(playerid)
  316. {
  317. mS_DestroySelectionMenu(playerid);
  318. SetPVarInt(playerid, "mS_ignore_next_esc", 1);
  319. CancelSelectTextDraw(playerid);
  320. return 1;
  321. }
  322. //------------------------------------------------
  323. stock mS_DestroySelectionMenu(playerid)
  324. {
  325. if(GetPVarInt(playerid, "mS_list_active") == 1)
  326. {
  327. if(mS_GetPlayerCurrentListID(playerid) == mS_CUSTOM_LISTID)
  328. {
  329. DeletePVar(playerid, "mS_custom_Xrot");
  330. DeletePVar(playerid, "mS_custom_Yrot");
  331. DeletePVar(playerid, "mS_custom_Zrot");
  332. DeletePVar(playerid, "mS_custom_Zoom");
  333. DeletePVar(playerid, "mS_custom_extraid");
  334. DeletePVar(playerid, "mS_custom_item_amount");
  335. }
  336. DeletePVar(playerid, "mS_list_time");
  337. SetPVarInt(playerid, "mS_list_active", 0);
  338. mS_DestroyPlayerMPs(playerid);
  339. PlayerTextDrawDestroy(playerid, gHeaderTextDrawId[playerid]);
  340. PlayerTextDrawDestroy(playerid, gBackgroundTextDrawId[playerid]);
  341. PlayerTextDrawDestroy(playerid, gCurrentPageTextDrawId[playerid]);
  342. PlayerTextDrawDestroy(playerid, gNextButtonTextDrawId[playerid]);
  343. PlayerTextDrawDestroy(playerid, gPrevButtonTextDrawId[playerid]);
  344. PlayerTextDrawDestroy(playerid, gCancelButtonTextDrawId[playerid]);
  345. gHeaderTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  346. gBackgroundTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  347. gCurrentPageTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  348. gNextButtonTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  349. gPrevButtonTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  350. gCancelButtonTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  351. }
  352. }
  353. //------------------------------------------------
  354. public OnPlayerConnect(playerid)
  355. {
  356. // Init all of the textdraw related globals
  357. gHeaderTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  358. gBackgroundTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  359. gCurrentPageTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  360. gNextButtonTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  361. gPrevButtonTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  362. gCancelButtonTextDrawId[playerid] = PlayerText:INVALID_TEXT_DRAW;
  363. for(new x=0; x < mS_SELECTION_ITEMS; x++) {
  364. gSelectionItems[playerid][x] = PlayerText:INVALID_TEXT_DRAW;
  365. }
  366. gItemAt[playerid] = 0;
  367. return CallLocalFunction("MP_OPC", "i", playerid);
  368. }
  369. #if defined _ALS_OnPlayerConnect
  370. #undef OnPlayerConnect
  371. #else
  372. #define _ALS_OnPlayerConnect
  373. #endif
  374. #define OnPlayerConnect MP_OPC
  375. forward MP_OPC(playerid);
  376. //-------------------------------------------
  377. // Even though only Player* textdraws are used in this script,
  378. // OnPlayerClickTextDraw is still required to handle ESC
  379. public OnPlayerClickTextDraw(playerid, Text:clickedid)
  380. {
  381. if(GetPVarInt(playerid, "mS_ignore_next_esc") == 1) {
  382. SetPVarInt(playerid, "mS_ignore_next_esc", 0);
  383. return CallLocalFunction("MP_OPCTD", "ii", playerid, _:clickedid);
  384. }
  385. if(GetPVarInt(playerid, "mS_list_active") == 0) return CallLocalFunction("MP_OPCTD", "ii", playerid, _:clickedid);
  386. // Handle: They cancelled (with ESC)
  387. if(clickedid == Text:INVALID_TEXT_DRAW) {
  388. new listid = mS_GetPlayerCurrentListID(playerid);
  389. if(listid == mS_CUSTOM_LISTID)
  390. {
  391. new extraid = GetPVarInt(playerid, "mS_custom_extraid");
  392. mS_DestroySelectionMenu(playerid);
  393. CallLocalFunction("OnPlayerModelSelectionEx", "dddd", playerid, 0, extraid, -1);
  394. PlayerPlaySound(playerid, 1085, 0.0, 0.0, 0.0);
  395. }
  396. else
  397. {
  398. mS_DestroySelectionMenu(playerid);
  399. CallLocalFunction("OnPlayerModelSelection", "dddd", playerid, 0, listid, -1);
  400. PlayerPlaySound(playerid, 1085, 0.0, 0.0, 0.0);
  401. }
  402. return 1;
  403. }
  404. return CallLocalFunction("MP_OPCTD", "ii", playerid, _:clickedid);
  405. }
  406. #if defined _ALS_OnPlayerClickTextDraw
  407. #undef OnPlayerClickTextDraw
  408. #else
  409. #define _ALS_OnPlayerClickTextDraw
  410. #endif
  411. #define OnPlayerClickTextDraw MP_OPCTD
  412. forward MP_OPCTD(playerid, Text:clickedid);
  413. //------------------------------------------------
  414. public OnPlayerClickPlayerTextDraw(playerid, PlayerText:playertextid)
  415. {
  416. if(GetPVarInt(playerid, "mS_list_active") == 0 || (GetTickCount()-GetPVarInt(playerid, "mS_list_time")) < 200 /* Disable instant selection */) return CallLocalFunction("MP_OPCPTD", "ii", playerid, _:playertextid);
  417. new curpage = GetPVarInt(playerid, "mS_list_page");
  418. // Handle: cancel button
  419. if(playertextid == gCancelButtonTextDrawId[playerid]) {
  420. new listID = mS_GetPlayerCurrentListID(playerid);
  421. if(listID == mS_CUSTOM_LISTID)
  422. {
  423. new extraid = GetPVarInt(playerid, "mS_custom_extraid");
  424. HideModelSelectionMenu(playerid);
  425. CallLocalFunction("OnPlayerModelSelectionEx", "dddd", playerid, 0, extraid, -1);
  426. PlayerPlaySound(playerid, 1085, 0.0, 0.0, 0.0);
  427. }
  428. else
  429. {
  430. HideModelSelectionMenu(playerid);
  431. CallLocalFunction("OnPlayerModelSelection", "dddd", playerid, 0, listID, -1);
  432. PlayerPlaySound(playerid, 1085, 0.0, 0.0, 0.0);
  433. }
  434. return 1;
  435. }
  436. // Handle: next button
  437. if(playertextid == gNextButtonTextDrawId[playerid]) {
  438. new listID = mS_GetPlayerCurrentListID(playerid);
  439. if(listID == mS_CUSTOM_LISTID)
  440. {
  441. if(curpage < (mS_GetNumberOfPagesEx(playerid) - 1)) {
  442. SetPVarInt(playerid, "mS_list_page", curpage + 1);
  443. mS_ShowPlayerMPs(playerid);
  444. mS_UpdatePageTextDraw(playerid);
  445. PlayerPlaySound(playerid, 1083, 0.0, 0.0, 0.0);
  446. } else {
  447. PlayerPlaySound(playerid, 1085, 0.0, 0.0, 0.0);
  448. }
  449. }
  450. else
  451. {
  452. if(curpage < (mS_GetNumberOfPages(listID) - 1)) {
  453. SetPVarInt(playerid, "mS_list_page", curpage + 1);
  454. mS_ShowPlayerMPs(playerid);
  455. mS_UpdatePageTextDraw(playerid);
  456. PlayerPlaySound(playerid, 1083, 0.0, 0.0, 0.0);
  457. } else {
  458. PlayerPlaySound(playerid, 1085, 0.0, 0.0, 0.0);
  459. }
  460. }
  461. return 1;
  462. }
  463. // Handle: previous button
  464. if(playertextid == gPrevButtonTextDrawId[playerid]) {
  465. if(curpage > 0) {
  466. SetPVarInt(playerid, "mS_list_page", curpage - 1);
  467. mS_ShowPlayerMPs(playerid);
  468. mS_UpdatePageTextDraw(playerid);
  469. PlayerPlaySound(playerid, 1084, 0.0, 0.0, 0.0);
  470. } else {
  471. PlayerPlaySound(playerid, 1085, 0.0, 0.0, 0.0);
  472. }
  473. return 1;
  474. }
  475. // Search in the array of textdraws used for the items
  476. new x=0;
  477. while(x != mS_SELECTION_ITEMS) {
  478. if(playertextid == gSelectionItems[playerid][x]) {
  479. new listID = mS_GetPlayerCurrentListID(playerid);
  480. if(listID == mS_CUSTOM_LISTID)
  481. {
  482. PlayerPlaySound(playerid, 1083, 0.0, 0.0, 0.0);
  483. new item_id = gSelectionItemsTag[playerid][x];
  484. new extraid = GetPVarInt(playerid, "mS_custom_extraid");
  485. HideModelSelectionMenu(playerid);
  486. CallLocalFunction("OnPlayerModelSelectionEx", "dddd", playerid, 1, extraid, item_id);
  487. return 1;
  488. }
  489. else
  490. {
  491. PlayerPlaySound(playerid, 1083, 0.0, 0.0, 0.0);
  492. new item_id = gSelectionItemsTag[playerid][x];
  493. HideModelSelectionMenu(playerid);
  494. CallLocalFunction("OnPlayerModelSelection", "dddd", playerid, 1, listID, item_id);
  495. return 1;
  496. }
  497. }
  498. x++;
  499. }
  500. return CallLocalFunction("MP_OPCPTD", "ii", playerid, _:playertextid);
  501. }
  502. #if defined _ALS_OnPlayerClickPlayerTD
  503. #undef OnPlayerClickPlayerTextDraw
  504. #else
  505. #define _ALS_OnPlayerClickPlayerTD
  506. #endif
  507. #define OnPlayerClickPlayerTextDraw MP_OPCPTD
  508. forward MP_OPCPTD(playerid, PlayerText:playertextid);
  509. //------------------------------------------------------------------
  510. stock LoadModelSelectionMenu(f_name[])
  511. {
  512. new File:f, str[75];
  513. format(str, sizeof(str), "%s", f_name);
  514. f = fopen(str, io_read);
  515. if( !f ) {
  516. printf("-mSelection- WARNING: Failed to load list: \"%s\"", f_name);
  517. return mS_INVALID_LISTID;
  518. }
  519. if(gListAmount >= mS_TOTAL_LISTS)
  520. {
  521. printf("-mSelection- WARNING: Reached maximum amount of lists, increase \"mS_TOTAL_LISTS\"", f_name);
  522. return mS_INVALID_LISTID;
  523. }
  524. new tmp_ItemAmount = gItemAmount; // copy value if loading fails
  525. new line[128], idxx;
  526. while(fread(f,line,sizeof(line),false))
  527. {
  528. if(tmp_ItemAmount >= mS_TOTAL_ITEMS)
  529. {
  530. printf("-mSelection- WARNING: Reached maximum amount of items, increase \"mS_TOTAL_ITEMS\"", f_name);
  531. break;
  532. }
  533. idxx = 0;
  534. if(!line[0]) continue;
  535. new mID = strval( mS_strtok(line,idxx) );
  536. if(0 <= mID < 20000)
  537. {
  538. gItemList[tmp_ItemAmount][mS_ITEM_MODEL] = mID;
  539. new tmp_mS_strtok[20];
  540. new Float:mRotation[3], Float:mZoom = 1.0;
  541. new bool:useRotation = false;
  542. tmp_mS_strtok = mS_strtok(line,idxx);
  543. if(tmp_mS_strtok[0]) {
  544. useRotation = true;
  545. mRotation[0] = floatstr(tmp_mS_strtok);
  546. }
  547. tmp_mS_strtok = mS_strtok(line,idxx);
  548. if(tmp_mS_strtok[0]) {
  549. useRotation = true;
  550. mRotation[1] = floatstr(tmp_mS_strtok);
  551. }
  552. tmp_mS_strtok = mS_strtok(line,idxx);
  553. if(tmp_mS_strtok[0]) {
  554. useRotation = true;
  555. mRotation[2] = floatstr(tmp_mS_strtok);
  556. }
  557. tmp_mS_strtok = mS_strtok(line,idxx);
  558. if(tmp_mS_strtok[0]) {
  559. useRotation = true;
  560. mZoom = floatstr(tmp_mS_strtok);
  561. }
  562. if(useRotation)
  563. {
  564. new bool:foundRotZoom = false;
  565. for(new i=0; i < gRotZoomAmount; i++)
  566. {
  567. if(gRotZoom[i][0] == mRotation[0] && gRotZoom[i][1] == mRotation[1] && gRotZoom[i][2] == mRotation[2] && gRotZoom[i][3] == mZoom)
  568. {
  569. foundRotZoom = true;
  570. gItemList[tmp_ItemAmount][mS_ITEM_ROT_ZOOM_ID] = i;
  571. break;
  572. }
  573. }
  574. if(gRotZoomAmount < mS_TOTAL_ROT_ZOOM)
  575. {
  576. if(!foundRotZoom)
  577. {
  578. gRotZoom[gRotZoomAmount][0] = mRotation[0];
  579. gRotZoom[gRotZoomAmount][1] = mRotation[1];
  580. gRotZoom[gRotZoomAmount][2] = mRotation[2];
  581. gRotZoom[gRotZoomAmount][3] = mZoom;
  582. gItemList[tmp_ItemAmount][mS_ITEM_ROT_ZOOM_ID] = gRotZoomAmount;
  583. gRotZoomAmount++;
  584. }
  585. }
  586. else print("-mSelection- WARNING: Not able to save rotation/zoom information. Reached maximum rotation/zoom information count. Increase '#define mS_TOTAL_ROT_ZOOM' to fix the issue");
  587. }
  588. else gItemList[tmp_ItemAmount][mS_ITEM_ROT_ZOOM_ID] = -1;
  589. tmp_ItemAmount++;
  590. }
  591. }
  592. if(tmp_ItemAmount > gItemAmount) // any models loaded ?
  593. {
  594. gLists[gListAmount][mS_LIST_START] = gItemAmount;
  595. gItemAmount = tmp_ItemAmount; // copy back
  596. gLists[gListAmount][mS_LIST_END] = (gItemAmount-1);
  597. gListAmount++;
  598. return (gListAmount-1);
  599. }
  600. printf("-mSelection- WARNING: No Items found in file: %s", f_name);
  601. return mS_INVALID_LISTID;
  602. }
  603. stock mS_strtok(const string[], &index)
  604. {
  605. new length = strlen(string);
  606. while ((index < length) && (string[index] <= ' '))
  607. {
  608. index++;
  609. }
  610. new offset = index;
  611. new result[20];
  612. while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1)))
  613. {
  614. result[index - offset] = string[index];
  615. index++;
  616. }
  617. result[index - offset] = EOS;
  618. return result;
  619. }