spring_ai_rs/ai_interface/callback/weapon_def/
mod.rs

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    // TODO: getOnlyTargetCategory
501
502    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    // TODO: InterceptedByShieldType
532
533    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    // TODO: CollisionFlags
577
578    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    // TODO: CustomParams
612
613    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}