vehicles.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. #if defined P_VEHICLES_INC
  2. #else
  3. #define P_VEHICLES_INC
  4. //===
  5. #define P_VEHICLES_TEST 1
  6. //custom color for new systems
  7. #define COLOR_VEHICLES 0x449b41FF
  8. #define MAX_SPAWN_SLOTS 3 //3: VIP 2: normal player
  9. //TODO: /dropcar restriction, dealerships
  10. //NOTE: ONLY, AND I MEAN ONLY KEEP VARIABLES IN HERE WHICH WILL BE USED MORE THAN ONCE
  11. enum pvehicleDatav {
  12. pvID, //vehicle ID from createvehicle(..)
  13. pvSID, //SQL ID of the vehicle in the DB.
  14. pvmodel,
  15. pvcolor1,
  16. pvcolor2,
  17. pvpaintjob,
  18. pvlocked,
  19. Float:pvdamage,
  20. //parking & towing
  21. Float:pvparkx,
  22. Float:pvparky,
  23. Float:pvparkz,
  24. Float:pvparkrz,
  25. //impound system
  26. pvimpounded,
  27. //upgrades
  28. pvgps,
  29. pvalarm,
  30. pvinsurance,
  31. pvsparekey,
  32. pvplate[9],
  33. pvvw
  34. }
  35. //Stores all vehicle data.
  36. new PlayerVehicles[MAX_PLAYERS][MAX_SPAWN_SLOTS][pvehicleDatav];
  37. //Vehicle Destroy Reason
  38. enum VD_REASON {
  39. VDPLAYER_DISCONNECT,
  40. VDPLAYER_ISSUE,
  41. }
  42. forward CreatePlayerVehicle(playerid, model, Float:x, Float:y, Float:z, Float:rz, color1, color2);
  43. forward SpawnPlayerVehicle(playerid, vsql);
  44. forward DestroyPlayerVehicle(playerid, slot, VD_REASON:reason);
  45. //junk
  46. SetVehicleLockState( vehicleid, lockstate ) {
  47. new engine, lights, alarm, doors, bonnet, boot, objective;
  48. GetVehicleParamsEx( vehicleid, engine, lights, alarm, doors, bonnet, boot, objective );
  49. SetVehicleParamsEx( vehicleid, engine, lights, alarm, lockstate, bonnet, boot, objective );
  50. gCarLock[vehicleid] = lockstate;
  51. return 1;
  52. }
  53. SetVehicleEngineState( vehicleid, enginestate ) {
  54. new engine, lights, alarm, doors, bonnet, boot, objective;
  55. GetVehicleParamsEx( vehicleid, engine, lights, alarm, doors, bonnet, boot, objective );
  56. SetVehicleParamsEx( vehicleid, enginestate, lights, alarm, doors, bonnet, boot, objective );
  57. engineOn[vehicleid] = enginestate;
  58. return 1;
  59. }
  60. IsVehicleOccupied( vehicleid ) {
  61. #pragma unused vehicleid
  62. /*for( new p; p <= GetPlayerPoolSize(); p++ ) {
  63. if( IsPlayerConnected( p ) ) {
  64. new pstate = GetPlayerState( p );
  65. if( pstate == PLAYER_STATE_DRIVER || pstate == PLAYER_STATE_PASSENGER ) {
  66. if( GetPlayerVehicleID( p ) == vehicleid ) {
  67. return 1;
  68. }
  69. }
  70. }
  71. }*/
  72. return 0;
  73. }
  74. //~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
  75. /* CREATING PLAYER VEHICLE
  76. INSERT, then create the vehicle if there's a free slot otherwise notify the player.
  77. */
  78. public CreatePlayerVehicle(playerid, model, Float:x, Float:y, Float:z, Float:rz, color1, color2) {
  79. //todo: generate random plate
  80. new plate[20];
  81. new query[500];
  82. //once vehicle is inserted into the database, get SID and try spawn
  83. inline OnInsertPlayerVehicle(pid, vmodel) {
  84. SendClientMessage(playerid, COLOR_VEHICLES, "Vehicle has been added to the database.");
  85. CreatePlayerVehicleEx(pid, vmodel);
  86. }
  87. mysql_format(sqlGameConnection, query, sizeof query,
  88. "INSERT INTO playervehicles \
  89. SET pID = %d, model = %d, parkx = %f, parky = %f, parkz = %f, parkrz = %f, locked = 0, color1 = 0, color2 = 0, damage=1000, gas=50, plate = '%e'",
  90. PlayerInfo[playerid][pID], model, x, y, z, rz, plate
  91. );
  92. mysql_pquery_inline(sqlGameConnection, query, using inline OnInsertPlayerVehicle, "ii", playerid, model);
  93. return 1;
  94. }
  95. //helper function
  96. static CreatePlayerVehicleEx(playerid, model) {
  97. SendClientMessage(playerid, COLOR_VEHICLES, "Checking database...");
  98. inline OnGetPlayerVehicleSID(pid) {
  99. new string[144];
  100. format(string, sizeof string, "Found %d vehicles belonging to player with model.", cache_get_row_count());
  101. SendClientMessage(playerid, COLOR_VEHICLES, string);
  102. if(cache_get_row_count()) {
  103. new id = cache_get_field_content_int(0, "ID");
  104. SendClientMessage(pid, COLOR_VEHICLES, "We have located your vehicle. Please wait while we prepare your vehicle. . .");
  105. SpawnPlayerVehicle(pid, id);
  106. }
  107. else {
  108. //log
  109. }
  110. }
  111. new query[120];
  112. mysql_format(sqlGameConnection, query, sizeof query, "SELECT ID FROM playervehicles WHERE model = %d LIMIT 1;", model);
  113. mysql_pquery_inline(sqlGameConnection, query, using inline OnGetPlayerVehicleSID, "i", playerid);
  114. return 1;
  115. }
  116. //~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
  117. /* SPAWNING VEHICLES
  118. 1. Get a free slot
  119. 2. Get data from MySQL & store to pVehicles ONLY IF it'll be reused later.
  120. 3. Setup the vehicle
  121. */
  122. public SpawnPlayerVehicle(playerid, vsql) {
  123. //where to spawn the vehicle?
  124. new Float:x, Float:y, Float:z, Float:rz;
  125. //keep damage as local vars: reduces size of playervehicles enum + it's useless after first spawn
  126. new dpanels, ddoors, dlights, dtires, gas;
  127. //get a free slot
  128. new slot = MAX_SPAWN_SLOTS+1;
  129. for(new i = 0; i < MAX_SPAWN_SLOTS; i++) {
  130. if(!PlayerVehicles[playerid][i][pvSID]) { //invalid SID = 0
  131. slot = i;
  132. }
  133. }
  134. if(slot == MAX_SPAWN_SLOTS+1) {
  135. SendClientMessage(playerid, COLOR_VEHICLES, "I'm sorry, you're going to have to park one of your vehicles in order to spawn this vehicle (/v park).");
  136. }
  137. SendClientMessage(playerid, COLOR_VEHICLES, "Found available vehicle slot. Fetching vehicle...");
  138. //Get the data from MySQL: playervehicles table
  139. inline SpawnPlayerVehicleEx(pid) {
  140. if(cache_get_row_count()) {
  141. #define veh(%1) PlayerVehicles[pid][slot][pv%1]
  142. veh(SID) = cache_get_field_content_int(0, "ID");
  143. x = cache_get_field_content_int(0, "x");
  144. y = cache_get_field_content_int(0, "y");
  145. z = cache_get_field_content_int(0, "z");
  146. rz = cache_get_field_content_int(0, "rz");
  147. veh(model) = cache_get_field_content_int(0, "model");
  148. veh(locked) = cache_get_field_content_int(0, "locked");
  149. veh(color1) = cache_get_field_content_int(0, "color1");
  150. veh(color2) = cache_get_field_content_int(0, "color2");
  151. veh(paintjob) = cache_get_field_content_int(0, "paintjob");
  152. gas = cache_get_field_content_int(0, "gas");
  153. veh(damage) = cache_get_field_content_float(0, "damage");
  154. //parking & towing;
  155. veh(parkx) = cache_get_field_content_float(0, "parkx");
  156. veh(parky) = cache_get_field_content_float(0, "parky");
  157. veh(parkz) = cache_get_field_content_float(0, "parkz");
  158. veh(parkrz) = cache_get_field_content_float(0, "parkrz");
  159. //upgrades
  160. veh(gps) = cache_get_field_content_int(0, "gps");
  161. veh(insurance) = cache_get_field_content_int( 0, "insurance");
  162. veh(alarm) = cache_get_field_content_int(0, "alarm");
  163. veh(sparekey) = cache_get_field_content_int(0, "sparekey");
  164. cache_get_field_content(0, "plate", veh(plate), sqlGameConnection, 9);
  165. dpanels = cache_get_field_content_int(0, "dpanels");
  166. ddoors = cache_get_field_content_int(0, "ddoors");
  167. dlights = cache_get_field_content_int(0, "dlights");
  168. dtires = cache_get_field_content_int(0, "dtires");
  169. veh(impounded) = cache_get_field_content_int(0, "impounded");
  170. //get vehicle component data
  171. new compstr[50];
  172. new components[14];
  173. for(new c; c < sizeof components; c++) {
  174. format( compstr, 50, "component%d", c );
  175. components[c] = cache_get_field_content_int(0, compstr);
  176. }
  177. if(x == 0.0) {
  178. x = veh(parkx);
  179. y = veh(parky);
  180. z = veh(parkz);
  181. rz = veh(parkrz);
  182. }
  183. #undef veh
  184. SendClientMessage(playerid, COLOR_VEHICLES, "Fetched vehicle. Spawning vehicle...");
  185. SetupPlayerVehicle(pid, slot, x, y, z, rz, dpanels, ddoors, dlights, dtires, gas, components);
  186. return 1;
  187. }
  188. }
  189. new query[100];
  190. mysql_format(sqlGameConnection, query, sizeof query, "SELECT * FROM playervehicles WHERE ID=%d", vsql);
  191. mysql_pquery_inline(sqlGameConnection, query, using inline SpawnPlayerVehicleEx, "i", playerid);
  192. return 1;
  193. }
  194. //PROTECTED (THIS MEANS: DO NOT TOUCH) --sets up the vehicle
  195. static SetupPlayerVehicle(playerid, slot, Float:x, Float:y, Float:z, Float:rz, dpanels, ddoors, dlights, dtires, gas, components[]) {
  196. #define veh(%1) PlayerVehicles[playerid][slot][pv%1]
  197. veh(ID) = CreateVehicle(veh(model), x, y, z, rz, veh(color1), veh(color2), -1);
  198. SendClientMessage(playerid, COLOR_VEHICLES, "Spawned vehicle. Setting attributes...");
  199. SetVehicleVirtualWorld(veh(ID), veh(vw));
  200. SetVehicleNumberPlate(veh(ID), veh(plate));
  201. //SetVehicleLockState(veh(ID), veh(locked));
  202. if( IsABicycle( veh(ID) ) ) engineOn[veh(ID)] = 1; //set engine vars off
  203. SetVehicleEngineState(veh(ID), engineOn[veh(ID)]);
  204. playerDisabledEngine[veh(ID)] = 1;
  205. //set component info
  206. //get vehicle component data
  207. for( new c; c < 14; c++ ) {
  208. if( components[c] ) {
  209. AddVehicleComponent(veh(ID), components[c]);
  210. }
  211. }
  212. //totalled state
  213. if( veh(damage) < 300.0 ) {
  214. SetVehicleEngineState(veh(ID), 0);
  215. veh(damage) = 305.0;
  216. }
  217. //set the damage/gas
  218. UpdateVehicleDamageStatus(veh(ID), dpanels, ddoors, dlights, dtires);
  219. SetVehicleHealth(veh(ID), veh(damage));
  220. ChangeVehiclePaintjob(veh(ID), veh(paintjob));
  221. Gas[veh(ID)] = gas;
  222. SendClientMessage(playerid, COLOR_VEHICLES, "Your vehicle is ready to go! It's located where you last parked it.");
  223. #undef veh
  224. }
  225. //~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
  226. /* DESTROY THE PLAYER VEHICLE
  227. Only save data which is being constantly updated by the server
  228. other data should be saved within commands etc.
  229. It's important we keep track of the reason the vehicle is being
  230. destroyed since if the player dropped connection we should
  231. respawn the vehicle back at its previous position
  232. */
  233. public DestroyPlayerVehicle(playerid, slot, VD_REASON:reason) {
  234. new query[500];
  235. #define veh(%1) PlayerVehicles[playerid][slot][pv%1]
  236. new Float:x, Float:y, Float:z, Float:rz, vw;
  237. //get data
  238. new damage = GetVehicleHealth(veh(ID), veh(damage));
  239. new dpanels, ddoors, dlights, dtires, gas;
  240. GetVehicleDamageStatus(veh(ID), dpanels, ddoors, dlights, dtires);
  241. gas = Gas[veh(ID)];
  242. //did the player drop connection? if so, keep track of current vehicle pos
  243. if(reason == VD_REASON:VDPLAYER_ISSUE) {
  244. GetVehiclePos(veh(ID), x, y, z);
  245. GetVehicleZAngle(veh(ID), rz);
  246. vw = GetVehicleVirtualWorld( veh(ID) );
  247. mysql_format(sqlGameConnection, query, sizeof query,
  248. "UPDATE playervehicles \
  249. SET x = %f, y = %f, z = %f, rz = %f, vw = %d",
  250. PlayerInfo[playerid][pID], x, y, z, rz, vw
  251. );
  252. }
  253. //else just update normal shit
  254. else {
  255. mysql_format(sqlGameConnection, query, sizeof query,
  256. "UPDATE playervehicles \
  257. SET x = 0.0"
  258. );
  259. }
  260. mysql_format(sqlGameConnection, query, sizeof query, "%s\
  261. , damage = %d, dpanels = %d, ddoors = %d, dlights = %d, dtires = %d, gas = %d",
  262. damage, dpanels, ddoors, dlights, dtires, gas
  263. );
  264. //get vehicle component data
  265. new components[14];
  266. for( new c; c < sizeof components; c++ ) {
  267. components[c] = GetVehicleComponentInSlot(veh(ID), c);
  268. mysql_format(sqlGameConnection, query, sizeof query, "%s, component%d = %d", c, components[c]);
  269. }
  270. //finally, commit & destroy
  271. mysql_pquery(sqlGameConnection, query);
  272. DestroyVehicle(veh(ID));
  273. veh(SID) = 0;
  274. #undef veh
  275. return 1;
  276. }
  277. /* TEST COMMANDS ONLY
  278. */
  279. #if P_VEHICLES_TEST == 1
  280. Hook:vehicles_OnPlayerSpawn(playerid) {
  281. SendClientMessage(playerid, COLOR_VEHICLES, "Good evening testers.");
  282. SendClientMessage(playerid, COLOR_VEHICLES, "Please test vehicles using commands: /cars, /c(reate)v(ehicle), /d(estroy)v(ehicle), /s(pawn)v(ehicle).");
  283. SendClientMessage(playerid, COLOR_VEHICLES, "It should be noted that these commands are going to be used for testing only.");
  284. SendClientMessage(playerid, COLOR_VEHICLES, "You should note, that this is only testing the backend, not the frontend (i.e user side).");
  285. return 1;
  286. }
  287. //Get player vehicles
  288. CMD:cars(playerid, params[]) {
  289. inline OnGetPlayerVehicles(pid) {
  290. new rows = cache_num_rows();
  291. new string[144];
  292. if(rows) {
  293. for(new row = 0; row < rows; rows++) {
  294. format(string, sizeof(string), "%s : ID is %d", GetVehicleFriendlyNameFromModel(cache_get_field_content_int(0, "model")), cache_get_field_content_int(row, "ID"));
  295. SendClientMessage(pid, COLOR_VEHICLES, string);
  296. }
  297. }
  298. else {
  299. SendClientMessage(playerid, COLOR_VEHICLES, "You have no vehicles, /cv");
  300. }
  301. }
  302. new query[300];
  303. mysql_format(sqlGameConnection, query, sizeof query, "SELECT ID, model FROM playervehicles WHERE pID = %d", PlayerInfo[playerid][pID]);
  304. mysql_pquery_inline(sqlGameConnection, query, using inline OnGetPlayerVehicles, "i", playerid);
  305. return 1;
  306. }
  307. CMD:cv(playerid, params[]) {
  308. new model;
  309. if(sscanf(params, "i", model)) {
  310. SendClientMessage(playerid, COLOR_GREY, "You must enter a MODEL NUMBER of a vehicle.");
  311. return 1;
  312. }
  313. new Float:x, Float:y, Float:z;
  314. GetPlayerPos(playerid, x, y, z);
  315. SendClientMessage(playerid, COLOR_VEHICLES, "We're creating a vehicle at your position. . .");
  316. CreatePlayerVehicle(playerid, model, x, y, z, 0.0, -1, -1);
  317. return 1;
  318. }
  319. CMD:dv(playerid, params[]) {
  320. new slot;
  321. if(sscanf(params, "i", slot)) {
  322. SendClientMessage(playerid, COLOR_GREY, "You must enter a SLOT for which your vehicle is spawned in (try 0-2).");
  323. return 1;
  324. }
  325. DestroyPlayerVehicle(playerid, slot, VDPLAYER_DISCONNECT);
  326. return 1;
  327. }
  328. CMD:sv(playerid, params[]) {
  329. new id;
  330. if(sscanf(params, "i", id)) {
  331. SendClientMessage(playerid, COLOR_GREY, "You must enter a ID for which your vehicle specified in /cars.");
  332. return 1;
  333. }
  334. SpawnPlayerVehicle(playerid, id);
  335. return 1;
  336. }
  337. #endif
  338. //EOF
  339. #endif