SAMP Gitlab CI Test
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

770 lines
24 KiB

5 years ago
  1. // -----------------------------------------------------------------------------
  2. // -----------------------------------------------------------------------------
  3. // Example Filterscript for the new LS Apartments 1 Building with Elevator
  4. // -----------------------------------------------------------------------
  5. // Original elevator code by Zamaroht in 2010
  6. //
  7. // Updated by Kye in 2011
  8. // * Added a sound effect for the elevator starting/stopping
  9. //
  10. // Edited by Matite in January 2015
  11. // * Added code to remove the existing building, add the new building and
  12. // edited the elevator code so it works in this new building
  13. //
  14. // Updated to v1.02 by Matite in February 2015
  15. // * Added code for the new car park object and edited the elevator to
  16. // include the car park
  17. //
  18. // This script creates the new LS Apartments 1 building object, removes the
  19. // existing GTASA building object, adds the new car park object and creates
  20. // an elevator that can be used to travel between all levels.
  21. //
  22. // You can un-comment the OnPlayerCommandText callback below to enable a simple
  23. // teleport command (/lsa) that teleports you to the LS Apartments 1 building.
  24. //
  25. // Warning...
  26. // This script uses a total of:
  27. // * 27 objects = 1 for the elevator, 2 for the elevator doors, 22 for the
  28. // elevator floor doors, 1 for the replacement LS Apartments 1 building
  29. // and 1 for the car park
  30. // * 12 3D Text Labels = 11 on the floors and 1 in the elevator
  31. // * 1 dialog (for the elevator - dialog ID 876)
  32. // -----------------------------------------------------------------------------
  33. // -----------------------------------------------------------------------------
  34. // -----------------------------------------------------------------------------
  35. // Includes
  36. // --------
  37. // SA-MP include
  38. #include <a_samp>
  39. // For PlaySoundForPlayersInRange()
  40. #include "../include/gl_common.inc"
  41. // -----------------------------------------------------------------------------
  42. // Defines
  43. // -------
  44. // Movement speed of the elevator
  45. #define ELEVATOR_SPEED (5.0)
  46. // Movement speed of the doors
  47. #define DOORS_SPEED (5.0)
  48. // Time in ms that the elevator will wait in each floor before continuing with the queue...
  49. // be sure to give enough time for doors to open
  50. #define ELEVATOR_WAIT_TIME (5000)
  51. // Dialog ID for the LS Apartments building elevator dialog
  52. #define DIALOG_ID (876)
  53. // Position defines
  54. #define Y_DOOR_CLOSED (-1180.535917)
  55. #define Y_DOOR_R_OPENED Y_DOOR_CLOSED - 1.6
  56. #define Y_DOOR_L_OPENED Y_DOOR_CLOSED + 1.6
  57. #define GROUND_Z_COORD (20.879316)
  58. #define ELEVATOR_OFFSET (0.059523)
  59. #define X_ELEVATOR_POS (1181.622924)
  60. #define Y_ELEVATOR_POS (-1180.554687)
  61. // Elevator state defines
  62. #define ELEVATOR_STATE_IDLE (0)
  63. #define ELEVATOR_STATE_WAITING (1)
  64. #define ELEVATOR_STATE_MOVING (2)
  65. // Invalid floor define
  66. #define INVALID_FLOOR (-1)
  67. // Used for chat text messages
  68. #define COLOR_MESSAGE_YELLOW 0xFFDD00AA
  69. // -----------------------------------------------------------------------------
  70. // Constants
  71. // ---------
  72. // Elevator floor names for the 3D text labels
  73. static FloorNames[11][] =
  74. {
  75. "Car Park",
  76. "Ground Floor",
  77. "First Floor",
  78. "Second Floor",
  79. "Third Floor",
  80. "Fourth Floor",
  81. "Fifth Floor",
  82. "Sixth Floor",
  83. "Seventh Floor",
  84. "Eighth Floor",
  85. "Ninth Floor"
  86. };
  87. // Elevator floor Z heights
  88. static Float:FloorZOffsets[11] =
  89. {
  90. 0.0, // Car Park
  91. 13.604544, // Ground Floor
  92. 18.808519, // First Floor = 13.604544 + 5.203975
  93. 24.012494, // Second Floor = 18.808519 + 5.203975
  94. 29.216469, // Third Floor = 24.012494 + 5.203975
  95. 34.420444, // Fourth Floor = 29.216469 + 5.203975
  96. 39.624419, // Fifth Floor = 34.420444 + 5.203975
  97. 44.828394, // Sixth Floor = 39.624419 + 5.203975
  98. 50.032369, // Seventh Floor = 44.828394 + 5.203975
  99. 55.236344, // Eighth Floor = 50.032369 + 5.203975
  100. 60.440319 // Ninth Floor = 55.236344 + 5.203975
  101. };
  102. // ------------------------------------------------------------------------------
  103. // Variables
  104. // ---------
  105. // Stores the created object number of the replacement building so it can be
  106. // destroyed when the filterscript is unloaded
  107. new LSApartments1Object;
  108. // Stores the created object number of the new cark park so it can be
  109. // destroyed when the filterscript is unloaded
  110. new LSApartments1CPObject;
  111. // Stores the created object numbers of the elevator, the elevator doors and
  112. // the elevator floor doors so they can be destroyed when the filterscript
  113. // is unloaded
  114. new Obj_Elevator, Obj_ElevatorDoors[2], Obj_FloorDoors[11][2];
  115. // Stores a reference to the 3D text labels used on each floor and inside the
  116. // elevator itself so they can be detroyed when the filterscript is unloaded
  117. new Text3D:Label_Elevator, Text3D:Label_Floors[11];
  118. // Stores the current state of the elevator (ie ELEVATOR_STATE_IDLE,
  119. // ELEVATOR_STATE_WAITING or ELEVATOR_STATE_MOVING)
  120. new ElevatorState;
  121. // Stores the current floor the elevator is on or heading to... if the value is
  122. // ELEVATOR_STATE_IDLE or ELEVATOR_STATE_WAITING this is the current floor. If
  123. // the value is ELEVATOR_STATE_MOVING then it is the floor it's moving to
  124. new ElevatorFloor;
  125. // Stores the elevator queue for each floor
  126. new ElevatorQueue[11];
  127. // Stores who requested the floor for the elevator queue...
  128. // FloorRequestedBy[floor_id] = playerid; (stores who requested which floor)
  129. new FloorRequestedBy[11];
  130. // Used for a timer that makes the elevator move faster after players start
  131. // surfing the object
  132. new ElevatorBoostTimer;
  133. // ------------------------------------------------------------------------------
  134. // Function Forwards
  135. // -----------------
  136. // Public:
  137. forward CallElevator(playerid, floorid); // You can use INVALID_PLAYER_ID too.
  138. forward ShowElevatorDialog(playerid);
  139. // Private:
  140. forward Elevator_Initialize();
  141. forward Elevator_Destroy();
  142. forward Elevator_OpenDoors();
  143. forward Elevator_CloseDoors();
  144. forward Floor_OpenDoors(floorid);
  145. forward Floor_CloseDoors(floorid);
  146. forward Elevator_MoveToFloor(floorid);
  147. forward Elevator_Boost(floorid); // Increases the elevator speed until it reaches 'floorid'.
  148. forward Elevator_TurnToIdle();
  149. forward ReadNextFloorInQueue();
  150. forward RemoveFirstQueueFloor();
  151. forward AddFloorToQueue(floorid);
  152. forward IsFloorInQueue(floorid);
  153. forward ResetElevatorQueue();
  154. forward DidPlayerRequestElevator(playerid);
  155. forward Float:GetElevatorZCoordForFloor(floorid);
  156. forward Float:GetDoorsZCoordForFloor(floorid);
  157. // ------------------------------------------------------------------------------
  158. // Callbacks
  159. // ---------
  160. // Uncomment the OnPlayerCommandText callback below (remove the "/*" and the "*/")
  161. // to enable a simple teleport command (/lsa) which teleports the player to
  162. // outside the LS Apartments 1 building.
  163. /*
  164. public OnPlayerCommandText(playerid, cmdtext[])
  165. {
  166. // Check command text
  167. if (strcmp("/lsa", cmdtext, true, 4) == 0)
  168. {
  169. // Set the interior
  170. SetPlayerInterior(playerid, 0);
  171. // Set player position and facing angle
  172. SetPlayerPos(playerid, 1131.07 + random(3), -1180.72 + random(2), 33.32);
  173. SetPlayerFacingAngle(playerid, 270);
  174. // Fix camera position after teleporting
  175. SetCameraBehindPlayer(playerid);
  176. // Send a gametext message to the player
  177. GameTextForPlayer(playerid, "~b~~h~LS Apartments 1!", 3000, 3);
  178. // Exit here
  179. return 1;
  180. }
  181. // Exit here (return 0 as the command was not handled in this filterscript)
  182. return 0;
  183. }
  184. */
  185. public OnFilterScriptInit()
  186. {
  187. // Display information in the Server Console
  188. print("\n");
  189. print(" |---------------------------------------------------");
  190. print(" |--- LS Apartments 1 Filterscript");
  191. print(" |-- Script v1.02");
  192. print(" |-- 5th February 2015");
  193. print(" |---------------------------------------------------");
  194. // Create the LS Apartments 1 Building object
  195. LSApartments1Object = CreateObject(19595, 1160.96, -1180.58, 70.4141, 0, 0, 0);
  196. // Display information in the Server Console
  197. print(" |-- LS Apartments 1 Building object created");
  198. // Create the LS Apartments 1 Car Park object
  199. LSApartments1CPObject = CreateObject(19798, 1160.96, -1180.58, 20.4141, 0, 0, 0);
  200. // Display information in the Server Console
  201. print(" |-- LS Apartments 1 Car Park object created");
  202. // Reset the elevator queue
  203. ResetElevatorQueue();
  204. // Create the elevator object, the elevator doors and the floor doors
  205. Elevator_Initialize();
  206. // Display information in the Server Console
  207. print(" |-- LS Apartments 1 Elevator created");
  208. print(" |---------------------------------------------------");
  209. // Loop
  210. for (new i = 0; i < MAX_PLAYERS; i++)
  211. {
  212. // Check if the player is connected and not a NPC
  213. if (IsPlayerConnected(i) && !IsPlayerNPC(i))
  214. {
  215. // Remove default GTASA building map object, LOD and awning shadows
  216. // (so any player currently ingame does not have to rejoin for them
  217. // to be removed when this filterscript is loaded)
  218. RemoveBuildingForPlayer(i, 5766, 1160.96, -1180.58, 70.4141, 250.0); // Awning shadows
  219. RemoveBuildingForPlayer(i, 5767, 1160.96, -1180.58, 70.4141, 250.0); // Building
  220. RemoveBuildingForPlayer(i, 5964, 1160.96, -1180.58, 70.4141, 250.0); // LOD
  221. }
  222. }
  223. // Exit here
  224. return 1;
  225. }
  226. public OnFilterScriptExit()
  227. {
  228. // Check for valid object
  229. if (IsValidObject(LSApartments1Object))
  230. {
  231. // Destroy the LS Apartments 1 Building object
  232. DestroyObject(LSApartments1Object);
  233. // Display information in the Server Console
  234. print(" |---------------------------------------------------");
  235. print(" |-- LS Apartments 1 Building object destroyed");
  236. }
  237. // Check for valid object
  238. if (IsValidObject(LSApartments1CPObject))
  239. {
  240. // Destroy the LS Apartments 1 Car Park object
  241. DestroyObject(LSApartments1CPObject);
  242. // Display information in the Server Console
  243. print(" |-- LS Apartments 1 Car Park object destroyed");
  244. }
  245. // Destroy the elevator, the elevator doors and the elevator floor doors
  246. Elevator_Destroy();
  247. // Display information in the Server Console
  248. print(" |-- LS Apartments 1 Elevator destroyed");
  249. print(" |---------------------------------------------------");
  250. // Exit here
  251. return 1;
  252. }
  253. public OnPlayerConnect(playerid)
  254. {
  255. // Remove default GTASA building map object, LOD and awning shadows
  256. RemoveBuildingForPlayer(playerid, 5766, 1160.96, -1180.58, 70.4141, 250.0); // Awning shadows
  257. RemoveBuildingForPlayer(playerid, 5767, 1160.96, -1180.58, 70.4141, 250.0); // Building
  258. RemoveBuildingForPlayer(playerid, 5964, 1160.96, -1180.58, 70.4141, 250.0); // LOD
  259. // Exit here
  260. return 1;
  261. }
  262. public OnObjectMoved(objectid)
  263. {
  264. // Create variables
  265. new Float:x, Float:y, Float:z;
  266. // Loop
  267. for(new i; i < sizeof(Obj_FloorDoors); i ++)
  268. {
  269. // Check if the object that moved was one of the elevator floor doors
  270. if(objectid == Obj_FloorDoors[i][0])
  271. {
  272. GetObjectPos(Obj_FloorDoors[i][0], x, y, z);
  273. // Some floor doors have shut, move the elevator to next floor in queue:
  274. if (y < Y_DOOR_L_OPENED - 0.5)
  275. {
  276. Elevator_MoveToFloor(ElevatorQueue[0]);
  277. RemoveFirstQueueFloor();
  278. }
  279. }
  280. }
  281. if(objectid == Obj_Elevator) // The elevator reached the specified floor.
  282. {
  283. KillTimer(ElevatorBoostTimer); // Kills the timer, in case the elevator reached the floor before boost.
  284. FloorRequestedBy[ElevatorFloor] = INVALID_PLAYER_ID;
  285. Elevator_OpenDoors();
  286. Floor_OpenDoors(ElevatorFloor);
  287. GetObjectPos(Obj_Elevator, x, y, z);
  288. Label_Elevator = Create3DTextLabel("{CCCCCC}Press '{FFFFFF}~k~~CONVERSATION_YES~{CCCCCC}' to use elevator", 0xCCCCCCAA, X_ELEVATOR_POS - 1.7, Y_ELEVATOR_POS - 1.75, z - 0.4, 4.0, 0, 1);
  289. ElevatorState = ELEVATOR_STATE_WAITING;
  290. SetTimer("Elevator_TurnToIdle", ELEVATOR_WAIT_TIME, 0);
  291. }
  292. return 1;
  293. }
  294. public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
  295. {
  296. if(dialogid == DIALOG_ID)
  297. {
  298. if(!response)
  299. return 0;
  300. if(FloorRequestedBy[listitem] != INVALID_PLAYER_ID || IsFloorInQueue(listitem))
  301. GameTextForPlayer(playerid, "~r~The floor is already in the queue", 3500, 4);
  302. else if(DidPlayerRequestElevator(playerid))
  303. GameTextForPlayer(playerid, "~r~You already requested the elevator", 3500, 4);
  304. else
  305. CallElevator(playerid, listitem);
  306. return 1;
  307. }
  308. return 0;
  309. }
  310. public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
  311. {
  312. // Check if the player is not in a vehicle and pressed the conversation yes key (Y by default)
  313. if (!IsPlayerInAnyVehicle(playerid) && (newkeys & KEY_YES))
  314. {
  315. // Create variables and get the players current position
  316. new Float:pos[3];
  317. GetPlayerPos(playerid, pos[0], pos[1], pos[2]);
  318. // For debug
  319. //printf("X = %0.2f | Y = %0.2f | Z = %0.2f", pos[0], pos[1], pos[2]);
  320. // Check if the player is using the button inside the elevator
  321. if (pos[1] > (Y_ELEVATOR_POS - 1.8) && pos[1] < (Y_ELEVATOR_POS + 1.8) && pos[0] < (X_ELEVATOR_POS + 1.8) && pos[0] > (X_ELEVATOR_POS - 1.8))
  322. {
  323. // The player is using the button inside the elevator
  324. // --------------------------------------------------
  325. // Show the elevator dialog to the player
  326. ShowElevatorDialog(playerid);
  327. }
  328. else
  329. {
  330. // Check if the player is using the button on one of the floors
  331. if(pos[1] < (Y_ELEVATOR_POS - 1.81) && pos[1] > (Y_ELEVATOR_POS - 3.8) && pos[0] > (X_ELEVATOR_POS - 3.8) && pos[0] < (X_ELEVATOR_POS - 1.81))
  332. {
  333. // The player is most likely using an elevator floor button... check which floor
  334. // -----------------------------------------------------------------------------
  335. // Create variable with the number of floors to check (total floors minus 1)
  336. new i = 10;
  337. // Loop
  338. while(pos[2] < GetDoorsZCoordForFloor(i) + 3.5 && i > 0)
  339. i --;
  340. if(i == 0 && pos[2] < GetDoorsZCoordForFloor(0) + 2.0)
  341. i = -1;
  342. if (i <= 9)
  343. {
  344. // Check if the elevator is not moving (idle or waiting)
  345. if (ElevatorState != ELEVATOR_STATE_MOVING)
  346. {
  347. // Check if the elevator is already on the floor it was called from
  348. if (ElevatorFloor == i + 1)
  349. {
  350. // Display gametext message to the player
  351. GameTextForPlayer(playerid, "~n~~n~~n~~n~~n~~n~~n~~y~~h~LS Apartments 1 Elevator Is~n~~y~~h~Already On This Floor...~n~~w~Walk Inside It~n~~w~And Press '~k~~CONVERSATION_YES~'", 3500, 3);
  352. // Display chat text message to the player
  353. SendClientMessage(playerid, COLOR_MESSAGE_YELLOW, "* The LS Apartments 1 elevator is already on this floor... walk inside it and press '{FFFFFF}~k~~CONVERSATION_YES~{CCCCCC}'");
  354. // Exit here (return 1 so this callback is processed in other scripts)
  355. return 1;
  356. }
  357. }
  358. // Call function to call the elevator to the floor
  359. CallElevator(playerid, i + 1);
  360. // Display gametext message to the player
  361. GameTextForPlayer(playerid, "~n~~n~~n~~n~~n~~n~~n~~n~~g~~h~LS Apartments 1 Elevator~n~~g~~h~Has Been Called...~n~~w~Please Wait", 3000, 3);
  362. // Create variable for formatted message
  363. new strTempString[100];
  364. // Check if the elevator is moving
  365. if (ElevatorState == ELEVATOR_STATE_MOVING)
  366. {
  367. // Format chat text message
  368. format(strTempString, sizeof(strTempString), "* The LS Apartments 1 elevator has been called... it is currently moving towards the %s.", FloorNames[ElevatorFloor]);
  369. }
  370. else
  371. {
  372. // Check if the floor is the car park
  373. if (ElevatorFloor == 0)
  374. {
  375. // Format chat text message
  376. format(strTempString, sizeof(strTempString), "* The LS Apartments 1 elevator has been called... it is currently at the %s.", FloorNames[ElevatorFloor]);
  377. }
  378. else
  379. {
  380. // Format chat text message
  381. format(strTempString, sizeof(strTempString), "* The LS Apartments 1 elevator has been called... it is currently on the %s.", FloorNames[ElevatorFloor]);
  382. }
  383. }
  384. // Display formatted chat text message to the player
  385. SendClientMessage(playerid, COLOR_MESSAGE_YELLOW, strTempString);
  386. // Exit here (return 1 so this callback is processed in other scripts)
  387. return 1;
  388. }
  389. }
  390. }
  391. }
  392. // Exit here (return 1 so this callback is processed in other scripts)
  393. return 1;
  394. }
  395. // ------------------------ Functions ------------------------
  396. stock Elevator_Initialize()
  397. {
  398. // Create the elevator and elevator door objects
  399. Obj_Elevator = CreateObject(18755, X_ELEVATOR_POS, Y_ELEVATOR_POS, GROUND_Z_COORD + ELEVATOR_OFFSET, 0.000000, 0.000000, 0.000000);
  400. Obj_ElevatorDoors[0] = CreateObject(18757, X_ELEVATOR_POS, Y_ELEVATOR_POS, GROUND_Z_COORD + ELEVATOR_OFFSET, 0.000000, 0.000000, 0.000000);
  401. Obj_ElevatorDoors[1] = CreateObject(18756, X_ELEVATOR_POS, Y_ELEVATOR_POS, GROUND_Z_COORD + ELEVATOR_OFFSET, 0.000000, 0.000000, 0.000000);
  402. // Create the 3D text label for inside the elevator
  403. Label_Elevator = Create3DTextLabel("{CCCCCC}Press '{FFFFFF}~k~~CONVERSATION_YES~{CCCCCC}' to use elevator", 0xCCCCCCAA, X_ELEVATOR_POS - 1.7, Y_ELEVATOR_POS - 1.75, GROUND_Z_COORD - 0.4, 4.0, 0, 1);
  404. // Create variables
  405. new string[128], Float:z;
  406. // Loop
  407. for (new i; i < sizeof(Obj_FloorDoors); i ++)
  408. {
  409. // Create elevator floor door objects
  410. Obj_FloorDoors[i][0] = CreateObject(18757, X_ELEVATOR_POS - 0.245, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(i), 0.000000, 0.000000, 0.000000);
  411. Obj_FloorDoors[i][1] = CreateObject(18756, X_ELEVATOR_POS - 0.245, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(i), 0.000000, 0.000000, 0.000000);
  412. // Format string for the floor 3D text label
  413. format(string, sizeof(string), "{CCCCCC}[%s]\n{CCCCCC}Press '{FFFFFF}~k~~CONVERSATION_YES~{CCCCCC}' to call", FloorNames[i]);
  414. // Get label Z position
  415. z = GetDoorsZCoordForFloor(i);
  416. // Create floor label
  417. Label_Floors[i] = Create3DTextLabel(string, 0xCCCCCCAA, X_ELEVATOR_POS - 2.5, Y_ELEVATOR_POS - 2.5, z - 0.2, 10.5, 0, 1);
  418. }
  419. // Open the car park floor doors and the elevator doors
  420. Floor_OpenDoors(0);
  421. Elevator_OpenDoors();
  422. // Exit here
  423. return 1;
  424. }
  425. stock Elevator_Destroy()
  426. {
  427. // Destroys the elevator.
  428. DestroyObject(Obj_Elevator);
  429. DestroyObject(Obj_ElevatorDoors[0]);
  430. DestroyObject(Obj_ElevatorDoors[1]);
  431. Delete3DTextLabel(Label_Elevator);
  432. for(new i; i < sizeof(Obj_FloorDoors); i ++)
  433. {
  434. DestroyObject(Obj_FloorDoors[i][0]);
  435. DestroyObject(Obj_FloorDoors[i][1]);
  436. Delete3DTextLabel(Label_Floors[i]);
  437. }
  438. return 1;
  439. }
  440. stock Elevator_OpenDoors()
  441. {
  442. // Opens the elevator's doors.
  443. new Float:x, Float:y, Float:z;
  444. GetObjectPos(Obj_ElevatorDoors[0], x, y, z);
  445. MoveObject(Obj_ElevatorDoors[0], x, Y_DOOR_L_OPENED, z, DOORS_SPEED);
  446. MoveObject(Obj_ElevatorDoors[1], x, Y_DOOR_R_OPENED, z, DOORS_SPEED);
  447. return 1;
  448. }
  449. stock Elevator_CloseDoors()
  450. {
  451. // Closes the elevator's doors.
  452. if(ElevatorState == ELEVATOR_STATE_MOVING)
  453. return 0;
  454. new Float:x, Float:y, Float:z;
  455. GetObjectPos(Obj_ElevatorDoors[0], x, y, z);
  456. MoveObject(Obj_ElevatorDoors[0], x, Y_DOOR_CLOSED, z, DOORS_SPEED);
  457. MoveObject(Obj_ElevatorDoors[1], x, Y_DOOR_CLOSED, z, DOORS_SPEED);
  458. return 1;
  459. }
  460. stock Floor_OpenDoors(floorid)
  461. {
  462. // Opens the doors at the specified floor.
  463. MoveObject(Obj_FloorDoors[floorid][0], X_ELEVATOR_POS - 0.245, Y_DOOR_L_OPENED, GetDoorsZCoordForFloor(floorid), DOORS_SPEED);
  464. MoveObject(Obj_FloorDoors[floorid][1], X_ELEVATOR_POS - 0.245, Y_DOOR_R_OPENED, GetDoorsZCoordForFloor(floorid), DOORS_SPEED);
  465. PlaySoundForPlayersInRange(6401, 50.0, X_ELEVATOR_POS, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid) + 5.0);
  466. return 1;
  467. }
  468. stock Floor_CloseDoors(floorid)
  469. {
  470. // Closes the doors at the specified floor.
  471. MoveObject(Obj_FloorDoors[floorid][0], X_ELEVATOR_POS - 0.245, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid), DOORS_SPEED);
  472. MoveObject(Obj_FloorDoors[floorid][1], X_ELEVATOR_POS - 0.245, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid), DOORS_SPEED);
  473. PlaySoundForPlayersInRange(6401, 50.0, X_ELEVATOR_POS, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid) + 5.0);
  474. return 1;
  475. }
  476. stock Elevator_MoveToFloor(floorid)
  477. {
  478. // Moves the elevator to specified floor (doors are meant to be already closed).
  479. ElevatorState = ELEVATOR_STATE_MOVING;
  480. ElevatorFloor = floorid;
  481. // Move the elevator slowly, to give time to clients to sync the object surfing. Then, boost it up:
  482. MoveObject(Obj_Elevator, X_ELEVATOR_POS, Y_ELEVATOR_POS, GetElevatorZCoordForFloor(floorid), 0.25);
  483. MoveObject(Obj_ElevatorDoors[0], X_ELEVATOR_POS, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid), 0.25);
  484. MoveObject(Obj_ElevatorDoors[1], X_ELEVATOR_POS, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid), 0.25);
  485. Delete3DTextLabel(Label_Elevator);
  486. ElevatorBoostTimer = SetTimerEx("Elevator_Boost", 2000, 0, "i", floorid);
  487. return 1;
  488. }
  489. public Elevator_Boost(floorid)
  490. {
  491. // Increases the elevator's speed until it reaches 'floorid'
  492. StopObject(Obj_Elevator);
  493. StopObject(Obj_ElevatorDoors[0]);
  494. StopObject(Obj_ElevatorDoors[1]);
  495. MoveObject(Obj_Elevator, X_ELEVATOR_POS, Y_ELEVATOR_POS, GetElevatorZCoordForFloor(floorid), ELEVATOR_SPEED);
  496. MoveObject(Obj_ElevatorDoors[0], X_ELEVATOR_POS, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid), ELEVATOR_SPEED);
  497. MoveObject(Obj_ElevatorDoors[1], X_ELEVATOR_POS, Y_ELEVATOR_POS, GetDoorsZCoordForFloor(floorid), ELEVATOR_SPEED);
  498. return 1;
  499. }
  500. public Elevator_TurnToIdle()
  501. {
  502. ElevatorState = ELEVATOR_STATE_IDLE;
  503. ReadNextFloorInQueue();
  504. return 1;
  505. }
  506. stock RemoveFirstQueueFloor()
  507. {
  508. // Removes the data in ElevatorQueue[0], and reorders the queue accordingly.
  509. for(new i; i < sizeof(ElevatorQueue) - 1; i ++)
  510. ElevatorQueue[i] = ElevatorQueue[i + 1];
  511. ElevatorQueue[sizeof(ElevatorQueue) - 1] = INVALID_FLOOR;
  512. return 1;
  513. }
  514. stock AddFloorToQueue(floorid)
  515. {
  516. // Adds 'floorid' at the end of the queue.
  517. // Scan for the first empty space:
  518. new slot = -1;
  519. for(new i; i < sizeof(ElevatorQueue); i ++)
  520. {
  521. if(ElevatorQueue[i] == INVALID_FLOOR)
  522. {
  523. slot = i;
  524. break;
  525. }
  526. }
  527. if(slot != -1)
  528. {
  529. ElevatorQueue[slot] = floorid;
  530. // If needed, move the elevator.
  531. if(ElevatorState == ELEVATOR_STATE_IDLE)
  532. ReadNextFloorInQueue();
  533. return 1;
  534. }
  535. return 0;
  536. }
  537. stock ResetElevatorQueue()
  538. {
  539. // Resets the queue.
  540. for(new i; i < sizeof(ElevatorQueue); i ++)
  541. {
  542. ElevatorQueue[i] = INVALID_FLOOR;
  543. FloorRequestedBy[i] = INVALID_PLAYER_ID;
  544. }
  545. return 1;
  546. }
  547. stock IsFloorInQueue(floorid)
  548. {
  549. // Checks if the specified floor is currently part of the queue.
  550. for(new i; i < sizeof(ElevatorQueue); i ++)
  551. if(ElevatorQueue[i] == floorid)
  552. return 1;
  553. return 0;
  554. }
  555. stock ReadNextFloorInQueue()
  556. {
  557. // Reads the next floor in the queue, closes doors, and goes to it.
  558. if(ElevatorState != ELEVATOR_STATE_IDLE || ElevatorQueue[0] == INVALID_FLOOR)
  559. return 0;
  560. Elevator_CloseDoors();
  561. Floor_CloseDoors(ElevatorFloor);
  562. return 1;
  563. }
  564. stock DidPlayerRequestElevator(playerid)
  565. {
  566. for(new i; i < sizeof(FloorRequestedBy); i ++)
  567. if(FloorRequestedBy[i] == playerid)
  568. return 1;
  569. return 0;
  570. }
  571. stock ShowElevatorDialog(playerid)
  572. {
  573. new string[512];
  574. for(new i; i < sizeof(ElevatorQueue); i ++)
  575. {
  576. if(FloorRequestedBy[i] != INVALID_PLAYER_ID)
  577. strcat(string, "{FF0000}");
  578. strcat(string, FloorNames[i]);
  579. strcat(string, "\n");
  580. }
  581. ShowPlayerDialog(playerid, DIALOG_ID, DIALOG_STYLE_LIST, "LS Apartments 1 Elevator...", string, "Accept", "Cancel");
  582. return 1;
  583. }
  584. stock CallElevator(playerid, floorid)
  585. {
  586. // Calls the elevator (also used with the elevator dialog).
  587. if(FloorRequestedBy[floorid] != INVALID_PLAYER_ID || IsFloorInQueue(floorid))
  588. return 0;
  589. FloorRequestedBy[floorid] = playerid;
  590. AddFloorToQueue(floorid);
  591. return 1;
  592. }
  593. stock Float:GetElevatorZCoordForFloor(floorid)
  594. {
  595. // Return Z height value plus a small offset
  596. return (GROUND_Z_COORD + FloorZOffsets[floorid] + ELEVATOR_OFFSET);
  597. }
  598. stock Float:GetDoorsZCoordForFloor(floorid)
  599. {
  600. // Return Z height value plus a small offset
  601. return (GROUND_Z_COORD + FloorZOffsets[floorid] + ELEVATOR_OFFSET);
  602. }