flymode.pwn 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. //-------------------------------------------------
  2. //
  3. // This is an example of using the AttachCameraToObject function
  4. // to create a no-clip flying camera.
  5. //
  6. // h02 2012
  7. //
  8. // SA-MP 0.3e and above
  9. //
  10. //-------------------------------------------------
  11. // Default Move Speed
  12. #define MOVE_SPEED 100.0
  13. #define ACCEL_RATE 0.03
  14. #define ACCEL_MODE true
  15. // Players Mode
  16. #define CAMERA_MODE_NONE 0
  17. #define CAMERA_MODE_FLY 1
  18. // Key state definitions
  19. #define MOVE_FORWARD 1
  20. #define MOVE_BACK 2
  21. #define MOVE_LEFT 3
  22. #define MOVE_RIGHT 4
  23. #define MOVE_FORWARD_LEFT 5
  24. #define MOVE_FORWARD_RIGHT 6
  25. #define MOVE_BACK_LEFT 7
  26. #define MOVE_BACK_RIGHT 8
  27. // Enumeration for storing data about the player
  28. enum noclipenum
  29. {
  30. cameramode,
  31. flyobject,
  32. mode,
  33. lrold,
  34. udold,
  35. lastmove,
  36. Float:accelmul,
  37. Float:accelrate,
  38. Float:maxspeed,
  39. bool:accel
  40. }
  41. new noclipdata[MAX_PLAYERS][noclipenum];
  42. new bool:FlyMode[MAX_PLAYERS];
  43. #define InFlyMode(%0) FlyMode[%0]
  44. //--------------------------------------------------
  45. tsfunc IsFlyMode(playerid) { return noclipdata[playerid][cameramode]; }
  46. public OnFilterScriptExit()
  47. {
  48. // If any players are still in edit mode, boot them out before the filterscript unloads
  49. for(new x; x<MAX_PLAYERS; x++)
  50. {
  51. if(noclipdata[x][cameramode] == CAMERA_MODE_FLY) CancelFlyMode(x);
  52. }
  53. #if defined FM_OnFilterScriptExit
  54. FM_OnFilterScriptExit();
  55. #endif
  56. return 1;
  57. }
  58. #if defined _ALS_OnFilterScriptExit
  59. #undef OnFilterScriptExit
  60. #else
  61. #define _ALS_OnFilterScriptExit
  62. #endif
  63. #define OnFilterScriptExit FM_OnFilterScriptExit
  64. #if defined FM_OnFilterScriptExit
  65. forward FM_OnFilterScriptExit();
  66. #endif
  67. //--------------------------------------------------
  68. public OnPlayerConnect(playerid)
  69. {
  70. // Reset the data belonging to this player slot
  71. noclipdata[playerid][cameramode] = CAMERA_MODE_NONE;
  72. noclipdata[playerid][lrold] = 0;
  73. noclipdata[playerid][udold] = 0;
  74. noclipdata[playerid][mode] = 0;
  75. noclipdata[playerid][lastmove] = 0;
  76. noclipdata[playerid][accelmul] = 0.0;
  77. noclipdata[playerid][accel] = ACCEL_MODE;
  78. noclipdata[playerid][accelrate] = ACCEL_RATE;
  79. noclipdata[playerid][maxspeed] = MOVE_SPEED;
  80. FlyMode[playerid] = false;
  81. #if defined FM_OnPlayerConnect
  82. FM_OnPlayerConnect(playerid);
  83. #endif
  84. return 1;
  85. }
  86. #if defined _ALS_OnPlayerConnect
  87. #undef OnPlayerConnect
  88. #else
  89. #define _ALS_OnPlayerConnect
  90. #endif
  91. #define OnPlayerConnect FM_OnPlayerConnect
  92. #if defined FM_OnPlayerConnect
  93. forward FM_OnPlayerConnect(playerid);
  94. #endif
  95. //--------------------------------------------------
  96. public OnPlayerDisconnect(playerid, reason)
  97. {
  98. if(noclipdata[playerid][cameramode] == CAMERA_MODE_FLY) CancelFlyMode(playerid);
  99. #if defined FM_OnPlayerDisconnect
  100. FM_OnPlayerDisconnect(playerid, reason);
  101. #endif
  102. return 1;
  103. }
  104. #if defined _ALS_OnPlayerDisconnect
  105. #undef OnPlayerDisconnect
  106. #else
  107. #define _ALS_OnPlayerDisconnect
  108. #endif
  109. #define OnPlayerDisconnect FM_OnPlayerDisconnect
  110. #if defined FM_OnPlayerDisconnect
  111. forward FM_OnPlayerDisconnect(playerid, reason);
  112. #endif
  113. //--------------------------------------------------
  114. YCMD:flymode(playerid, arg[], help)
  115. {
  116. if(help)
  117. {
  118. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  119. SendClientMessage(playerid, STEALTH_GREEN, "Toggle flymode.");
  120. return 1;
  121. }
  122. // Place the player in and out of edit mode
  123. if(FlyMode[playerid]) CancelFlyMode(playerid);
  124. else StartFlyMode(playerid);
  125. return 1;
  126. }
  127. YCMD:fmspeed(playerid, arg[], help)
  128. {
  129. if(help)
  130. {
  131. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  132. SendClientMessage(playerid, STEALTH_GREEN, "Change flymode speed, must be 5-200.");
  133. return 1;
  134. }
  135. new Float:newspeed;
  136. sscanf(arg, "F(-1.0)", newspeed);
  137. if(newspeed == -1.0)
  138. newspeed = MOVE_SPEED;
  139. else if(newspeed < 5.0)
  140. newspeed = 5.0;
  141. else if(newspeed > 200.0)
  142. newspeed = 200.0;
  143. noclipdata[playerid][maxspeed] = newspeed;
  144. SendClientMessage(playerid, STEALTH_GREEN, sprintf("Flymode max speed set to %0.2f", newspeed));
  145. return 1;
  146. }
  147. YCMD:fmaccel(playerid, arg[], help)
  148. {
  149. if(help)
  150. {
  151. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  152. SendClientMessage(playerid, STEALTH_GREEN, "Change flymode acceleration rate, must be 0.005 - 0.05");
  153. return 1;
  154. }
  155. new Float:newacc;
  156. sscanf(arg, "F(-1.0)", newacc);
  157. if(newacc == -1.0)
  158. newacc = ACCEL_RATE;
  159. else if(newacc < 0.005)
  160. newacc = 0.005;
  161. else if(newacc > 0.05)
  162. newacc = 0.05;
  163. noclipdata[playerid][accelrate] = newacc;
  164. SendClientMessage(playerid, STEALTH_GREEN, sprintf("Flymode max speed set to %0.3f", newacc));
  165. return 1;
  166. }
  167. YCMD:fmtoggle(playerid, arg[], help)
  168. {
  169. if(help)
  170. {
  171. SendClientMessage(playerid, STEALTH_ORANGE, "______________________________________________");
  172. SendClientMessage(playerid, STEALTH_GREEN, "Toggle flymode acceleration.");
  173. return 1;
  174. }
  175. noclipdata[playerid][accel] = !noclipdata[playerid][accel];
  176. SendClientMessage(playerid, STEALTH_GREEN, sprintf("Flymode acceleration toggled %s", noclipdata[playerid][accel] ? ("on") : ("off")));
  177. return 1;
  178. }
  179. //--------------------------------------------------
  180. public OnPlayerUpdate(playerid)
  181. {
  182. if(noclipdata[playerid][cameramode] == CAMERA_MODE_FLY)
  183. {
  184. new keys,ud,lr;
  185. GetPlayerKeys(playerid,keys,ud,lr);
  186. if(noclipdata[playerid][mode] && (GetTickCount() - noclipdata[playerid][lastmove] > 100))
  187. {
  188. // If the last move was > 100ms ago, process moving the object the players camera is attached to
  189. MoveCamera(playerid);
  190. }
  191. // Is the players current key state different than their last keystate?
  192. if(noclipdata[playerid][udold] != ud || noclipdata[playerid][lrold] != lr)
  193. {
  194. if((noclipdata[playerid][udold] != 0 || noclipdata[playerid][lrold] != 0) && ud == 0 && lr == 0)
  195. { // All keys have been released, stop the object the camera is attached to and reset the acceleration multiplier
  196. StopDynamicObject(noclipdata[playerid][flyobject]);
  197. noclipdata[playerid][mode] = 0;
  198. noclipdata[playerid][accelmul] = 0.0;
  199. }
  200. else
  201. { // Indicates a new key has been pressed
  202. // Get the direction the player wants to move as indicated by the keys
  203. noclipdata[playerid][mode] = GetMoveDirectionFromKeys(ud, lr);
  204. // Process moving the object the players camera is attached to
  205. MoveCamera(playerid);
  206. }
  207. }
  208. noclipdata[playerid][udold] = ud; noclipdata[playerid][lrold] = lr; // Store current keys pressed for comparison next update
  209. #if defined FM_OnPlayerUpdate
  210. FM_OnPlayerUpdate(playerid);
  211. #endif
  212. return 0;
  213. }
  214. #if defined FM_OnPlayerUpdate
  215. FM_OnPlayerUpdate(playerid);
  216. #endif
  217. return 1;
  218. }
  219. #if defined _ALS_OnPlayerUpdate
  220. #undef OnPlayerUpdate
  221. #else
  222. #define _ALS_OnPlayerUpdate
  223. #endif
  224. #define OnPlayerUpdate FM_OnPlayerUpdate
  225. #if defined FM_OnPlayerUpdate
  226. forward FM_OnPlayerUpdate(playerid);
  227. #endif
  228. //--------------------------------------------------
  229. tsfunc GetMoveDirectionFromKeys(ud, lr)
  230. {
  231. new direction = 0;
  232. if(lr < 0)
  233. {
  234. if(ud < 0) direction = MOVE_FORWARD_LEFT; // Up & Left key pressed
  235. else if(ud > 0) direction = MOVE_BACK_LEFT; // Back & Left key pressed
  236. else direction = MOVE_LEFT; // Left key pressed
  237. }
  238. else if(lr > 0) // Right pressed
  239. {
  240. if(ud < 0) direction = MOVE_FORWARD_RIGHT; // Up & Right key pressed
  241. else if(ud > 0) direction = MOVE_BACK_RIGHT; // Back & Right key pressed
  242. else direction = MOVE_RIGHT; // Right key pressed
  243. }
  244. else if(ud < 0) direction = MOVE_FORWARD; // Up key pressed
  245. else if(ud > 0) direction = MOVE_BACK; // Down key pressed
  246. return direction;
  247. }
  248. //--------------------------------------------------
  249. tsfunc MoveCamera(playerid)
  250. {
  251. new Float:FV[3], Float:CP[3];
  252. //GetPlayerCameraPos(playerid, CP[0], CP[1], CP[2]); // Cameras position in space
  253. GetDynamicObjectPos(noclipdata[playerid][flyobject], CP[0], CP[1], CP[2]); // Cameras position in space
  254. GetPlayerCameraFrontVector(playerid, FV[0], FV[1], FV[2]); // Where the camera is looking at
  255. // Increases the acceleration multiplier the longer the key is held
  256. if(noclipdata[playerid][accelmul] <= 1.0) noclipdata[playerid][accelmul] += noclipdata[playerid][accelrate];
  257. // Determine the speed to move the camera based on the acceleration multiplier
  258. new Float:speed = noclipdata[playerid][maxspeed] * (noclipdata[playerid][accel] ? noclipdata[playerid][accelmul] : 1.0);
  259. // Calculate the cameras next position based on their current position and the direction their camera is facing
  260. new Float:X, Float:Y, Float:Z;
  261. GetNextCameraPosition(noclipdata[playerid][mode], CP, FV, X, Y, Z);
  262. MoveDynamicObject(noclipdata[playerid][flyobject], X, Y, Z, speed, 0.0, 0.0, 0.0);
  263. //SendClientMessage(playerid, -1, sprintf("(%0.1f, %0.1f, %0.1f) - (%0.1f, %0.1f, %0.1f) - (%0.1f, %0.1f, %0.1f)", CP[0], CP[1], CP[2], FV[0], FV[1], FV[2], X, Y, Z));
  264. // Store the last time the camera was moved as now
  265. noclipdata[playerid][lastmove] = GetTickCount();
  266. return 1;
  267. }
  268. tsfunc SetFlyModePos(playerid, Float:x, Float:y, Float:z)
  269. {
  270. if(FlyMode[playerid])
  271. {
  272. SetDynamicObjectPos(noclipdata[playerid][flyobject], x, y, z);
  273. noclipdata[playerid][lastmove] = GetTickCount();
  274. return 1;
  275. }
  276. return 0;
  277. }
  278. tsfunc GetFlyModePos(playerid, &Float:x, &Float:y, &Float:z)
  279. {
  280. if(FlyMode[playerid])
  281. {
  282. GetDynamicObjectPos(noclipdata[playerid][flyobject], x, y, z);
  283. return 1;
  284. }
  285. return 0;
  286. }
  287. //--------------------------------------------------
  288. tsfunc GetNextCameraPosition(move_mode, Float:CP[3], Float:FV[3], &Float:X, &Float:Y, &Float:Z)
  289. {
  290. // Calculate the cameras next position based on their current position and the direction their camera is facing
  291. #define OFFSET_X (FV[0]*6000.0)
  292. #define OFFSET_Y (FV[1]*6000.0)
  293. #define OFFSET_Z (FV[2]*6000.0)
  294. switch(move_mode)
  295. {
  296. case MOVE_FORWARD:
  297. {
  298. X = CP[0]+OFFSET_X;
  299. Y = CP[1]+OFFSET_Y;
  300. Z = CP[2]+OFFSET_Z;
  301. }
  302. case MOVE_BACK:
  303. {
  304. X = CP[0]-OFFSET_X;
  305. Y = CP[1]-OFFSET_Y;
  306. Z = CP[2]-OFFSET_Z;
  307. }
  308. case MOVE_LEFT:
  309. {
  310. X = CP[0]-OFFSET_Y;
  311. Y = CP[1]+OFFSET_X;
  312. Z = CP[2];
  313. }
  314. case MOVE_RIGHT:
  315. {
  316. X = CP[0]+OFFSET_Y;
  317. Y = CP[1]-OFFSET_X;
  318. Z = CP[2];
  319. }
  320. case MOVE_BACK_LEFT:
  321. {
  322. X = CP[0]+(-OFFSET_X - OFFSET_Y);
  323. Y = CP[1]+(-OFFSET_Y + OFFSET_X);
  324. Z = CP[2]-OFFSET_Z;
  325. }
  326. case MOVE_BACK_RIGHT:
  327. {
  328. X = CP[0]+(-OFFSET_X + OFFSET_Y);
  329. Y = CP[1]+(-OFFSET_Y - OFFSET_X);
  330. Z = CP[2]-OFFSET_Z;
  331. }
  332. case MOVE_FORWARD_LEFT:
  333. {
  334. X = CP[0]+(OFFSET_X - OFFSET_Y);
  335. Y = CP[1]+(OFFSET_Y + OFFSET_X);
  336. Z = CP[2]+OFFSET_Z;
  337. }
  338. case MOVE_FORWARD_RIGHT:
  339. {
  340. X = CP[0]+(OFFSET_X + OFFSET_Y);
  341. Y = CP[1]+(OFFSET_Y - OFFSET_X);
  342. Z = CP[2]+OFFSET_Z;
  343. }
  344. }
  345. }
  346. //--------------------------------------------------
  347. tsfunc CancelFlyMode(playerid)
  348. {
  349. new Float:x, Float:y, Float:z;
  350. GetPlayerCameraPos(playerid, x, y, z);
  351. SetTimerEx("DelaySetPos", 2000, false, "ifff", playerid, x, y, z);
  352. FlyMode[playerid] = false;
  353. CancelEdit(playerid);
  354. TogglePlayerSpectating(playerid, false);
  355. DestroyDynamicObject(noclipdata[playerid][flyobject]);
  356. noclipdata[playerid][cameramode] = CAMERA_MODE_NONE;
  357. return 1;
  358. }
  359. forward DelaySetPos(playerid, Float:x, Float:y, Float:z);
  360. public DelaySetPos(playerid, Float:x, Float:y, Float:z) { SetPlayerPos(playerid, x, y, z); }
  361. //--------------------------------------------------
  362. tsfunc StartFlyMode(playerid)
  363. {
  364. // Create an invisible object for the players camera to be attached to
  365. new Float:X, Float:Y, Float:Z;
  366. GetPlayerPos(playerid, X, Y, Z);
  367. noclipdata[playerid][flyobject] = CreateDynamicObject(19300, X, Y, Z, 0.0, 0.0, 0.0, .playerid = playerid, .streamdistance = 300.0, .drawdistance = 300.0);
  368. // Place the player in spectating mode so objects will be streamed based on camera location
  369. TogglePlayerSpectating(playerid, true);
  370. // Attach the players camera to the created object
  371. AttachCameraToDynamicObject(playerid, noclipdata[playerid][flyobject]);
  372. FlyMode[playerid] = true;
  373. noclipdata[playerid][cameramode] = CAMERA_MODE_FLY;
  374. return 1;
  375. }
  376. //--------------------------------------------------