pub mod events;
pub mod functions;
use std::ffi::c_void;
use crate::{
players::Player,
runtime::queue_api_call,
types::vector::{Vector3, Vector4},
};
pub use functions::load_functions;
pub struct Vehicle {
handle: *const c_void,
}
impl Vehicle {
pub fn get_handle(&self) -> *const c_void {
self.handle
}
pub fn new(handle: *const c_void) -> Self {
Self { handle }
}
pub fn create(
modelid: i32,
pos: Vector3,
rotation: f32,
colour1: i32,
colour2: i32,
respawnDelay: i32,
addSiren: bool,
) -> Option<Vehicle> {
let mut _id = 0;
functions::Vehicle_Create(
modelid,
pos.x,
pos.y,
pos.z,
rotation,
colour1,
colour2,
respawnDelay,
addSiren,
&mut _id,
)
}
pub fn get_seats(modelid: i32) -> i32 {
functions::Vehicle_GetMaxPassengerSeats(modelid)
}
pub fn destroy(&self) {
self.defer_api_call(Box::new(|vehicle| {
functions::Vehicle_Destroy(&vehicle);
}));
}
pub fn is_streamed_in(&self, player: &Player) -> bool {
functions::Vehicle_IsStreamedIn(self, player)
}
pub fn get_pos(&self) -> Vector3 {
let mut pos = Vector3::default();
functions::Vehicle_GetPos(self, &mut pos.x, &mut pos.y, &mut pos.z);
pos
}
pub fn set_pos(&self, pos: Vector3) {
self.defer_api_call(Box::new(move |vehicle| {
functions::Vehicle_SetPos(&vehicle, pos.x, pos.y, pos.z);
}));
}
pub fn get_z_angle(&self) -> f32 {
functions::Vehicle_GetZAngle(self)
}
pub fn get_rotation_quat(&self) -> Vector4 {
let mut rotation = Vector4::default();
functions::Vehicle_GetRotationQuat(
self,
&mut rotation.w,
&mut rotation.x,
&mut rotation.y,
&mut rotation.z,
);
rotation
}
pub fn get_distance_from_point(&self, pos: Vector3) -> f32 {
functions::Vehicle_GetDistanceFromPoint(self, pos.x, pos.y, pos.z)
}
pub fn set_z_angle(&self, angle: f32) -> bool {
functions::Vehicle_SetZAngle(self, angle)
}
pub fn set_params_for_player(&self, player: &Player, params: VehicleParams) -> bool {
functions::Vehicle_SetParamsForPlayer(
self,
player,
params.objective as i32,
params.doors as i32,
)
}
pub fn use_manual_engine_and_lights() -> bool {
functions::Vehicle_UseManualEngineAndLights()
}
pub fn set_params(&self, params: VehicleParams) -> bool {
functions::Vehicle_SetParamsEx(
self,
params.engine as i32,
params.lights as i32,
params.alarm as i32,
params.doors as i32,
params.bonnet as i32,
params.boot as i32,
params.objective as i32,
)
}
pub fn get_params(&self) -> VehicleParams {
let mut params = VehicleParams::default();
functions::Vehicle_GetParamsEx(
self,
&mut params.engine,
&mut params.lights,
&mut params.alarm,
&mut params.doors,
&mut params.bonnet,
&mut params.boot,
&mut params.objective,
);
params
}
pub fn set_to_respawn(&self) {
self.defer_api_call(Box::new(move |vehicle| {
functions::Vehicle_SetToRespawn(&vehicle);
}));
}
pub fn link_to_interior(&self, interiorid: i32) {
self.defer_api_call(Box::new(move |vehicle| {
functions::Vehicle_LinkToInterior(&vehicle, interiorid);
}));
}
pub fn add_component(&self, componentid: i32) -> bool {
functions::Vehicle_AddComponent(self, componentid)
}
pub fn remove_component(&self, componentid: i32) -> bool {
functions::Vehicle_RemoveComponent(self, componentid)
}
pub fn change_color(&self, colour1: i32, colour2: i32) -> bool {
functions::Vehicle_ChangeColor(self, colour1, colour2)
}
pub fn change_paintjob(&self, paintjobid: i32) -> bool {
functions::Vehicle_ChangePaintjob(self, paintjobid)
}
pub fn set_health(&self, health: f32) {
self.defer_api_call(Box::new(move |vehicle| {
functions::Vehicle_SetHealth(&vehicle, health);
}));
}
pub fn get_health(&self) -> f32 {
functions::Vehicle_GetHealth(self)
}
pub fn attach_trailer(&self, trailer: &Vehicle) -> bool {
functions::Vehicle_AttachTrailer(self, trailer)
}
pub fn detach_trailer(&self) -> bool {
functions::Vehicle_DetachTrailer(self)
}
pub fn is_trailer_attached(&self) -> bool {
functions::Vehicle_IsTrailerAttached(self)
}
pub fn get_trailer(&self) -> Option<Vehicle> {
functions::Vehicle_GetTrailer(self)
}
pub fn set_number_plate(&self, numberPlate: &str) -> bool {
functions::Vehicle_SetNumberPlate(self, numberPlate)
}
pub fn get_model(&self) -> i32 {
functions::Vehicle_GetModel(self)
}
pub fn get_component_in_slot(&self, slot: i32) -> i32 {
functions::Vehicle_GetComponentInSlot(self, slot)
}
pub fn get_component_type(componentid: i32) -> i32 {
functions::Vehicle_GetComponentType(componentid)
}
pub fn can_have_component(modelid: i32, componentid: i32) -> bool {
functions::Vehicle_CanHaveComponent(modelid, componentid)
}
pub fn get_random_car_col_pair(modelid: i32) -> (i32, i32, i32, i32) {
let (mut colour1, mut colour2, mut colour3, mut colour4) = Default::default();
functions::Vehicle_GetRandomColorPair(
modelid,
&mut colour1,
&mut colour2,
&mut colour3,
&mut colour4,
);
(colour1, colour2, colour3, colour4)
}
pub fn colour_index_to_colour(colourIndex: i32, alpha: i32) -> i32 {
functions::Vehicle_ColorIndexToColor(colourIndex, alpha)
}
pub fn repair(&self) {
self.defer_api_call(Box::new(move |vehicle| {
functions::Vehicle_Repair(&vehicle);
}));
}
pub fn get_velocity(&self) -> Vector3 {
let mut velocity = Vector3::default();
functions::Vehicle_GetVelocity(self, &mut velocity.x, &mut velocity.y, &mut velocity.z);
velocity
}
pub fn set_velocity(&self, velocity: Vector3) {
self.defer_api_call(Box::new(move |vehicle| {
functions::Vehicle_SetVelocity(&vehicle, velocity.x, velocity.y, velocity.z);
}));
}
pub fn set_angular_velocity(&self, velocity: Vector3) -> bool {
functions::Vehicle_SetAngularVelocity(self, velocity.x, velocity.y, velocity.z)
}
pub fn get_damage_status(&self) -> VehicleDamageStatusData {
let (mut panels, mut doors, mut lights, mut tires) = Default::default();
functions::Vehicle_GetDamageStatus(self, &mut panels, &mut doors, &mut lights, &mut tires);
VehicleDamageStatusData {
panels,
doors,
lights,
tires,
}
}
pub fn update_damage_status(&self, panels: i32, doors: i32, lights: i32, tires: i32) {
self.defer_api_call(Box::new(move |vehicle| {
functions::Vehicle_UpdateDamageStatus(&vehicle, panels, doors, lights, tires);
}));
}
pub fn get_model_info(model: i32, infotype: i32) -> Vector3 {
let mut pos = Vector3::default();
functions::Vehicle_GetModelInfo(model, infotype, &mut pos.x, &mut pos.y, &mut pos.z);
pos
}
pub fn set_virtual_world(&self, virtualWorld: i32) -> bool {
functions::Vehicle_SetVirtualWorld(self, virtualWorld)
}
pub fn get_virtual_world(&self) -> i32 {
functions::Vehicle_GetVirtualWorld(self)
}
pub fn get_landing_gear_state(&self) -> i32 {
functions::Vehicle_GetLandingGearState(self)
}
pub fn create_static(
modelid: i32,
spawn: Vector3,
angle: f32,
colour1: i32,
colour2: i32,
respawnDelay: i32,
addSiren: bool,
) -> Option<Vehicle> {
let mut _id = 0;
functions::Vehicle_AddStaticEx(
modelid,
spawn.x,
spawn.y,
spawn.z,
angle,
colour1,
colour2,
respawnDelay,
addSiren,
&mut _id,
)
}
pub fn enable_friendly_fire() -> bool {
functions::Vehicle_EnableFriendlyFire()
}
pub fn get_spawn_info(&self) -> VehicleSpawnData {
let (
mut position,
mut rotation,
mut colour1,
mut colour2,
respawnDelay,
modelID,
siren,
interior,
): (Vector3, f32, i32, i32, i32, i32, bool, i32) = Default::default();
functions::Vehicle_GetSpawnInfo(
self,
&mut position.x,
&mut position.y,
&mut position.z,
&mut rotation,
&mut colour1,
&mut colour2,
);
VehicleSpawnData {
position,
rotation,
colour1,
colour2,
respawnDelay,
modelID,
siren,
interior,
}
}
pub fn set_spawn_info(&self, data: VehicleSpawnData) -> bool {
functions::Vehicle_SetSpawnInfo(
self,
data.modelID,
data.position.x,
data.position.y,
data.position.z,
data.rotation,
data.colour1,
data.colour2,
data.respawnDelay,
data.interior,
)
}
pub fn get_model_count(modelid: i32) -> i32 {
functions::Vehicle_GetModelCount(modelid)
}
pub fn get_models_used() -> i32 {
functions::Vehicle_GetModelsUsed()
}
pub fn get_paintjob(&self) -> i32 {
functions::Vehicle_GetPaintjob(self)
}
pub fn get_color(&self) -> (i32, i32) {
let mut colour1 = -1;
let mut colour2 = -1;
functions::Vehicle_GetColor(self, &mut colour1, &mut colour2);
(colour1, colour2)
}
pub fn get_interior(&self) -> i32 {
functions::Vehicle_GetInterior(self)
}
pub fn get_number_plate(&self) -> String {
let mut number_plate = String::new();
functions::Vehicle_GetNumberPlate(self, &mut number_plate, 16);
number_plate
}
pub fn set_respawn_delay(&self, respawn_delay: i32) -> bool {
functions::Vehicle_SetRespawnDelay(self, respawn_delay)
}
pub fn get_respawn_delay(&self) -> i32 {
functions::Vehicle_GetRespawnDelay(self)
}
pub fn get_cab(&self) -> Option<Vehicle> {
functions::Vehicle_GetCab(self)
}
pub fn get_occupied_tick(&self) -> i32 {
functions::Vehicle_GetOccupiedTick(self)
}
pub fn get_respawn_tick(&self) -> i32 {
functions::Vehicle_GetRespawnTick(self)
}
pub fn has_been_occupied(&self) -> bool {
functions::Vehicle_HasBeenOccupied(self)
}
pub fn is_occupied(&self) -> bool {
functions::Vehicle_IsOccupied(self)
}
pub fn is_dead(&self) -> bool {
functions::Vehicle_IsDead(self)
}
pub fn toggle_siren_enabled(&self, status: bool) -> bool {
functions::Vehicle_ToggleSirenEnabled(self, status)
}
pub fn is_siren_enabled(&self) -> bool {
functions::Vehicle_IsSirenEnabled(self)
}
pub fn get_last_driver(&self) -> Option<Player> {
functions::Vehicle_GetLastDriver(self)
}
pub fn get_driver(&self) -> Option<Player> {
functions::Vehicle_GetDriver(self)
}
pub fn get_siren_state(&self) -> i32 {
functions::Vehicle_GetParamsSirenState(self)
}
pub fn get_hydra_reactor_angle(&self) -> u32 {
functions::Vehicle_GetHydraReactorAngle(self)
}
pub fn get_train_speed(&self) -> f32 {
functions::Vehicle_GetTrainSpeed(self)
}
pub fn get_matrix(&self) -> VehicleMatrix {
let (mut right, mut up, mut at): (Vector3, Vector3, Vector3) = Default::default();
functions::Vehicle_GetMatrix(
self,
&mut right.x,
&mut right.y,
&mut right.z,
&mut up.x,
&mut up.y,
&mut up.z,
&mut at.x,
&mut at.y,
&mut at.z,
);
VehicleMatrix { right, up, at }
}
pub fn get_occupant(&self, seat: i32) -> Option<Player> {
functions::Vehicle_GetOccupant(self, seat)
}
pub fn get_max_passengers(model: i32) -> i32 {
functions::Vehicle_GetMaxPassengerSeats(model)
}
pub fn count_occupants(&self) -> i32 {
functions::Vehicle_CountOccupants(self)
}
pub fn get_from_id(id: i32) -> Option<Vehicle> {
functions::Vehicle_FromID(id)
}
pub fn get_id(&self) -> i32 {
functions::Vehicle_GetID(self)
}
fn defer_api_call(&self, callback: Box<dyn FnOnce(Self)>) {
let vehicle_id = self.get_id();
queue_api_call(Box::new(move || {
let vehicle = match Self::get_from_id(vehicle_id) {
Some(vehicle) => vehicle,
None => {
log::error!("vehicle with id={vehicle_id} not found");
return;
}
};
callback(vehicle);
}));
}
}
#[repr(C)]
pub struct VehicleParams {
pub engine: i8,
pub lights: i8,
pub alarm: i8,
pub doors: i8,
pub bonnet: i8,
pub boot: i8,
pub objective: i8,
pub siren: i8,
pub doorDriver: i8,
pub doorPassenger: i8,
pub doorBackLeft: i8,
pub doorBackRight: i8,
pub windowDriver: i8,
pub windowPassenger: i8,
pub windowBackLeft: i8,
pub windowBackRight: i8,
}
impl Default for VehicleParams {
fn default() -> Self {
Self {
engine: -1,
lights: -1,
alarm: -1,
doors: -1,
bonnet: -1,
boot: -1,
objective: -1,
siren: -1,
doorDriver: -1,
doorPassenger: -1,
doorBackLeft: -1,
doorBackRight: -1,
windowDriver: -1,
windowPassenger: -1,
windowBackLeft: -1,
windowBackRight: -1,
}
}
}
#[repr(C)]
#[derive(Default, PartialEq, Clone, Copy, Debug)]
pub struct UnoccupiedVehicleUpdate {
pub seat: i32,
pub position: Vector3,
pub velocity: Vector3,
}
#[derive(Default, PartialEq, Clone, Copy, Debug)]
pub struct VehicleDamageStatusData {
pub panels: i32,
pub doors: i32,
pub lights: i32,
pub tires: i32,
}
#[derive(Default, PartialEq, Clone, Copy, Debug)]
pub struct VehicleSpawnData {
pub respawnDelay: i32,
pub modelID: i32,
pub position: Vector3,
pub rotation: f32,
pub colour1: i32,
pub colour2: i32,
pub siren: bool,
pub interior: i32,
}
#[derive(Default, PartialEq, Clone, Copy, Debug)]
pub struct VehicleMatrix {
pub right: Vector3,
pub up: Vector3,
pub at: Vector3,
}