dcso3/
weapon.rs

1/*
2Copyright 2024 Eric Stokes.
3
4This file is part of dcso3.
5
6dcso3 is free software: you can redistribute it and/or modify it under
7the terms of the MIT License.
8
9dcso3 is distributed in the hope that it will be useful, but WITHOUT
10ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11FITNESS FOR A PARTICULAR PURPOSE.
12*/
13
14use super::{as_tbl, object::Object, unit::Unit};
15use crate::{cvt_err, object::{DcsObject, DcsOid}, simple_enum, wrapped_table, LuaEnv, MizLua};
16use anyhow::{bail, Result};
17use mlua::{prelude::*, Value};
18use serde::Deserialize;
19use serde_derive::Serialize;
20use std::{marker::PhantomData, ops::Deref};
21
22// the documentation is unfortunately not sufficient for this to be a
23// proper bitflags
24simple_enum!(WeaponFlag, u64, [
25    NoWeapon => 0,
26    LGB => 2,
27    TvGB => 4,
28    SNSGB => 8,
29    HEBomb => 16,
30    Penetrator => 32,
31    NapalmBomb => 64,
32    FAEBomb => 128,
33    ClusterBomb => 256,
34    Dispenser => 512,
35    CandleBomb => 1024,
36    ParachuteBomb => 2147483648,
37    GuidedBomb => 14,
38    AnyUnguidedBomb => 2147485680,
39    AnyBomb => 2147485694,
40    LightRocket => 2048,
41    MarkerRocket => 4096,
42    CandleRocket => 8192,
43    HeavyRocket => 16384,
44    AnyRocket => 30720,
45    AntiRadarMissile => 32768,
46    AntiShipMissile => 65536,
47    AntiTankMissile => 131072,
48    FireAndForgetASM => 262144,
49    LaserASM => 524288,
50    TeleASM => 1048576,
51    CruiseMissile => 2097152,
52    GuidedASM => 1572864,
53    TacticalASM => 1835008,
54    AnyASM => 4161536,
55    SRAAM => 4194304,
56    MRAAM => 8388608,
57    LRAAM => 16777216,
58    IRAAM => 33554432,
59    SARAAM => 67108864,
60    ARAAM => 134217728,
61    AnyAAM => 264241152,
62    AnyMissile => 268402688,
63    AnyAutonomousMissile => 36012032,
64    GunPod => 268435456,
65    BuiltInCannon => 536870912,
66    Cannons => 805306368,
67    AntiRadarMissile2 => 1073741824,
68    SmokeShell => 17179869184,
69    IlluminationShell => 34359738368,
70    MarkerShell => 51539607552,
71    SubmunitionDispenserShell => 68719476736,
72    GuidedShell => 137438953472,
73    ConventionalShell => 206963736576,
74    AnyShell => 258503344128,
75    Decoys => 8589934592,
76    Torpedo => 4294967296,
77    AnyAGWeapon => 2956984318,
78    AnyAAWeapon => 1069547520,
79    UnguidedWeapon => 2952822768,
80    GuidedWeapon => 268402702,
81    AnyWeapon => 3221225470,
82    MarkerWeapon => 13312,
83    ArmWeapon => 209379642366
84]);
85
86wrapped_table!(Weapon, Some("Weapon"));
87
88impl<'lua> Weapon<'lua> {
89    pub fn as_object(&self) -> Result<Object<'lua>> {
90        Ok(Object::from_lua(Value::Table(self.t.clone()), self.lua)?)
91    }
92
93    pub fn is_exist(&self) -> Result<bool> {
94        Ok(self.t.call_method("isExist", ())?)
95    }
96
97    pub fn get_name(&self) -> Result<String> {
98        Ok(self.t.call_method("getName", ())?)
99    }
100
101    pub fn get_type(&self) -> Result<String> {
102        Ok(self.t.call_method("getTypeName", ())?)
103    }
104
105    pub fn get_launcher(&self) -> Result<Unit<'lua>> {
106        Ok(self.t.call_method("getLauncher", ())?)
107    }
108
109    pub fn get_target(&self) -> Result<Option<Object<'lua>>> {
110        match self.t.call_method("getTarget", ())? {
111            Value::Nil => Ok(None),
112            v => Ok(Some(Object::from_lua(v, self.lua)?)),
113        }
114    }
115
116    pub fn get_desc(&self) -> Result<mlua::Table<'lua>> {
117        Ok(self.t.call_method("getDesc", ())?)
118    }
119}
120
121#[derive(Debug, Clone)]
122pub struct ClassWeapon;
123
124impl<'lua> DcsObject<'lua> for Weapon<'lua> {
125    type Class = ClassWeapon;
126
127    fn get_instance(lua: MizLua<'lua>, id: &DcsOid<Self::Class>) -> Result<Self> {
128        let t = lua.inner().create_table()?;
129        t.set_metatable(Some(lua.inner().globals().raw_get(&**id.class)?));
130        t.raw_set("id_", id.id)?;
131        let t = Weapon {
132            t,
133            lua: lua.inner(),
134        };
135        if !t.is_exist()? {
136            bail!("{} is an invalid weapon", id.id)
137        }
138        Ok(t)
139    }
140
141    fn get_instance_dyn<T>(lua: MizLua<'lua>, id: &DcsOid<T>) -> Result<Self> {
142        id.check_implements(lua, "Weapon")?;
143        let id = DcsOid {
144            id: id.id,
145            class: id.class.clone(),
146            t: PhantomData,
147        };
148        Self::get_instance(lua, &id)
149    }
150
151    fn change_instance(self, id: &DcsOid<Self::Class>) -> Result<Self> {
152        self.raw_set("id_", id.id)?;
153        if !self.is_exist()? {
154            bail!("{} is an invalid weapon", id.id)
155        }
156        Ok(self)
157    }
158
159    fn change_instance_dyn<T>(self, id: &DcsOid<T>) -> Result<Self> {
160        id.check_implements(MizLua(self.lua), "Weapon")?;
161        self.t.raw_set("id_", id.id)?;
162        if !self.is_exist()? {
163            bail!("{} is an invalid weapon", id.id)
164        }
165        Ok(self)
166    }
167}