omp_gdk/scripting/objects/
mod.rs

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::{colour::Colour, vector::Vector3},
10    vehicles::Vehicle,
11};
12
13pub use functions::load_functions;
14
15pub struct Object {
16    handle: *const c_void,
17}
18
19impl Object {
20    pub fn get_handle(&self) -> *const c_void {
21        self.handle
22    }
23
24    pub fn new(handle: *const c_void) -> Self {
25        Self { handle }
26    }
27
28    /// Creates an object at specified coordinates in the game world.
29    pub fn create(
30        modelid: i32,
31        position: Vector3,
32        rotation: Vector3,
33        draw_distance: f32,
34    ) -> Option<Object> {
35        let mut _id = 0;
36        functions::Object_Create(
37            modelid,
38            position.x,
39            position.y,
40            position.z,
41            rotation.x,
42            rotation.y,
43            rotation.z,
44            draw_distance,
45            &mut _id,
46        )
47    }
48
49    /// Destroys (removes) an object that was created using create method.
50    pub fn destroy(&self) {
51        self.defer_api_call(Box::new(move |object| {
52            functions::Object_Destroy(&object);
53        }));
54    }
55
56    /// Attach an object to a vehicle.
57    pub fn attach_to_vehicle(&self, vehicle: &Vehicle, offset: Vector3, rotation: Vector3) -> bool {
58        functions::Object_AttachToVehicle(
59            self, vehicle, offset.x, offset.y, offset.z, rotation.x, rotation.y, rotation.z,
60        )
61    }
62
63    /// Attach an object to an object.
64    pub fn attach_to_object(
65        &self,
66        obj_attached_to: &Object,
67        offset: Vector3,
68        rotation: Vector3,
69        sync_rotation: bool,
70    ) -> bool {
71        functions::Object_AttachToObject(
72            self,
73            obj_attached_to,
74            offset.x,
75            offset.y,
76            offset.z,
77            rotation.x,
78            rotation.y,
79            rotation.z,
80            sync_rotation,
81        )
82    }
83
84    /// Attach a player object to a player.
85    pub fn attach_to_player(&self, player: &Player, offset: Vector3, rotation: Vector3) -> bool {
86        functions::Object_AttachToPlayer(
87            self, player, offset.x, offset.y, offset.z, rotation.x, rotation.y, rotation.z,
88        )
89    }
90
91    ///  Set the position of an object.
92    pub fn set_pos(&self, position: Vector3) -> bool {
93        functions::Object_SetPos(self, position.x, position.y, position.z)
94    }
95
96    ///  Locate an object.
97    pub fn get_pos(&self) -> Vector3 {
98        let mut pos = Vector3::default();
99        functions::Object_GetPos(self, &mut pos.x, &mut pos.y, &mut pos.z);
100        pos
101    }
102
103    /// Set the rotation of an object.
104    pub fn set_rotation(&self, rotation: Vector3) -> bool {
105        functions::Object_SetRot(self, rotation.x, rotation.y, rotation.z)
106    }
107
108    /// Get the rotation of an object.
109    pub fn get_rotation(&self) -> Vector3 {
110        let mut rotation = Vector3::default();
111        functions::Object_GetRot(self, &mut rotation.x, &mut rotation.y, &mut rotation.z);
112        rotation
113    }
114
115    /// Get the model ID of an object
116    pub fn get_model(&self) -> i32 {
117        functions::Object_GetModel(self)
118    }
119
120    /// Disable collisions between players' cameras and the specified object.
121    pub fn set_no_camera_collision(&self) -> bool {
122        functions::Object_SetNoCameraCollision(self)
123    }
124
125    /// Move an object to a new position with a set speed. Players/vehicles will 'surf' the object as it moves.
126    pub fn move_object(&self, data: ObjectMoveData) -> i32 {
127        self.defer_api_call(Box::new(move |object| {
128            functions::Object_Move(
129                &object,
130                data.targetPos.x,
131                data.targetPos.y,
132                data.targetPos.z,
133                data.speed,
134                data.targetRot.x,
135                data.targetRot.y,
136                data.targetRot.z,
137            );
138        }));
139
140        if data.speed <= 0.0 {
141            return 0; // avoid division by zero or negative time
142        }
143
144        let distance = (data.targetPos - self.get_pos()).length();
145        let time_ms = (distance / data.speed) * 1000.0;
146        time_ms as i32
147    }
148
149    /// Stop an object from moving.
150    pub fn stop(&self) -> bool {
151        functions::Object_Stop(self)
152    }
153
154    /// Check if the object is moving.
155    pub fn is_moving(&self) -> bool {
156        functions::Object_IsMoving(self)
157    }
158
159    /// Replace the texture of an object with the texture from another model in the game.
160    pub fn set_material(
161        &self,
162        material_index: i32,
163        model_id: i32,
164        texture_library: &str,
165        texture_name: &str,
166        material_colour: Colour,
167    ) -> bool {
168        functions::Object_SetMaterial(
169            self,
170            material_index,
171            model_id,
172            texture_library,
173            texture_name,
174            material_colour.argb(),
175        )
176    }
177
178    /// Replace the texture of an object with text.
179    pub fn set_material_text(
180        &self,
181        text: &str,
182        material_index: i32,
183        material_size: ObjectMaterialSize,
184        fontface: &str,
185        fontsize: i32,
186        bold: bool,
187        font_colour: Colour,
188        background_colour: Colour,
189        textalignment: ObjectMaterialTextAlign,
190    ) -> bool {
191        functions::Object_SetMaterialText(
192            self,
193            text,
194            material_index,
195            material_size as i32,
196            fontface,
197            fontsize,
198            bold,
199            font_colour.argb(),
200            background_colour.argb(),
201            textalignment as i32,
202        )
203    }
204
205    /// Allows camera collisions with newly created objects to be disabled by default.
206    pub fn set_objects_default_camera_collision(disable: bool) -> bool {
207        functions::Object_SetDefaultCameraCollision(disable)
208    }
209
210    /// Get the draw distance of an object.
211    pub fn get_draw_distance(&self) -> f32 {
212        functions::Object_GetDrawDistance(self)
213    }
214
215    /// Get the move speed of an object.
216    pub fn get_move_speed(&self) -> f32 {
217        functions::Object_GetMoveSpeed(self)
218    }
219
220    /// Get the move data of an object.
221    pub fn get_move_data(&self) -> ObjectMoveData {
222        let mut data = ObjectMoveData {
223            speed: functions::Object_GetMoveSpeed(self),
224            ..Default::default()
225        };
226
227        functions::Object_GetMovingTargetPos(
228            self,
229            &mut data.targetPos.x,
230            &mut data.targetPos.y,
231            &mut data.targetPos.z,
232        );
233        functions::Object_GetMovingTargetPos(
234            self,
235            &mut data.targetRot.x,
236            &mut data.targetRot.y,
237            &mut data.targetRot.z,
238        );
239        data
240    }
241
242    /// Get the attachment data of an object.
243    pub fn get_attached_data(&self) -> ObjectAttachmentData {
244        let mut data = ObjectAttachmentData::default();
245        let (mut pid, mut oid, mut vid): (i32, i32, i32) = (-1, -1, -1);
246
247        functions::Object_GetAttachedData(self, &mut pid, &mut oid, &mut vid);
248        if pid != 65535 {
249            data.ID = pid;
250            data.attachment_type = ObjectAttachmentType::Player;
251        } else if oid != 65535 {
252            data.ID = oid;
253            data.attachment_type = ObjectAttachmentType::Object;
254        } else if vid != 65535 {
255            data.ID = vid;
256            data.attachment_type = ObjectAttachmentType::Vehicle;
257        } else {
258            data.attachment_type = ObjectAttachmentType::None;
259        }
260
261        data.syncRotation = functions::Object_GetSyncRotation(self);
262        functions::Object_GetAttachedOffset(
263            self,
264            &mut data.offset.x,
265            &mut data.offset.y,
266            &mut data.offset.z,
267            &mut data.rotation.x,
268            &mut data.rotation.y,
269            &mut data.rotation.z,
270        );
271        data
272    }
273
274    /// Checks if a slot of object material is used.
275    pub fn is_material_slot_used(&self, material_index: i32) -> bool {
276        functions::Object_IsMaterialSlotUsed(self, material_index)
277    }
278
279    /// Get object's material data
280    pub fn get_material_data(&self, material_index: i32) -> ObjectMaterialData {
281        let (
282            mut modelid,
283            mut texture_library,
284            mut texture_name,
285            mut material_colour,
286            mut text,
287            mut material_size,
288            mut font_face,
289            mut font_size,
290            mut bold,
291            mut font_colour,
292            mut background_colour,
293            mut text_alignment,
294        ): (
295            i32,
296            String,
297            String,
298            i32,
299            String,
300            i32,
301            String,
302            i32,
303            bool,
304            i32,
305            i32,
306            i32,
307        ) = Default::default();
308
309        functions::Object_GetMaterial(
310            self,
311            material_index,
312            &mut modelid,
313            &mut texture_library,
314            16,
315            &mut texture_name,
316            16,
317            &mut material_colour,
318        );
319
320        functions::Object_GetMaterialText(
321            self,
322            material_index,
323            &mut text,
324            16,
325            &mut material_size,
326            &mut font_face,
327            16,
328            &mut font_size,
329            &mut bold,
330            &mut font_colour,
331            &mut background_colour,
332            &mut text_alignment,
333        );
334
335        ObjectMaterialData::new(
336            modelid,
337            texture_library,
338            texture_name,
339            Colour::from_argb(material_colour as u32),
340            text,
341            material_size,
342            font_face,
343            font_size,
344            bold,
345            Colour::from_argb(font_colour as u32),
346            Colour::from_argb(background_colour as u32),
347            text_alignment,
348        )
349    }
350
351    /// Check if collisions between players' cameras and the specified object is disabled.
352    pub fn is_no_camera_collision(&self) -> bool {
353        functions::Object_IsObjectNoCameraCollision(self)
354    }
355
356    /// Get object's id
357    pub fn get_id(&self) -> i32 {
358        functions::Object_GetID(self)
359    }
360
361    /// Get Object from an id
362    pub fn from_id(id: i32) -> Option<Object> {
363        functions::Object_FromID(id)
364    }
365
366    fn defer_api_call(&self, callback: Box<dyn FnOnce(Self)>) {
367        let object_id = self.get_id();
368        queue_api_call(Box::new(move || {
369            let object = match Self::from_id(object_id) {
370                Some(object) => object,
371                None => {
372                    log::error!("object with id={object_id} not found");
373                    return;
374                }
375            };
376            callback(object);
377        }));
378    }
379}
380
381pub struct PlayerObject {
382    handle: *const c_void,
383    pub player: Player,
384}
385
386impl PlayerObject {
387    pub fn get_handle(&self) -> *const c_void {
388        self.handle
389    }
390
391    pub fn new(handle: *const c_void, player: Player) -> Self {
392        Self { handle, player }
393    }
394
395    /// Attach a player object to a vehicle.
396    pub fn attach_player_object_to_vehicle(
397        &self,
398        vehicle: &Vehicle,
399        offset: Vector3,
400        rotation: Vector3,
401    ) -> bool {
402        functions::PlayerObject_AttachToVehicle(
403            &self.player,
404            self,
405            vehicle,
406            offset.x,
407            offset.y,
408            offset.z,
409            rotation.x,
410            rotation.y,
411            rotation.z,
412        )
413    }
414    /// Attach PlayerObject to another player
415    pub fn attach_player_object_to_player(
416        &self,
417        player_attached_to: &Player,
418        offset: Vector3,
419        rotation: Vector3,
420    ) -> bool {
421        functions::PlayerObject_AttachToPlayer(
422            &self.player,
423            self,
424            player_attached_to,
425            offset.x,
426            offset.y,
427            offset.z,
428            rotation.x,
429            rotation.y,
430            rotation.z,
431        )
432    }
433    /// You can use this function to attach player-objects to other player-objects.
434    pub fn attach_player_object_to_object(
435        &self,
436        attached_to: &PlayerObject,
437        offset: Vector3,
438        rotation: Vector3,
439    ) -> bool {
440        functions::PlayerObject_AttachToObject(
441            &self.player,
442            self,
443            attached_to,
444            offset.x,
445            offset.y,
446            offset.z,
447            rotation.x,
448            rotation.y,
449            rotation.z,
450        )
451    }
452    /// Sets the position of a player-object to the specified coordinates.
453    pub fn set_player_object_pos(&self, position: Vector3) -> bool {
454        functions::PlayerObject_SetPos(&self.player, self, position.x, position.y, position.z)
455    }
456    /// Get the position of a player object (CreatePlayerObject).
457    pub fn get_player_object_pos(&self) -> Vector3 {
458        let mut position = Vector3::default();
459        functions::PlayerObject_GetPos(
460            &self.player,
461            self,
462            &mut position.x,
463            &mut position.y,
464            &mut position.z,
465        );
466        position
467    }
468    /// Set the rotation of an object on the X, Y and Z axis.
469    pub fn set_player_object_rotation(&self, rotation: Vector3) -> bool {
470        functions::PlayerObject_SetRot(&self.player, self, rotation.x, rotation.y, rotation.z)
471    }
472    /// Use this function to get the object's current rotation.
473    pub fn get_player_object_rotation(&self) -> Vector3 {
474        let mut rotation = Vector3::default();
475        functions::PlayerObject_GetRot(
476            &self.player,
477            self,
478            &mut rotation.x,
479            &mut rotation.y,
480            &mut rotation.z,
481        );
482        rotation
483    }
484    /// Retrieve the model ID of a player-object.
485    pub fn get_player_object_model(&self) -> i32 {
486        functions::PlayerObject_GetModel(&self.player, self)
487    }
488    /// Toggles a player object camera collision.
489    pub fn set_player_object_no_camera_collision(&self) -> bool {
490        functions::PlayerObject_SetNoCameraCollision(&self.player, self)
491    }
492    /// Move a player object with a set speed.
493    pub fn move_player_object(&self, data: ObjectMoveData) -> i32 {
494        functions::PlayerObject_Move(
495            &self.player,
496            self,
497            data.targetPos.x,
498            data.targetPos.y,
499            data.targetPos.z,
500            data.speed,
501            data.targetRot.x,
502            data.targetRot.y,
503            data.targetRot.z,
504        )
505    }
506    /// Stop a moving player-object after MovePlayerObject has been used.
507    pub fn stop_player_object(&self) -> bool {
508        functions::PlayerObject_Stop(&self.player, self)
509    }
510    /// Checks if the given player objectid is moving.
511    pub fn is_player_object_moving(&self) -> bool {
512        functions::PlayerObject_IsMoving(&self.player, self)
513    }
514
515    /// Replace the texture of a player-object with the texture from another model in the game.
516    pub fn set_player_object_material(
517        &self,
518        material_index: i32,
519        model_id: i32,
520        texture_library: &str,
521        texture_name: &str,
522        material_colour: Colour,
523    ) -> bool {
524        functions::PlayerObject_SetMaterial(
525            &self.player,
526            self,
527            material_index,
528            model_id,
529            texture_library,
530            texture_name,
531            material_colour.argb(),
532        )
533    }
534    /// Replace the texture of a player object with text.
535    pub fn set_player_object_material_text(
536        &self,
537        text: &str,
538        material_index: i32,
539        material_size: i32,
540        fontface: &str,
541        fontsize: i32,
542        bold: bool,
543        font_colour: Colour,
544        background_colour: Colour,
545        textalignment: ObjectMaterialTextAlign,
546    ) -> bool {
547        functions::PlayerObject_SetMaterialText(
548            &self.player,
549            self,
550            text,
551            material_index,
552            material_size,
553            fontface,
554            fontsize,
555            bold,
556            font_colour.argb(),
557            background_colour.argb(),
558            textalignment as i32,
559        )
560    }
561    /// Get the draw distance of a player-object.
562    pub fn get_player_object_draw_distance(&self) -> f32 {
563        functions::PlayerObject_GetDrawDistance(&self.player, self)
564    }
565    /// Get the move speed of a player-object.
566    pub fn get_player_object_move_speed(&self) -> f32 {
567        functions::PlayerObject_GetMoveSpeed(&self.player, self)
568    }
569    pub fn get_player_object_moving_data(&self) -> ObjectMoveData {
570        let mut data = ObjectMoveData {
571            speed: functions::PlayerObject_GetMoveSpeed(&self.player, self),
572            ..Default::default()
573        };
574        functions::PlayerObject_GetMovingTargetPos(
575            &self.player,
576            self,
577            &mut data.targetPos.x,
578            &mut data.targetPos.y,
579            &mut data.targetPos.z,
580        );
581        functions::PlayerObject_GetMovingTargetRot(
582            &self.player,
583            self,
584            &mut data.targetRot.x,
585            &mut data.targetRot.y,
586            &mut data.targetRot.z,
587        );
588        data
589    }
590    /// Get the attachment data of a player-object.
591    pub fn get_player_object_attached_data(&self) -> ObjectAttachmentData {
592        let mut data = ObjectAttachmentData::default();
593        let (mut pid, mut oid, mut vid): (i32, i32, i32) = (-1, -1, -1);
594
595        functions::PlayerObject_GetAttachedData(&self.player, self, &mut pid, &mut oid, &mut vid);
596        if pid != 65535 {
597            data.ID = pid;
598            data.attachment_type = ObjectAttachmentType::Player;
599        } else if oid != 65535 {
600            data.ID = oid;
601            data.attachment_type = ObjectAttachmentType::Object;
602        } else if vid != 65535 {
603            data.ID = vid;
604            data.attachment_type = ObjectAttachmentType::Vehicle;
605        } else {
606            data.attachment_type = ObjectAttachmentType::None;
607        }
608
609        data.syncRotation = functions::PlayerObject_GetSyncRotation(&self.player, self);
610        functions::PlayerObject_GetAttachedOffset(
611            &self.player,
612            self,
613            &mut data.offset.x,
614            &mut data.offset.y,
615            &mut data.offset.z,
616            &mut data.rotation.x,
617            &mut data.rotation.y,
618            &mut data.rotation.z,
619        );
620        data
621    }
622    /// Checks if a slot of player-object material is used.
623    pub fn is_player_object_material_slot_used(&self, material_index: i32) -> bool {
624        functions::PlayerObject_IsMaterialSlotUsed(&self.player, self, material_index)
625    }
626    pub fn get_player_object_material_data(&self, material_index: i32) -> ObjectMaterialData {
627        let (
628            mut modelid,
629            mut texture_library,
630            mut texture_name,
631            mut material_colour,
632            mut text,
633            mut material_size,
634            mut font_face,
635            mut font_size,
636            mut bold,
637            mut font_colour,
638            mut background_colour,
639            mut text_alignment,
640        ): (
641            i32,
642            String,
643            String,
644            i32,
645            String,
646            i32,
647            String,
648            i32,
649            bool,
650            i32,
651            i32,
652            i32,
653        ) = Default::default();
654
655        functions::PlayerObject_GetMaterial(
656            &self.player,
657            self,
658            material_index,
659            &mut modelid,
660            &mut texture_library,
661            16,
662            &mut texture_name,
663            16,
664            &mut material_colour,
665        );
666
667        functions::PlayerObject_GetMaterialText(
668            &self.player,
669            self,
670            material_index,
671            &mut text,
672            16,
673            &mut material_size,
674            &mut font_face,
675            16,
676            &mut font_size,
677            &mut bold,
678            &mut font_colour,
679            &mut background_colour,
680            &mut text_alignment,
681        );
682
683        ObjectMaterialData::new(
684            modelid,
685            texture_library,
686            texture_name,
687            Colour::from_argb(material_colour as u32),
688            text,
689            material_size,
690            font_face,
691            font_size,
692            bold,
693            Colour::from_argb(font_colour as u32),
694            Colour::from_argb(background_colour as u32),
695            text_alignment,
696        )
697    }
698    /// Check if collisions between players' cameras and the specified player object is disabled.
699    pub fn is_player_object_no_camera_collision(&self) -> bool {
700        functions::PlayerObject_IsNoCameraCollision(&self.player, self)
701    }
702
703    /// Get player object's id
704    pub fn get_id(&self) -> i32 {
705        functions::PlayerObject_GetID(&self.player, self)
706    }
707}
708
709/// Object moving information
710#[repr(C)]
711#[derive(Default, Clone, Copy, Debug)]
712pub struct ObjectMoveData {
713    /// The position the object moving to.
714    pub targetPos: Vector3,
715    /// The final rotation of the object.
716    pub targetRot: Vector3,
717    /// The speed at which to move the object (units per second).
718    pub speed: f32,
719}
720
721/// The type of attachment attached to Object
722#[repr(C)]
723#[derive(Default, PartialEq, Clone, Copy, Debug)]
724pub enum ObjectAttachmentType {
725    #[default]
726    None,
727    Vehicle,
728    Object,
729    Player,
730}
731
732/// Data information of attachment
733#[repr(C)]
734#[derive(Default, Clone, Copy, Debug)]
735pub struct ObjectAttachmentData {
736    /// Type of attachement
737    pub attachment_type: ObjectAttachmentType,
738    /// the sync rotation of the object
739    pub syncRotation: bool,
740    /// ID of the object (use from_id methods to create an instance of these)
741    pub ID: i32,
742    /// Attachement offset
743    pub offset: Vector3,
744    /// Attachement rotation
745    pub rotation: Vector3,
746}
747
748/// Alignment of Object material text
749#[repr(C)]
750#[derive(PartialEq, Clone, Copy, Debug)]
751pub enum ObjectMaterialTextAlign {
752    Left,
753    Center,
754    Right,
755}
756
757/// Size of Object material
758#[repr(C)]
759#[derive(PartialEq, Clone, Copy, Debug)]
760pub enum ObjectMaterialSize {
761    Size32x32 = 10,
762    Size64x32 = 20,
763    Size64x64 = 30,
764    Size128x32 = 40,
765    Size128x64 = 50,
766    Size128x128 = 60,
767    Size256x32 = 70,
768    Size256x64 = 80,
769    Size256x128 = 90,
770    Size256x256 = 100,
771    Size512x64 = 110,
772    Size512x128 = 120,
773    Size512x256 = 130,
774    Size512x512 = 140,
775}
776
777/// Kind of Object Material
778#[repr(C)]
779#[derive(PartialEq, Clone, Copy, Debug)]
780pub enum ObjectMaterialType {
781    None,
782    Default,
783    Text,
784}
785
786/// Object Material Data
787#[derive(PartialEq, Clone, Debug)]
788pub struct ObjectMaterialData {
789    pub modelid: i32,
790    pub textureLibrary: String,
791    pub textureName: String,
792    pub materialColour: Colour,
793    pub text: String,
794    pub materialSize: i32,
795    pub fontFace: String,
796    pub fontSize: i32,
797    pub bold: bool,
798    pub fontColour: Colour,
799    pub backgroundColour: Colour,
800    pub textAlignment: i32,
801}
802
803impl ObjectMaterialData {
804    pub fn new(
805        modelid: i32,
806        textureLibrary: String,
807        textureName: String,
808        materialColour: Colour,
809        text: String,
810        materialSize: i32,
811        fontFace: String,
812        fontSize: i32,
813        bold: bool,
814        fontColour: Colour,
815        backgroundColour: Colour,
816        textAlignment: i32,
817    ) -> Self {
818        Self {
819            modelid,
820            textureLibrary,
821            textureName,
822            materialColour,
823            text,
824            materialSize,
825            fontFace,
826            fontSize,
827            bold,
828            fontColour,
829            backgroundColour,
830            textAlignment,
831        }
832    }
833}
834
835#[repr(C)]
836#[derive(PartialEq, Clone, Copy, Debug)]
837pub enum ObjectEditResponse {
838    Cancel,
839    Final,
840    Update,
841}
842
843#[repr(C)]
844#[derive(Clone, Copy, Debug, Default)]
845pub struct ObjectAttachmentSlotData {
846    pub model: i32,
847    pub bone: i32,
848    pub offset: Vector3,
849    pub rotation: Vector3,
850    pub scale: Vector3,
851    pub colour1: Colour,
852    pub colour2: Colour,
853}