1use std::{collections::HashMap, error::Error, ffi::CStr};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 ai_interface::{
7 callback::{
8 resource::Resource,
9 weapon_def::{
10 bounce::{WeaponBounce, WeaponBounceAll},
11 shield::{WeaponShield, WeaponShieldAll},
12 },
13 },
14 AIInterface,
15 },
16 get_callback,
17};
18
19pub mod bounce;
20pub mod shield;
21
22#[derive(Debug, Copy, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
23pub struct WeaponDef {
24 pub ai_id: i32,
25 pub weapon_def_id: i32,
26}
27
28#[derive(Debug, Clone)]
29pub struct WeaponDefInterface {
30 pub ai_id: i32,
31}
32
33#[derive(Debug, Copy, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
34pub enum Trajectory {
35 Low,
36 High,
37 Unit,
38}
39
40#[derive(Debug, Clone)]
41pub struct WeaponDefAll {
42 name: String,
43 description: String,
44 range: f32,
45 spray_angle: f32,
46 moving_accuracy: f32,
47 target_move_error: f32,
48 lead_limit: f32,
49 lead_bonus: f32,
50 predict_boost: f32,
51 paralyze_damage_time: i32,
52 impulse_factor: f32,
53 impulse_boost: f32,
54 crater_multiplier: f32,
55 crater_boost: f32,
56 area_of_effect: f32,
57 self_damage: bool,
58 fire_starter: f32,
59 edge_effectivness: f32,
60 size: f32,
61 size_growth: f32,
62 collision_size: f32,
63 salvo_size: i32,
64 salvo_delay: f32,
65 reload: f32,
66 beam_time: f32,
67 beam_burst: bool,
68 bounce: WeaponBounceAll,
69 max_angle: f32,
70 up_time: f32,
71 flight_time: i32,
72 cost: HashMap<Resource, f32>,
73 projectiles_per_shot: i32,
74 turret: bool,
75 only_forward: bool,
76 fixed_launcher: bool,
77 water_weapon: bool,
78 fire_submersed: bool,
79 sub_missile: bool,
80 tracks: bool,
81 dropped: bool,
82 paralyzer: bool,
83 impact_only: bool,
84 auto_target: bool,
85 manual_fire: bool,
86 interceptor: bool,
87 targetable: bool,
88 stockpileable: bool,
89 stockpile_time: f32,
90 interceptor_coverage_range: f32,
91 fall_off_rate: f32,
92 sound_trigger: bool,
93 self_explode: bool,
94 gravity_affected: bool,
95 trajectory: Trajectory,
96 trajectory_height: f32,
97 gravity: f32,
98 explode: bool,
99 start_velocity: f32,
100 max_velocity: f32,
101 weapon_acceleration: f32,
102 turn_rate: f32,
103 projectile_speed: f32,
104 explosion_speed: f32,
105 wobble: f32,
106 dance: f32,
107 large_beam_laser: bool,
108 shield: Option<WeaponShieldAll>,
109 avoid_friendly: bool,
110 avoid_feature: bool,
111 avoid_neutral: bool,
112 target_border: f32,
113 cylinder_targetting: f32,
114 minimum_intensity: f32,
115 height_boost_factor: f32,
116 proximity_priority: f32,
117 sweep_fire: bool,
118 able_to_attack_ground: bool,
119 dynamic_damage_exponent: f32,
120 dynamic_damage_minimum: f32,
121 dynamic_damage_range: f32,
122 dynamic_damage_inverted: bool,
123}
124
125impl AIInterface {
126 pub fn weapon_def_interface(&self) -> WeaponDefInterface {
127 WeaponDefInterface { ai_id: self.ai_id }
128 }
129}
130
131const MAX_WEAPON_DEFS: usize = 128;
132
133impl WeaponDefInterface {
134 pub fn get_weapon_defs(&self) -> Result<Vec<WeaponDef>, Box<dyn Error>> {
135 let get_weapon_defs_func = get_callback!(self.ai_id, getWeaponDefs)?;
136
137 Ok((0..unsafe { get_weapon_defs_func(self.ai_id) })
138 .map(|i| WeaponDef {
139 ai_id: self.ai_id,
140 weapon_def_id: i,
141 })
142 .collect())
143 }
144}
145
146impl WeaponDef {
147 pub fn name(&self) -> Result<String, Box<dyn Error>> {
148 let get_name = get_callback!(self.ai_id, WeaponDef_getName)?;
149 Ok(String::from(
150 unsafe { CStr::from_ptr(get_name(self.ai_id, self.weapon_def_id)) }.to_str()?,
151 ))
152 }
153
154 pub fn description(&self) -> Result<String, Box<dyn Error>> {
155 let get_description = get_callback!(self.ai_id, WeaponDef_getDescription)?;
156 Ok(String::from(
157 unsafe { CStr::from_ptr(get_description(self.ai_id, self.weapon_def_id)) }.to_str()?,
158 ))
159 }
160
161 pub fn range(&self) -> Result<f32, Box<dyn Error>> {
162 let get_range = get_callback!(self.ai_id, WeaponDef_getRange)?;
163 Ok(unsafe { get_range(self.ai_id, self.weapon_def_id) })
164 }
165
166 pub fn spray_angle(&self) -> Result<f32, Box<dyn Error>> {
167 let get_spray_angle = get_callback!(self.ai_id, WeaponDef_getSprayAngle)?;
168 Ok(unsafe { get_spray_angle(self.ai_id, self.weapon_def_id) })
169 }
170
171 pub fn moving_accuracy(&self) -> Result<f32, Box<dyn Error>> {
172 let get_moving_accuracy = get_callback!(self.ai_id, WeaponDef_getMovingAccuracy)?;
173 Ok(unsafe { get_moving_accuracy(self.ai_id, self.weapon_def_id) })
174 }
175
176 pub fn target_move_error(&self) -> Result<f32, Box<dyn Error>> {
177 let get_target_move_error = get_callback!(self.ai_id, WeaponDef_getTargetMoveError)?;
178 Ok(unsafe { get_target_move_error(self.ai_id, self.weapon_def_id) })
179 }
180
181 pub fn lead_limit(&self) -> Result<f32, Box<dyn Error>> {
182 let get_lead_limit = get_callback!(self.ai_id, WeaponDef_getLeadLimit)?;
183 Ok(unsafe { get_lead_limit(self.ai_id, self.weapon_def_id) })
184 }
185
186 pub fn lead_bonus(&self) -> Result<f32, Box<dyn Error>> {
187 let get_lead_bonus = get_callback!(self.ai_id, WeaponDef_getLeadBonus)?;
188 Ok(unsafe { get_lead_bonus(self.ai_id, self.weapon_def_id) })
189 }
190
191 pub fn predict_boost(&self) -> Result<f32, Box<dyn Error>> {
192 let get_predict_boost = get_callback!(self.ai_id, WeaponDef_getPredictBoost)?;
193 Ok(unsafe { get_predict_boost(self.ai_id, self.weapon_def_id) })
194 }
195
196 pub fn paralyze_damage_time(&self) -> Result<i32, Box<dyn Error>> {
197 let get_paralyze_damage_time =
198 get_callback!(self.ai_id, WeaponDef_Damage_getParalyzeDamageTime)?;
199 Ok(unsafe { get_paralyze_damage_time(self.ai_id, self.weapon_def_id) })
200 }
201
202 pub fn impulse_factor(&self) -> Result<f32, Box<dyn Error>> {
203 let get_impulse_factor = get_callback!(self.ai_id, WeaponDef_Damage_getImpulseFactor)?;
204 Ok(unsafe { get_impulse_factor(self.ai_id, self.weapon_def_id) })
205 }
206
207 pub fn impulse_boost(&self) -> Result<f32, Box<dyn Error>> {
208 let get_impulse_boost = get_callback!(self.ai_id, WeaponDef_Damage_getImpulseBoost)?;
209 Ok(unsafe { get_impulse_boost(self.ai_id, self.weapon_def_id) })
210 }
211
212 pub fn crater_multiplier(&self) -> Result<f32, Box<dyn Error>> {
213 let get_crater_multiplier = get_callback!(self.ai_id, WeaponDef_Damage_getCraterMult)?;
214 Ok(unsafe { get_crater_multiplier(self.ai_id, self.weapon_def_id) })
215 }
216
217 pub fn crater_boost(&self) -> Result<f32, Box<dyn Error>> {
218 let get_crater_boost = get_callback!(self.ai_id, WeaponDef_Damage_getCraterBoost)?;
219 Ok(unsafe { get_crater_boost(self.ai_id, self.weapon_def_id) })
220 }
221
222 pub fn area_of_effect(&self) -> Result<f32, Box<dyn Error>> {
223 let get_area_of_effect = get_callback!(self.ai_id, WeaponDef_getAreaOfEffect)?;
224 Ok(unsafe { get_area_of_effect(self.ai_id, self.weapon_def_id) })
225 }
226
227 pub fn self_damage(&self) -> Result<bool, Box<dyn Error>> {
228 let get_no_self_damage = get_callback!(self.ai_id, WeaponDef_isNoSelfDamage)?;
229 Ok(!unsafe { get_no_self_damage(self.ai_id, self.weapon_def_id) })
230 }
231
232 pub fn fire_starter(&self) -> Result<f32, Box<dyn Error>> {
233 let get_fire_starter = get_callback!(self.ai_id, WeaponDef_getFireStarter)?;
234 Ok(unsafe { get_fire_starter(self.ai_id, self.weapon_def_id) })
235 }
236
237 pub fn edge_effectivness(&self) -> Result<f32, Box<dyn Error>> {
238 let get_edge_effectivness = get_callback!(self.ai_id, WeaponDef_getEdgeEffectiveness)?;
239 Ok(unsafe { get_edge_effectivness(self.ai_id, self.weapon_def_id) })
240 }
241
242 pub fn size(&self) -> Result<f32, Box<dyn Error>> {
243 let get_size = get_callback!(self.ai_id, WeaponDef_getSize)?;
244 Ok(unsafe { get_size(self.ai_id, self.weapon_def_id) })
245 }
246
247 pub fn size_growth(&self) -> Result<f32, Box<dyn Error>> {
248 let get_size_growth = get_callback!(self.ai_id, WeaponDef_getSizeGrowth)?;
249 Ok(unsafe { get_size_growth(self.ai_id, self.weapon_def_id) })
250 }
251
252 pub fn collision_size(&self) -> Result<f32, Box<dyn Error>> {
253 let get_collision_size = get_callback!(self.ai_id, WeaponDef_getCollisionSize)?;
254 Ok(unsafe { get_collision_size(self.ai_id, self.weapon_def_id) })
255 }
256
257 pub fn salvo_size(&self) -> Result<i32, Box<dyn Error>> {
258 let get_salvo_size = get_callback!(self.ai_id, WeaponDef_getSalvoSize)?;
259 Ok(unsafe { get_salvo_size(self.ai_id, self.weapon_def_id) })
260 }
261
262 pub fn salvo_delay(&self) -> Result<f32, Box<dyn Error>> {
263 let get_salvo_delay = get_callback!(self.ai_id, WeaponDef_getSalvoDelay)?;
264 Ok(unsafe { get_salvo_delay(self.ai_id, self.weapon_def_id) })
265 }
266
267 pub fn reload(&self) -> Result<f32, Box<dyn Error>> {
268 let get_reload = get_callback!(self.ai_id, WeaponDef_getReload)?;
269 Ok(unsafe { get_reload(self.ai_id, self.weapon_def_id) })
270 }
271
272 pub fn beam_time(&self) -> Result<f32, Box<dyn Error>> {
273 let get_beam_time = get_callback!(self.ai_id, WeaponDef_getBeamTime)?;
274 Ok(unsafe { get_beam_time(self.ai_id, self.weapon_def_id) })
275 }
276
277 pub fn beam_burst(&self) -> Result<bool, Box<dyn Error>> {
278 let get_beam_burst = get_callback!(self.ai_id, WeaponDef_isBeamBurst)?;
279 Ok(unsafe { get_beam_burst(self.ai_id, self.weapon_def_id) })
280 }
281
282 pub fn bounce(&self) -> WeaponBounce {
283 WeaponBounce {
284 ai_id: self.ai_id,
285 weapon_def_id: self.weapon_def_id,
286 }
287 }
288
289 pub fn max_angle(&self) -> Result<f32, Box<dyn Error>> {
290 let get_max_angle = get_callback!(self.ai_id, WeaponDef_getMaxAngle)?;
291 Ok(unsafe { get_max_angle(self.ai_id, self.weapon_def_id) })
292 }
293
294 pub fn up_time(&self) -> Result<f32, Box<dyn Error>> {
295 let get_up_time = get_callback!(self.ai_id, WeaponDef_getUpTime)?;
296 Ok(unsafe { get_up_time(self.ai_id, self.weapon_def_id) })
297 }
298
299 pub fn flight_time(&self) -> Result<i32, Box<dyn Error>> {
300 let get_flight_time = get_callback!(self.ai_id, WeaponDef_getFlightTime)?;
301 Ok(unsafe { get_flight_time(self.ai_id, self.weapon_def_id) })
302 }
303
304 pub fn cost(&self, resource: Resource) -> Result<f32, Box<dyn Error>> {
305 let get_cost_func = get_callback!(self.ai_id, WeaponDef_getCost)?;
306 Ok(unsafe { get_cost_func(self.ai_id, self.weapon_def_id, resource.resource_id) })
307 }
308
309 pub fn projectiles_per_shot(&self) -> Result<i32, Box<dyn Error>> {
310 let get_projectiles_per_shot_func =
311 get_callback!(self.ai_id, WeaponDef_getProjectilesPerShot)?;
312 Ok(unsafe { get_projectiles_per_shot_func(self.ai_id, self.weapon_def_id) })
313 }
314
315 pub fn turret(&self) -> Result<bool, Box<dyn Error>> {
316 let get_is_turret_func = get_callback!(self.ai_id, WeaponDef_isTurret)?;
317 Ok(unsafe { get_is_turret_func(self.ai_id, self.weapon_def_id) })
318 }
319
320 pub fn only_forward(&self) -> Result<bool, Box<dyn Error>> {
321 let get_only_forward_func = get_callback!(self.ai_id, WeaponDef_isOnlyForward)?;
322 Ok(unsafe { get_only_forward_func(self.ai_id, self.weapon_def_id) })
323 }
324
325 pub fn fixed_launcher(&self) -> Result<bool, Box<dyn Error>> {
326 let get_fixed_launcher_func = get_callback!(self.ai_id, WeaponDef_isFixedLauncher)?;
327 Ok(unsafe { get_fixed_launcher_func(self.ai_id, self.weapon_def_id) })
328 }
329
330 pub fn water_weapon(&self) -> Result<bool, Box<dyn Error>> {
331 let get_water_weapon_func = get_callback!(self.ai_id, WeaponDef_isWaterWeapon)?;
332 Ok(unsafe { get_water_weapon_func(self.ai_id, self.weapon_def_id) })
333 }
334
335 pub fn fire_submersed(&self) -> Result<bool, Box<dyn Error>> {
336 let get_fire_submersed_func = get_callback!(self.ai_id, WeaponDef_isFireSubmersed)?;
337 Ok(unsafe { get_fire_submersed_func(self.ai_id, self.weapon_def_id) })
338 }
339
340 pub fn sub_missile(&self) -> Result<bool, Box<dyn Error>> {
341 let get_sub_missile_func = get_callback!(self.ai_id, WeaponDef_isSubMissile)?;
342 Ok(unsafe { get_sub_missile_func(self.ai_id, self.weapon_def_id) })
343 }
344
345 pub fn tracks(&self) -> Result<bool, Box<dyn Error>> {
346 let get_tracks_func = get_callback!(self.ai_id, WeaponDef_isTracks)?;
347 Ok(unsafe { get_tracks_func(self.ai_id, self.weapon_def_id) })
348 }
349
350 pub fn dropped(&self) -> Result<bool, Box<dyn Error>> {
351 let get_dropped_func = get_callback!(self.ai_id, WeaponDef_isDropped)?;
352 Ok(unsafe { get_dropped_func(self.ai_id, self.weapon_def_id) })
353 }
354
355 pub fn paralyzer(&self) -> Result<bool, Box<dyn Error>> {
356 let get_paralyzer_func = get_callback!(self.ai_id, WeaponDef_isParalyzer)?;
357 Ok(unsafe { get_paralyzer_func(self.ai_id, self.weapon_def_id) })
358 }
359
360 pub fn impact_only(&self) -> Result<bool, Box<dyn Error>> {
361 let get_impact_only_func = get_callback!(self.ai_id, WeaponDef_isImpactOnly)?;
362 Ok(unsafe { get_impact_only_func(self.ai_id, self.weapon_def_id) })
363 }
364
365 pub fn auto_target(&self) -> Result<bool, Box<dyn Error>> {
366 let get_no_auto_target_func = get_callback!(self.ai_id, WeaponDef_isNoAutoTarget)?;
367 Ok(!unsafe { get_no_auto_target_func(self.ai_id, self.weapon_def_id) })
368 }
369
370 pub fn manual_fire(&self) -> Result<bool, Box<dyn Error>> {
371 let get_manual_fire_func = get_callback!(self.ai_id, WeaponDef_isManualFire)?;
372 Ok(unsafe { get_manual_fire_func(self.ai_id, self.weapon_def_id) })
373 }
374
375 pub fn interceptor(&self) -> Result<bool, Box<dyn Error>> {
376 let get_interceptor_func = get_callback!(self.ai_id, WeaponDef_getInterceptor)?;
377 let ret = unsafe { get_interceptor_func(self.ai_id, self.weapon_def_id) };
378 if ret == 1 {
379 Ok(true)
380 } else if ret == 0 {
381 Ok(false)
382 } else {
383 Err("Interceptor not 0 or 1".into())
384 }
385 }
386
387 pub fn targetable(&self) -> Result<bool, Box<dyn Error>> {
388 let get_targetable_func = get_callback!(self.ai_id, WeaponDef_getTargetable)?;
389 let ret = unsafe { get_targetable_func(self.ai_id, self.weapon_def_id) };
390 if ret == 1 {
391 Ok(true)
392 } else if ret == 0 {
393 Ok(false)
394 } else {
395 Err("Targetable not 0 or 1".into())
396 }
397 }
398
399 pub fn stockpileable(&self) -> Result<bool, Box<dyn Error>> {
400 let get_stockpileable_func = get_callback!(self.ai_id, WeaponDef_isStockpileable)?;
401 Ok(unsafe { get_stockpileable_func(self.ai_id, self.weapon_def_id) })
402 }
403
404 pub fn stockpile_time(&self) -> Result<f32, Box<dyn Error>> {
405 let get_stockpile_time_func = get_callback!(self.ai_id, WeaponDef_getStockpileTime)?;
406 Ok(unsafe { get_stockpile_time_func(self.ai_id, self.weapon_def_id) })
407 }
408
409 pub fn interceptor_coverage_range(&self) -> Result<f32, Box<dyn Error>> {
410 let get_coverage_range_func = get_callback!(self.ai_id, WeaponDef_getCoverageRange)?;
411 Ok(unsafe { get_coverage_range_func(self.ai_id, self.weapon_def_id) })
412 }
413
414 pub fn intensity(&self) -> Result<f32, Box<dyn Error>> {
415 let get_intensity_func = get_callback!(self.ai_id, WeaponDef_getIntensity)?;
416 Ok(unsafe { get_intensity_func(self.ai_id, self.weapon_def_id) })
417 }
418
419 pub fn duration(&self) -> Result<f32, Box<dyn Error>> {
420 let get_duration_func = get_callback!(self.ai_id, WeaponDef_getDuration)?;
421 Ok(unsafe { get_duration_func(self.ai_id, self.weapon_def_id) })
422 }
423
424 pub fn fall_off_rate(&self) -> Result<f32, Box<dyn Error>> {
425 let get_fall_off_rate_func = get_callback!(self.ai_id, WeaponDef_getFalloffRate)?;
426 Ok(unsafe { get_fall_off_rate_func(self.ai_id, self.weapon_def_id) })
427 }
428
429 pub fn sound_trigger(&self) -> Result<bool, Box<dyn Error>> {
430 let get_sound_trigger_func = get_callback!(self.ai_id, WeaponDef_isSoundTrigger)?;
431 Ok(unsafe { get_sound_trigger_func(self.ai_id, self.weapon_def_id) })
432 }
433
434 pub fn self_explode(&self) -> Result<bool, Box<dyn Error>> {
435 let get_self_explode_func = get_callback!(self.ai_id, WeaponDef_isSelfExplode)?;
436 Ok(unsafe { get_self_explode_func(self.ai_id, self.weapon_def_id) })
437 }
438
439 pub fn gravity_affected(&self) -> Result<bool, Box<dyn Error>> {
440 let get_gravity_affected_func = get_callback!(self.ai_id, WeaponDef_isGravityAffected)?;
441 Ok(unsafe { get_gravity_affected_func(self.ai_id, self.weapon_def_id) })
442 }
443
444 pub fn trajectory_height(&self) -> Result<f32, Box<dyn Error>> {
445 let get_trajectory_height_func = get_callback!(self.ai_id, WeaponDef_getTrajectoryHeight)?;
446 Ok(unsafe { get_trajectory_height_func(self.ai_id, self.weapon_def_id) })
447 }
448
449 pub fn trajectory(&self) -> Result<Trajectory, Box<dyn Error>> {
450 let get_high_trajectory_func = get_callback!(self.ai_id, WeaponDef_getHighTrajectory)?;
451 match unsafe { get_high_trajectory_func(self.ai_id, self.weapon_def_id) } {
452 0 => Ok(Trajectory::Low),
453 1 => Ok(Trajectory::High),
454 2 => Ok(Trajectory::Unit),
455 _ => Err("Trajectory not 0, 1, or 2".into()),
456 }
457 }
458
459 pub fn gravity(&self) -> Result<f32, Box<dyn Error>> {
460 let get_gravity_func = get_callback!(self.ai_id, WeaponDef_getMyGravity)?;
461 Ok(unsafe { get_gravity_func(self.ai_id, self.weapon_def_id) })
462 }
463
464 pub fn explode(&self) -> Result<bool, Box<dyn Error>> {
465 let get_no_explode_func = get_callback!(self.ai_id, WeaponDef_isNoExplode)?;
466 Ok(!unsafe { get_no_explode_func(self.ai_id, self.weapon_def_id) })
467 }
468
469 pub fn start_velocity(&self) -> Result<f32, Box<dyn Error>> {
470 let get_start_velocity_func = get_callback!(self.ai_id, WeaponDef_getStartVelocity)?;
471 Ok(unsafe { get_start_velocity_func(self.ai_id, self.weapon_def_id) })
472 }
473
474 pub fn max_velocity(&self) -> Result<f32, Box<dyn Error>> {
475 let get_max_velocity_func = get_callback!(self.ai_id, WeaponDef_getMaxVelocity)?;
476 Ok(unsafe { get_max_velocity_func(self.ai_id, self.weapon_def_id) })
477 }
478
479 pub fn weapon_acceleration(&self) -> Result<f32, Box<dyn Error>> {
480 let get_weapon_acceleration_func =
481 get_callback!(self.ai_id, WeaponDef_getWeaponAcceleration)?;
482 Ok(unsafe { get_weapon_acceleration_func(self.ai_id, self.weapon_def_id) })
483 }
484
485 pub fn turn_rate(&self) -> Result<f32, Box<dyn Error>> {
486 let get_turn_rate_func = get_callback!(self.ai_id, WeaponDef_getTurnRate)?;
487 Ok(unsafe { get_turn_rate_func(self.ai_id, self.weapon_def_id) })
488 }
489
490 pub fn projectile_speed(&self) -> Result<f32, Box<dyn Error>> {
491 let get_projectile_speed_func = get_callback!(self.ai_id, WeaponDef_getProjectileSpeed)?;
492 Ok(unsafe { get_projectile_speed_func(self.ai_id, self.weapon_def_id) })
493 }
494
495 pub fn explosion_speed(&self) -> Result<f32, Box<dyn Error>> {
496 let get_explosion_speed_func = get_callback!(self.ai_id, WeaponDef_getExplosionSpeed)?;
497 Ok(unsafe { get_explosion_speed_func(self.ai_id, self.weapon_def_id) })
498 }
499
500 pub fn wobble(&self) -> Result<f32, Box<dyn Error>> {
503 let get_wobble_func = get_callback!(self.ai_id, WeaponDef_getWobble)?;
504 Ok(unsafe { get_wobble_func(self.ai_id, self.weapon_def_id) })
505 }
506
507 pub fn dance(&self) -> Result<f32, Box<dyn Error>> {
508 let get_dance_func = get_callback!(self.ai_id, WeaponDef_getDance)?;
509 Ok(unsafe { get_dance_func(self.ai_id, self.weapon_def_id) })
510 }
511
512 pub fn large_beam_laser(&self) -> Result<bool, Box<dyn Error>> {
513 let get_large_beam_laser_func = get_callback!(self.ai_id, WeaponDef_isLargeBeamLaser)?;
514 Ok(unsafe { get_large_beam_laser_func(self.ai_id, self.weapon_def_id) })
515 }
516
517 pub fn shield(&self) -> Result<Option<WeaponShield>, Box<dyn Error>> {
518 let get_shield_func = get_callback!(self.ai_id, WeaponDef_isShield)?;
519 let has_shield = unsafe { get_shield_func(self.ai_id, self.weapon_def_id) };
520
521 Ok(if has_shield {
522 Some(WeaponShield {
523 ai_id: self.ai_id,
524 weapon_def_id: self.weapon_def_id,
525 })
526 } else {
527 None
528 })
529 }
530
531 pub fn avoid_friendly(&self) -> Result<bool, Box<dyn Error>> {
534 let get_avoid_friendly_func = get_callback!(self.ai_id, WeaponDef_isAvoidFriendly)?;
535 Ok(unsafe { get_avoid_friendly_func(self.ai_id, self.weapon_def_id) })
536 }
537
538 pub fn avoid_feature(&self) -> Result<bool, Box<dyn Error>> {
539 let get_avoid_feature_func = get_callback!(self.ai_id, WeaponDef_isAvoidFeature)?;
540 Ok(unsafe { get_avoid_feature_func(self.ai_id, self.weapon_def_id) })
541 }
542
543 pub fn avoid_neutral(&self) -> Result<bool, Box<dyn Error>> {
544 let get_avoid_neutral_func = get_callback!(self.ai_id, WeaponDef_isAvoidNeutral)?;
545 Ok(unsafe { get_avoid_neutral_func(self.ai_id, self.weapon_def_id) })
546 }
547
548 pub fn target_border(&self) -> Result<f32, Box<dyn Error>> {
549 let get_target_border_func = get_callback!(self.ai_id, WeaponDef_getTargetBorder)?;
550 Ok(unsafe { get_target_border_func(self.ai_id, self.weapon_def_id) })
551 }
552
553 pub fn cylinder_targetting(&self) -> Result<f32, Box<dyn Error>> {
554 let get_cylinder_targetting_func =
555 get_callback!(self.ai_id, WeaponDef_getCylinderTargetting)?;
556 Ok(unsafe { get_cylinder_targetting_func(self.ai_id, self.weapon_def_id) })
557 }
558
559 pub fn minimum_intensity(&self) -> Result<f32, Box<dyn Error>> {
560 let get_minimum_intensity_func = get_callback!(self.ai_id, WeaponDef_getMinIntensity)?;
561 Ok(unsafe { get_minimum_intensity_func(self.ai_id, self.weapon_def_id) })
562 }
563
564 pub fn height_boost_factor(&self) -> Result<f32, Box<dyn Error>> {
565 let get_height_boost_factor_func =
566 get_callback!(self.ai_id, WeaponDef_getHeightBoostFactor)?;
567 Ok(unsafe { get_height_boost_factor_func(self.ai_id, self.weapon_def_id) })
568 }
569
570 pub fn proximity_priority(&self) -> Result<f32, Box<dyn Error>> {
571 let get_proximity_priority_func =
572 get_callback!(self.ai_id, WeaponDef_getProximityPriority)?;
573 Ok(unsafe { get_proximity_priority_func(self.ai_id, self.weapon_def_id) })
574 }
575
576 pub fn sweep_fire(&self) -> Result<bool, Box<dyn Error>> {
579 let get_sweep_fire_func = get_callback!(self.ai_id, WeaponDef_isSweepFire)?;
580 Ok(unsafe { get_sweep_fire_func(self.ai_id, self.weapon_def_id) })
581 }
582
583 pub fn able_to_attack_ground(&self) -> Result<bool, Box<dyn Error>> {
584 let get_able_to_attack_ground_func =
585 get_callback!(self.ai_id, WeaponDef_isAbleToAttackGround)?;
586 Ok(unsafe { get_able_to_attack_ground_func(self.ai_id, self.weapon_def_id) })
587 }
588
589 pub fn dynamic_damage_exponent(&self) -> Result<f32, Box<dyn Error>> {
590 let get_dynamic_damage_exponent_func =
591 get_callback!(self.ai_id, WeaponDef_getDynDamageExp)?;
592 Ok(unsafe { get_dynamic_damage_exponent_func(self.ai_id, self.weapon_def_id) })
593 }
594
595 pub fn dynamic_damage_minimum(&self) -> Result<f32, Box<dyn Error>> {
596 let get_dynamic_damage_min_func = get_callback!(self.ai_id, WeaponDef_getDynDamageMin)?;
597 Ok(unsafe { get_dynamic_damage_min_func(self.ai_id, self.weapon_def_id) })
598 }
599
600 pub fn dynamic_damage_range(&self) -> Result<f32, Box<dyn Error>> {
601 let get_dynamic_damage_range_func = get_callback!(self.ai_id, WeaponDef_getDynDamageRange)?;
602 Ok(unsafe { get_dynamic_damage_range_func(self.ai_id, self.weapon_def_id) })
603 }
604
605 pub fn dynamic_damage_inverted(&self) -> Result<bool, Box<dyn Error>> {
606 let get_dynamic_damage_inverted_func =
607 get_callback!(self.ai_id, WeaponDef_isDynDamageInverted)?;
608 Ok(unsafe { get_dynamic_damage_inverted_func(self.ai_id, self.weapon_def_id) })
609 }
610
611 pub fn all(&self) -> Result<WeaponDefAll, Box<dyn Error>> {
614 Ok(WeaponDefAll {
615 name: self.name()?,
616 description: self.description()?,
617 range: self.range()?,
618 spray_angle: self.spray_angle()?,
619 moving_accuracy: self.moving_accuracy()?,
620 target_move_error: self.target_move_error()?,
621 lead_limit: self.lead_limit()?,
622 lead_bonus: self.lead_bonus()?,
623 predict_boost: self.predict_boost()?,
624 paralyze_damage_time: self.paralyze_damage_time()?,
625 impulse_factor: self.impulse_factor()?,
626 impulse_boost: self.impulse_boost()?,
627 crater_multiplier: self.crater_multiplier()?,
628 crater_boost: self.crater_boost()?,
629 area_of_effect: self.area_of_effect()?,
630 self_damage: self.self_damage()?,
631 fire_starter: self.fire_starter()?,
632 edge_effectivness: self.edge_effectivness()?,
633 size: self.size()?,
634 size_growth: self.size_growth()?,
635 collision_size: self.collision_size()?,
636 salvo_size: self.salvo_size()?,
637 salvo_delay: self.salvo_delay()?,
638 reload: self.reload()?,
639 beam_time: self.beam_time()?,
640 beam_burst: self.beam_burst()?,
641 bounce: self.bounce().all()?,
642 max_angle: self.max_angle()?,
643 up_time: self.up_time()?,
644 flight_time: self.flight_time()?,
645 cost: AIInterface::new(self.ai_id)
646 .resource_interface()
647 .get_resources()?
648 .into_iter()
649 .filter_map(|resource| {
650 if let Ok(res) = self.cost(resource) {
651 Some((resource, res))
652 } else {
653 None
654 }
655 })
656 .collect(),
657 projectiles_per_shot: self.projectiles_per_shot()?,
658 turret: self.turret()?,
659 only_forward: self.only_forward()?,
660 fixed_launcher: self.fixed_launcher()?,
661 water_weapon: self.water_weapon()?,
662 fire_submersed: self.fire_submersed()?,
663 sub_missile: self.sub_missile()?,
664 tracks: self.tracks()?,
665 dropped: self.dropped()?,
666 paralyzer: self.paralyzer()?,
667 impact_only: self.impact_only()?,
668 auto_target: self.auto_target()?,
669 manual_fire: self.manual_fire()?,
670 interceptor: self.interceptor()?,
671 targetable: self.targetable()?,
672 stockpileable: self.stockpileable()?,
673 stockpile_time: self.stockpile_time()?,
674 interceptor_coverage_range: self.interceptor_coverage_range()?,
675 fall_off_rate: self.fall_off_rate()?,
676 sound_trigger: self.sound_trigger()?,
677 self_explode: self.self_explode()?,
678 gravity_affected: self.gravity_affected()?,
679 trajectory: self.trajectory()?,
680 trajectory_height: self.trajectory_height()?,
681 gravity: self.gravity()?,
682 explode: self.explode()?,
683 start_velocity: self.start_velocity()?,
684 max_velocity: self.max_velocity()?,
685 weapon_acceleration: self.weapon_acceleration()?,
686 turn_rate: self.turn_rate()?,
687 projectile_speed: self.projectile_speed()?,
688 explosion_speed: self.explosion_speed()?,
689 wobble: self.wobble()?,
690 dance: self.dance()?,
691 large_beam_laser: self.large_beam_laser()?,
692 shield: match self.shield()? {
693 Some(s) => Some(s.all()?),
694 None => None,
695 },
696 avoid_friendly: self.avoid_friendly()?,
697 avoid_feature: self.avoid_feature()?,
698 avoid_neutral: self.avoid_neutral()?,
699 target_border: self.target_border()?,
700 cylinder_targetting: self.cylinder_targetting()?,
701 minimum_intensity: self.minimum_intensity()?,
702 height_boost_factor: self.height_boost_factor()?,
703 proximity_priority: self.proximity_priority()?,
704 sweep_fire: self.sweep_fire()?,
705 able_to_attack_ground: self.able_to_attack_ground()?,
706 dynamic_damage_exponent: self.dynamic_damage_exponent()?,
707 dynamic_damage_minimum: self.dynamic_damage_minimum()?,
708 dynamic_damage_range: self.dynamic_damage_range()?,
709 dynamic_damage_inverted: self.dynamic_damage_inverted()?,
710 })
711 }
712}