omp_gdk/scripting/actors/
mod.rs

1pub mod events;
2pub mod functions;
3
4pub use functions::load_functions;
5
6use crate::players::Player;
7use crate::runtime::queue_api_call;
8use crate::types::animationdata::AnimationData;
9use crate::types::vector::Vector3;
10
11use std::ffi::c_void;
12
13/// Main handler pointing to open.mp's Actor object
14pub struct Actor {
15    handle: *const c_void,
16}
17
18impl Actor {
19    pub fn get_handle(&self) -> *const c_void {
20        self.handle
21    }
22
23    pub fn new(handle: *const c_void) -> Self {
24        Self { handle }
25    }
26
27    /// Create a static 'actor' in the world.
28    /// These 'actors' are like NPCs, however they have limited functionality.
29    /// They do not take up server player slots.
30    pub fn create_actor(skin: i32, pos: Vector3, angle: f32) -> Option<Actor> {
31        let mut _id: i32 = 0;
32        functions::Actor_Create(skin, pos.x, pos.y, pos.z, angle, &mut _id)
33    }
34
35    /// Destroys an Actor
36    pub fn destroy(&self) {
37        self.defer_api_call(Box::new(move |actor| {
38            functions::Actor_Destroy(&actor);
39        }));
40    }
41
42    /// Checks if an actor is streamed in for a player.
43    pub fn is_streamed_in(&self, player: &Player) -> bool {
44        functions::Actor_IsStreamedInFor(self, player)
45    }
46
47    /// Sets an actor's virtual world
48    pub fn set_virtual_world(&self, virtual_world: i32) -> bool {
49        functions::Actor_SetVirtualWorld(self, virtual_world)
50    }
51
52    /// Get the virtual world of an actor.
53    pub fn get_virtual_world(&self) -> i32 {
54        functions::Actor_GetVirtualWorld(self)
55    }
56
57    /// Apply an animation to an actor.
58    pub fn apply_animation(&self, animation_data: AnimationData) -> bool {
59        functions::Actor_ApplyAnimation(
60            self,
61            &animation_data.get_animation_library(),
62            &animation_data.get_name(),
63            animation_data.delta,
64            animation_data.looping,
65            animation_data.lockX,
66            animation_data.lockY,
67            animation_data.freeze,
68            animation_data.time,
69        )
70    }
71
72    /// Clear any animations that are applied to an actor.
73    pub fn clear_animations(&self) -> bool {
74        functions::Actor_ClearAnimations(self)
75    }
76
77    /// Set the position of an actor.
78    pub fn set_pos(&self, pos: Vector3) {
79        self.defer_api_call(Box::new(move |actor| {
80            functions::Actor_SetPos(&actor, pos.x, pos.y, pos.z);
81        }));
82    }
83
84    /// Get the position of an actor.
85    pub fn get_pos(&self) -> Vector3 {
86        let mut position = Vector3 {
87            x: 0.0,
88            y: 0.0,
89            z: 0.0,
90        };
91        functions::Actor_GetPos(self, &mut position.x, &mut position.y, &mut position.z);
92        position
93    }
94
95    /// Set the facing angle of an actor.
96    pub fn set_facing_angle(&self, angle: f32) -> bool {
97        functions::Actor_SetFacingAngle(self, angle)
98    }
99
100    /// Get the facing angle of an actor.
101    pub fn get_facing_angle(&self) -> f32 {
102        functions::Actor_GetFacingAngle(self)
103    }
104
105    /// Set the health of an actor.
106    pub fn set_health(&self, health: f32) {
107        self.defer_api_call(Box::new(move |actor| {
108            functions::Actor_SetHealth(&actor, health);
109        }));
110    }
111
112    /// Get the health of an actor
113    pub fn get_health(&self) -> f32 {
114        functions::Actor_GetHealth(self)
115    }
116
117    /// Set actor invulnerability
118    pub fn set_invulnerable(&self, invulnerable: bool) -> bool {
119        functions::Actor_SetInvulnerable(self, invulnerable)
120    }
121
122    /// Check if actor is invulnerable.
123    pub fn is_invulnerable(&self) -> bool {
124        functions::Actor_IsInvulnerable(self)
125    }
126
127    /// Set the skin of the actor.
128    pub fn set_skin(&self, skin: i32) -> bool {
129        functions::Actor_SetSkin(self, skin)
130    }
131
132    /// Get the skin of the actor.
133    pub fn get_skin(&self) -> i32 {
134        functions::Actor_GetSkin(self)
135    }
136
137    /// Get the animation the actor is currently performing.
138    pub fn get_animation(&self) -> AnimationData {
139        let (
140            mut animation_library,
141            mut animation_name,
142            mut delta,
143            mut animloop,
144            mut lock_x,
145            mut lock_y,
146            mut freeze,
147            mut time,
148        ) = Default::default();
149
150        functions::Actor_GetAnimation(
151            self,
152            &mut animation_library,
153            16,
154            &mut animation_name,
155            24,
156            &mut delta,
157            &mut animloop,
158            &mut lock_x,
159            &mut lock_y,
160            &mut freeze,
161            &mut time,
162        );
163
164        AnimationData::new(
165            delta,
166            animloop,
167            lock_x,
168            lock_y,
169            freeze,
170            time,
171            &animation_library,
172            &animation_name,
173        )
174    }
175
176    /// Get the initial spawn point of the actor.
177    pub fn get_spawn_info(&self) -> ActorSpawnData {
178        let mut spawn_data = ActorSpawnData::default();
179        functions::Actor_GetSpawnInfo(
180            self,
181            &mut spawn_data.position.x,
182            &mut spawn_data.position.y,
183            &mut spawn_data.position.z,
184            &mut spawn_data.facingAngle,
185            &mut spawn_data.skin,
186        );
187        spawn_data
188    }
189
190    /// Get id of the Actor object
191    pub fn get_id(&self) -> i32 {
192        functions::Actor_GetID(self)
193    }
194
195    /// Get the Actor object from an id
196    pub fn from_id(actorid: i32) -> Option<Actor> {
197        functions::Actor_FromID(actorid)
198    }
199
200    fn defer_api_call(&self, callback: Box<dyn FnOnce(Self)>) {
201        let actor_id = self.get_id();
202        queue_api_call(Box::new(move || {
203            let actor = match Self::from_id(actor_id) {
204                Some(actor) => actor,
205                None => {
206                    log::error!("actor with id={actor_id} not found");
207                    return;
208                }
209            };
210            callback(actor);
211        }));
212    }
213}
214
215/// Actor's spawn information
216#[derive(Copy, Clone, Debug, Default)]
217#[repr(C)]
218pub struct ActorSpawnData {
219    pub position: Vector3,
220    pub facingAngle: f32,
221    pub skin: i32,
222}