1pub mod events;
2pub mod functions;
3
4use std::ffi::c_void;
5
6use crate::{
7 players::Player,
8 runtime::queue_api_call,
9 types::vector::{Vector3, Vector4},
10};
11
12pub use functions::load_functions;
13
14pub struct Vehicle {
15 handle: *const c_void,
16}
17
18impl Vehicle {
19 pub fn get_handle(&self) -> *const c_void {
20 self.handle
21 }
22 pub fn new(handle: *const c_void) -> Self {
23 Self { handle }
24 }
25 pub fn create(
27 modelid: i32,
28 pos: Vector3,
29 rotation: f32,
30 colour1: i32,
31 colour2: i32,
32 respawnDelay: i32,
33 addSiren: bool,
34 ) -> Option<Vehicle> {
35 let mut _id = 0;
36 functions::Vehicle_Create(
37 modelid,
38 pos.x,
39 pos.y,
40 pos.z,
41 rotation,
42 colour1,
43 colour2,
44 respawnDelay,
45 addSiren,
46 &mut _id,
47 )
48 }
49 pub fn get_seats(modelid: i32) -> i32 {
51 functions::Vehicle_GetMaxPassengerSeats(modelid)
52 }
53 pub fn destroy(&self) {
55 self.defer_api_call(Box::new(|vehicle| {
56 functions::Vehicle_Destroy(&vehicle);
57 }));
58 }
59 pub fn is_streamed_in(&self, player: &Player) -> bool {
61 functions::Vehicle_IsStreamedIn(self, player)
62 }
63 pub fn get_pos(&self) -> Vector3 {
65 let mut pos = Vector3::default();
66 functions::Vehicle_GetPos(self, &mut pos.x, &mut pos.y, &mut pos.z);
67 pos
68 }
69 pub fn set_pos(&self, pos: Vector3) {
71 self.defer_api_call(Box::new(move |vehicle| {
72 functions::Vehicle_SetPos(&vehicle, pos.x, pos.y, pos.z);
73 }));
74 }
75 pub fn get_z_angle(&self) -> f32 {
77 functions::Vehicle_GetZAngle(self)
78 }
79 pub fn get_rotation_quat(&self) -> Vector4 {
81 let mut rotation = Vector4::default();
82 functions::Vehicle_GetRotationQuat(
83 self,
84 &mut rotation.w,
85 &mut rotation.x,
86 &mut rotation.y,
87 &mut rotation.z,
88 );
89 rotation
90 }
91 pub fn get_distance_from_point(&self, pos: Vector3) -> f32 {
93 functions::Vehicle_GetDistanceFromPoint(self, pos.x, pos.y, pos.z)
94 }
95 pub fn set_z_angle(&self, angle: f32) -> bool {
97 functions::Vehicle_SetZAngle(self, angle)
98 }
99 pub fn set_params_for_player(&self, player: &Player, params: VehicleParams) -> bool {
101 functions::Vehicle_SetParamsForPlayer(
102 self,
103 player,
104 params.objective as i32,
105 params.doors as i32,
106 )
107 }
108 pub fn use_manual_engine_and_lights() -> bool {
109 functions::Vehicle_UseManualEngineAndLights()
110 }
111 pub fn set_params(&self, params: VehicleParams) -> bool {
112 functions::Vehicle_SetParamsEx(
113 self,
114 params.engine as i32,
115 params.lights as i32,
116 params.alarm as i32,
117 params.doors as i32,
118 params.bonnet as i32,
119 params.boot as i32,
120 params.objective as i32,
121 )
122 }
123 pub fn get_params(&self) -> VehicleParams {
124 let mut params = VehicleParams::default();
125 functions::Vehicle_GetParamsEx(
126 self,
127 &mut params.engine,
128 &mut params.lights,
129 &mut params.alarm,
130 &mut params.doors,
131 &mut params.bonnet,
132 &mut params.boot,
133 &mut params.objective,
134 );
135 params
136 }
137 pub fn set_to_respawn(&self) {
139 self.defer_api_call(Box::new(move |vehicle| {
140 functions::Vehicle_SetToRespawn(&vehicle);
141 }));
142 }
143 pub fn link_to_interior(&self, interiorid: i32) {
145 self.defer_api_call(Box::new(move |vehicle| {
146 functions::Vehicle_LinkToInterior(&vehicle, interiorid);
147 }));
148 }
149 pub fn add_component(&self, componentid: i32) -> bool {
151 functions::Vehicle_AddComponent(self, componentid)
152 }
153 pub fn remove_component(&self, componentid: i32) -> bool {
155 functions::Vehicle_RemoveComponent(self, componentid)
156 }
157 pub fn change_color(&self, colour1: i32, colour2: i32) -> bool {
159 functions::Vehicle_ChangeColor(self, colour1, colour2)
160 }
161 pub fn change_paintjob(&self, paintjobid: i32) -> bool {
163 functions::Vehicle_ChangePaintjob(self, paintjobid)
164 }
165 pub fn set_health(&self, health: f32) {
167 self.defer_api_call(Box::new(move |vehicle| {
168 functions::Vehicle_SetHealth(&vehicle, health);
169 }));
170 }
171 pub fn get_health(&self) -> f32 {
173 functions::Vehicle_GetHealth(self)
174 }
175 pub fn attach_trailer(&self, trailer: &Vehicle) -> bool {
177 functions::Vehicle_AttachTrailer(self, trailer)
178 }
179 pub fn detach_trailer(&self) -> bool {
181 functions::Vehicle_DetachTrailer(self)
182 }
183 pub fn is_trailer_attached(&self) -> bool {
185 functions::Vehicle_IsTrailerAttached(self)
186 }
187 pub fn get_trailer(&self) -> Option<Vehicle> {
189 functions::Vehicle_GetTrailer(self)
190 }
191 pub fn set_number_plate(&self, numberPlate: &str) -> bool {
193 functions::Vehicle_SetNumberPlate(self, numberPlate)
194 }
195 pub fn get_model(&self) -> i32 {
197 functions::Vehicle_GetModel(self)
198 }
199 pub fn get_component_in_slot(&self, slot: i32) -> i32 {
201 functions::Vehicle_GetComponentInSlot(self, slot)
202 }
203 pub fn get_component_type(componentid: i32) -> i32 {
205 functions::Vehicle_GetComponentType(componentid)
206 }
207 pub fn can_have_component(modelid: i32, componentid: i32) -> bool {
209 functions::Vehicle_CanHaveComponent(modelid, componentid)
210 }
211 pub fn get_random_car_col_pair(modelid: i32) -> (i32, i32, i32, i32) {
212 let (mut colour1, mut colour2, mut colour3, mut colour4) = Default::default();
213 functions::Vehicle_GetRandomColorPair(
214 modelid,
215 &mut colour1,
216 &mut colour2,
217 &mut colour3,
218 &mut colour4,
219 );
220 (colour1, colour2, colour3, colour4)
221 }
222 pub fn colour_index_to_colour(colourIndex: i32, alpha: i32) -> i32 {
223 functions::Vehicle_ColorIndexToColor(colourIndex, alpha)
224 }
225 pub fn repair(&self) {
227 self.defer_api_call(Box::new(move |vehicle| {
228 functions::Vehicle_Repair(&vehicle);
229 }));
230 }
231 pub fn get_velocity(&self) -> Vector3 {
233 let mut velocity = Vector3::default();
234 functions::Vehicle_GetVelocity(self, &mut velocity.x, &mut velocity.y, &mut velocity.z);
235 velocity
236 }
237 pub fn set_velocity(&self, velocity: Vector3) {
239 self.defer_api_call(Box::new(move |vehicle| {
240 functions::Vehicle_SetVelocity(&vehicle, velocity.x, velocity.y, velocity.z);
241 }));
242 }
243 pub fn set_angular_velocity(&self, velocity: Vector3) -> bool {
245 functions::Vehicle_SetAngularVelocity(self, velocity.x, velocity.y, velocity.z)
246 }
247 pub fn get_damage_status(&self) -> VehicleDamageStatusData {
249 let (mut panels, mut doors, mut lights, mut tires) = Default::default();
250
251 functions::Vehicle_GetDamageStatus(self, &mut panels, &mut doors, &mut lights, &mut tires);
252
253 VehicleDamageStatusData {
254 panels,
255 doors,
256 lights,
257 tires,
258 }
259 }
260 pub fn update_damage_status(&self, panels: i32, doors: i32, lights: i32, tires: i32) {
262 self.defer_api_call(Box::new(move |vehicle| {
263 functions::Vehicle_UpdateDamageStatus(&vehicle, panels, doors, lights, tires);
264 }));
265 }
266 pub fn get_model_info(model: i32, infotype: i32) -> Vector3 {
268 let mut pos = Vector3::default();
269 functions::Vehicle_GetModelInfo(model, infotype, &mut pos.x, &mut pos.y, &mut pos.z);
270 pos
271 }
272 pub fn set_virtual_world(&self, virtualWorld: i32) -> bool {
274 functions::Vehicle_SetVirtualWorld(self, virtualWorld)
275 }
276 pub fn get_virtual_world(&self) -> i32 {
278 functions::Vehicle_GetVirtualWorld(self)
279 }
280 pub fn get_landing_gear_state(&self) -> i32 {
282 functions::Vehicle_GetLandingGearState(self)
283 }
284 pub fn create_static(
286 modelid: i32,
287 spawn: Vector3,
288 angle: f32,
289 colour1: i32,
290 colour2: i32,
291 respawnDelay: i32,
292 addSiren: bool,
293 ) -> Option<Vehicle> {
294 let mut _id = 0;
295 functions::Vehicle_AddStaticEx(
296 modelid,
297 spawn.x,
298 spawn.y,
299 spawn.z,
300 angle,
301 colour1,
302 colour2,
303 respawnDelay,
304 addSiren,
305 &mut _id,
306 )
307 }
308
309 pub fn enable_friendly_fire() -> bool {
311 functions::Vehicle_EnableFriendlyFire()
312 }
313
314 pub fn get_spawn_info(&self) -> VehicleSpawnData {
316 let (
317 mut position,
318 mut rotation,
319 mut colour1,
320 mut colour2,
321 respawnDelay,
322 modelID,
323 siren,
324 interior,
325 ): (Vector3, f32, i32, i32, i32, i32, bool, i32) = Default::default();
326
327 functions::Vehicle_GetSpawnInfo(
328 self,
329 &mut position.x,
330 &mut position.y,
331 &mut position.z,
332 &mut rotation,
333 &mut colour1,
334 &mut colour2,
335 );
336
337 VehicleSpawnData {
338 position,
339 rotation,
340 colour1,
341 colour2,
342 respawnDelay,
343 modelID,
344 siren,
345 interior,
346 }
347 }
348 pub fn set_spawn_info(&self, data: VehicleSpawnData) -> bool {
350 functions::Vehicle_SetSpawnInfo(
351 self,
352 data.modelID,
353 data.position.x,
354 data.position.y,
355 data.position.z,
356 data.rotation,
357 data.colour1,
358 data.colour2,
359 data.respawnDelay,
360 data.interior,
361 )
362 }
363 pub fn get_model_count(modelid: i32) -> i32 {
365 functions::Vehicle_GetModelCount(modelid)
366 }
367 pub fn get_models_used() -> i32 {
369 functions::Vehicle_GetModelsUsed()
370 }
371 pub fn get_paintjob(&self) -> i32 {
373 functions::Vehicle_GetPaintjob(self)
374 }
375 pub fn get_color(&self) -> (i32, i32) {
376 let mut colour1 = -1;
377 let mut colour2 = -1;
378 functions::Vehicle_GetColor(self, &mut colour1, &mut colour2);
379 (colour1, colour2)
380 }
381 pub fn get_interior(&self) -> i32 {
383 functions::Vehicle_GetInterior(self)
384 }
385 pub fn get_number_plate(&self) -> String {
387 let mut number_plate = String::new();
388 functions::Vehicle_GetNumberPlate(self, &mut number_plate, 16);
389 number_plate
390 }
391 pub fn set_respawn_delay(&self, respawn_delay: i32) -> bool {
393 functions::Vehicle_SetRespawnDelay(self, respawn_delay)
394 }
395 pub fn get_respawn_delay(&self) -> i32 {
397 functions::Vehicle_GetRespawnDelay(self)
398 }
399 pub fn get_cab(&self) -> Option<Vehicle> {
401 functions::Vehicle_GetCab(self)
402 }
403 pub fn get_occupied_tick(&self) -> i32 {
405 functions::Vehicle_GetOccupiedTick(self)
406 }
407 pub fn get_respawn_tick(&self) -> i32 {
409 functions::Vehicle_GetRespawnTick(self)
410 }
411 pub fn has_been_occupied(&self) -> bool {
413 functions::Vehicle_HasBeenOccupied(self)
414 }
415 pub fn is_occupied(&self) -> bool {
417 functions::Vehicle_IsOccupied(self)
418 }
419 pub fn is_dead(&self) -> bool {
421 functions::Vehicle_IsDead(self)
422 }
423 pub fn toggle_siren_enabled(&self, status: bool) -> bool {
425 functions::Vehicle_ToggleSirenEnabled(self, status)
426 }
427 pub fn is_siren_enabled(&self) -> bool {
429 functions::Vehicle_IsSirenEnabled(self)
430 }
431 pub fn get_last_driver(&self) -> Option<Player> {
433 functions::Vehicle_GetLastDriver(self)
434 }
435 pub fn get_driver(&self) -> Option<Player> {
437 functions::Vehicle_GetDriver(self)
438 }
439
440 pub fn get_siren_state(&self) -> i32 {
442 functions::Vehicle_GetParamsSirenState(self)
443 }
444 pub fn get_hydra_reactor_angle(&self) -> u32 {
446 functions::Vehicle_GetHydraReactorAngle(self)
447 }
448 pub fn get_train_speed(&self) -> f32 {
450 functions::Vehicle_GetTrainSpeed(self)
451 }
452 pub fn get_matrix(&self) -> VehicleMatrix {
454 let (mut right, mut up, mut at): (Vector3, Vector3, Vector3) = Default::default();
455
456 functions::Vehicle_GetMatrix(
457 self,
458 &mut right.x,
459 &mut right.y,
460 &mut right.z,
461 &mut up.x,
462 &mut up.y,
463 &mut up.z,
464 &mut at.x,
465 &mut at.y,
466 &mut at.z,
467 );
468 VehicleMatrix { right, up, at }
469 }
470 pub fn get_occupant(&self, seat: i32) -> Option<Player> {
471 functions::Vehicle_GetOccupant(self, seat)
472 }
473 pub fn get_max_passengers(model: i32) -> i32 {
474 functions::Vehicle_GetMaxPassengerSeats(model)
475 }
476 pub fn count_occupants(&self) -> i32 {
477 functions::Vehicle_CountOccupants(self)
478 }
479 pub fn get_from_id(id: i32) -> Option<Vehicle> {
480 functions::Vehicle_FromID(id)
481 }
482 pub fn get_id(&self) -> i32 {
483 functions::Vehicle_GetID(self)
484 }
485
486 fn defer_api_call(&self, callback: Box<dyn FnOnce(Self)>) {
487 let vehicle_id = self.get_id();
488 queue_api_call(Box::new(move || {
489 let vehicle = match Self::get_from_id(vehicle_id) {
490 Some(vehicle) => vehicle,
491 None => {
492 log::error!("vehicle with id={vehicle_id} not found");
493 return;
494 }
495 };
496 callback(vehicle);
497 }));
498 }
499}
500
501#[repr(C)]
502pub struct VehicleParams {
503 pub engine: i8,
504 pub lights: i8,
505 pub alarm: i8,
506 pub doors: i8,
507 pub bonnet: i8,
508 pub boot: i8,
509 pub objective: i8,
510 pub siren: i8,
511 pub doorDriver: i8,
512 pub doorPassenger: i8,
513 pub doorBackLeft: i8,
514 pub doorBackRight: i8,
515 pub windowDriver: i8,
516 pub windowPassenger: i8,
517 pub windowBackLeft: i8,
518 pub windowBackRight: i8,
519}
520
521impl Default for VehicleParams {
522 fn default() -> Self {
523 Self {
524 engine: -1,
525 lights: -1,
526 alarm: -1,
527 doors: -1,
528 bonnet: -1,
529 boot: -1,
530 objective: -1,
531 siren: -1,
532 doorDriver: -1,
533 doorPassenger: -1,
534 doorBackLeft: -1,
535 doorBackRight: -1,
536 windowDriver: -1,
537 windowPassenger: -1,
538 windowBackLeft: -1,
539 windowBackRight: -1,
540 }
541 }
542}
543
544#[repr(C)]
545#[derive(Default, PartialEq, Clone, Copy, Debug)]
546pub struct UnoccupiedVehicleUpdate {
547 pub seat: i32,
548 pub position: Vector3,
549 pub velocity: Vector3,
550}
551
552#[derive(Default, PartialEq, Clone, Copy, Debug)]
553pub struct VehicleDamageStatusData {
554 pub panels: i32,
555 pub doors: i32,
556 pub lights: i32,
557 pub tires: i32,
558}
559
560#[derive(Default, PartialEq, Clone, Copy, Debug)]
561pub struct VehicleSpawnData {
562 pub respawnDelay: i32,
563 pub modelID: i32,
564 pub position: Vector3,
565 pub rotation: f32,
566 pub colour1: i32,
567 pub colour2: i32,
568 pub siren: bool,
569 pub interior: i32,
570}
571
572#[derive(Default, PartialEq, Clone, Copy, Debug)]
573pub struct VehicleMatrix {
574 pub right: Vector3,
575 pub up: Vector3,
576 pub at: Vector3,
577}