1use super::{
15 as_tbl, as_tbl_ref, lua_err, object::Object, unit::Unit, weapon::Weapon, world::MarkPanel,
16 String, Time, value_to_json
17};
18use anyhow::{bail, Result};
19use log::{error, info};
20use mlua::{prelude::*, Value};
21use serde_derive::Serialize;
22
23#[derive(Debug, Clone, Serialize)]
24pub enum BirthPlace {
25 Air,
26 Runway,
27 Park,
28 HeliportHot,
29 HeliportCold,
30}
31
32#[derive(Debug, Clone, Serialize)]
33pub struct Shot<'lua> {
34 pub time: Time,
35 pub initiator: Unit<'lua>,
36 pub weapon: Weapon<'lua>,
37 pub weapon_name: String,
38}
39
40impl<'lua> FromLua<'lua> for Shot<'lua> {
41 fn from_lua(value: Value<'lua>, _: &'lua Lua) -> LuaResult<Self> {
42 let tbl = as_tbl("Shot", None, value).map_err(lua_err)?;
43 Ok(Self {
44 time: tbl.raw_get("time")?,
45 initiator: tbl.raw_get("initiator")?,
46 weapon: tbl.raw_get("weapon")?,
47 weapon_name: tbl.raw_get("weapon_name")?,
48 })
49 }
50}
51
52#[derive(Debug, Clone, Serialize)]
53pub struct ShootingEnd<'lua> {
54 pub time: Time,
55 pub initiator: Unit<'lua>,
56 pub weapon_name: String,
57}
58
59impl<'lua> FromLua<'lua> for ShootingEnd<'lua> {
60 fn from_lua(value: Value<'lua>, _: &'lua Lua) -> LuaResult<Self> {
61 let tbl = as_tbl("Shot", None, value).map_err(lua_err)?;
62 Ok(Self {
63 time: tbl.raw_get("time")?,
64 initiator: tbl.raw_get("initiator")?,
65 weapon_name: tbl.raw_get("weapon_name")?,
66 })
67 }
68}
69
70#[derive(Debug, Clone, Serialize)]
71pub struct WeaponUse<'lua> {
72 pub time: Time,
73 pub initiator: Option<Object<'lua>>,
74 pub target: Option<Object<'lua>>,
75 pub weapon_name: String,
76}
77
78impl<'lua> FromLua<'lua> for WeaponUse<'lua> {
79 fn from_lua(value: Value<'lua>, _: &'lua Lua) -> LuaResult<Self> {
80 let tbl = as_tbl("WeaponUse", None, value).map_err(lua_err)?;
81 Ok(Self {
82 time: tbl.raw_get("time")?,
83 initiator: tbl.raw_get("initiator")?,
84 target: tbl.raw_get("target")?,
85 weapon_name: tbl.raw_get("weapon_name")?,
86 })
87 }
88}
89
90#[derive(Debug, Clone, Serialize)]
91pub struct UnitEvent<'lua> {
92 pub time: Time,
93 pub initiator: Option<Object<'lua>>,
94}
95
96impl<'lua> FromLua<'lua> for UnitEvent<'lua> {
97 fn from_lua(value: Value<'lua>, _: &'lua Lua) -> LuaResult<Self> {
98 let tbl = as_tbl("UnitEvent", None, value).map_err(lua_err)?;
99 Ok(Self {
100 time: tbl.raw_get("time")?,
101 initiator: tbl.raw_get("initiator")?,
102 })
103 }
104}
105
106#[derive(Debug, Clone, Serialize)]
107pub struct EjectionEvent<'lua> {
108 pub time: Time,
109 pub initiator: Object<'lua>,
110 pub target: Object<'lua>,
111}
112
113impl<'lua> FromLua<'lua> for EjectionEvent<'lua> {
114 fn from_lua(value: Value<'lua>, _: &'lua Lua) -> LuaResult<Self> {
115 let tbl = as_tbl("EjectionEvent", None, value).map_err(lua_err)?;
116 Ok(Self {
117 time: tbl.raw_get("time")?,
118 initiator: tbl.raw_get("initiator")?,
119 target: tbl.raw_get("target")?,
120 })
121 }
122}
123
124#[derive(Debug, Clone, Serialize)]
125pub struct Birth<'lua> {
126 pub time: Time,
127 pub initiator: Object<'lua>,
128 pub place: Option<Object<'lua>>,
129 pub subplace: Option<i64>,
130}
131
132impl<'lua> FromLua<'lua> for Birth<'lua> {
133 fn from_lua(value: Value<'lua>, _: &'lua Lua) -> LuaResult<Self> {
134 let tbl = as_tbl("AtPlace", None, value).map_err(lua_err)?;
135 Ok(Self {
136 time: tbl.raw_get("time")?,
137 initiator: tbl.raw_get("initiator")?,
138 place: tbl.raw_get("place")?,
139 subplace: tbl.raw_get("subPlace")?,
140 })
141 }
142}
143
144#[derive(Debug, Clone, Serialize)]
145pub struct AtPlace<'lua> {
146 pub time: Time,
147 pub initiator: Object<'lua>,
148 pub place: Option<Object<'lua>>,
149 pub subplace: Option<i64>,
150}
151
152impl<'lua> FromLua<'lua> for AtPlace<'lua> {
153 fn from_lua(value: Value<'lua>, _: &'lua Lua) -> LuaResult<Self> {
154 let tbl = as_tbl("AtPlace", None, value).map_err(lua_err)?;
155 Ok(Self {
156 time: tbl.raw_get("time")?,
157 initiator: tbl.raw_get("initiator")?,
158 place: tbl.raw_get("place")?,
159 subplace: tbl.raw_get("subPlace")?,
160 })
161 }
162}
163
164#[derive(Debug, Clone, Serialize)]
165pub struct WeaponAdd<'lua> {
166 pub time: Time,
167 pub initiator: Object<'lua>,
168 pub weapon_name: String,
169}
170
171impl<'lua> FromLua<'lua> for WeaponAdd<'lua> {
172 fn from_lua(value: Value<'lua>, _lua: &'lua Lua) -> LuaResult<Self> {
173 let tbl = as_tbl("WeaponAdd", None, value).map_err(lua_err)?;
174 Ok(Self {
175 time: tbl.raw_get("time")?,
176 initiator: tbl.raw_get("initiator")?,
177 weapon_name: tbl.raw_get("weapon_name")?,
178 })
179 }
180}
181
182#[derive(Debug, Clone, Serialize)]
184pub enum Event<'lua> {
185 Invalid,
186 Shot(Shot<'lua>),
187 Hit(WeaponUse<'lua>),
188 Takeoff(AtPlace<'lua>),
189 Land(AtPlace<'lua>),
190 Crash(UnitEvent<'lua>),
191 Ejection(EjectionEvent<'lua>),
192 Refueling,
193 Dead(UnitEvent<'lua>),
194 PilotDead(UnitEvent<'lua>),
195 BaseCaptured,
196 MissionStart,
197 MissionEnd,
198 TookControl,
199 RefuelingStop,
200 Birth(Birth<'lua>),
201 HumanFailure,
202 DetailedFailure,
203 EngineStartup(AtPlace<'lua>),
204 EngineShutdown(AtPlace<'lua>),
205 PlayerEnterUnit(UnitEvent<'lua>),
206 PlayerLeaveUnit(UnitEvent<'lua>),
207 PlayerComment,
208 ShootingStart(WeaponUse<'lua>),
209 ShootingEnd(ShootingEnd<'lua>),
210 MarkAdded(MarkPanel<'lua>),
211 MarkChange(MarkPanel<'lua>),
212 MarkRemoved(MarkPanel<'lua>),
213 Kill(WeaponUse<'lua>),
214 Score(UnitEvent<'lua>),
215 UnitLost(UnitEvent<'lua>),
216 LandingAfterEjection,
217 ParatrooperLanding,
218 DiscardChairAfterEjection,
219 WeaponAdd(WeaponAdd<'lua>),
220 TriggerZone,
221 LandingQualityMark,
222 Bda,
223 AiAbortMission(UnitEvent<'lua>),
224 DayNight,
225 FlightTime,
226 PlayerSelfKillPilot,
227 PlayerCaptureAirfield,
228 EmergencyLanding,
229 UnitCreateTask,
230 UnitDeleteTask,
231 SimulationStart,
232 WeaponRearm,
233 WeaponDrop,
234 UnitTaskTimeout,
235 UnitTaskStage,
236 MacSubtaskScore,
237 MacExtraScore,
238 MissionRestart,
239 MissionWinner,
240 PostponedTakeoff(AtPlace<'lua>),
241 PostponedLand(AtPlace<'lua>),
242 Max,
243}
244
245fn translate<'a, 'lua: 'a>(lua: &'lua Lua, id: i64, value: Value<'lua>) -> Result<Event<'lua>> {
246 Ok(match id {
247 0 => Event::Invalid,
248 1 => Event::Shot(Shot::from_lua(value, lua)?),
249 2 => Event::Hit(WeaponUse::from_lua(value, lua)?),
250 3 => Event::Takeoff(AtPlace::from_lua(value, lua)?),
251 4 => Event::Land(AtPlace::from_lua(value, lua)?),
252 5 => Event::Crash(UnitEvent::from_lua(value, lua)?),
253 6 => Event::Ejection(EjectionEvent::from_lua(value, lua)?),
254 7 => Event::Refueling,
255 8 => Event::Dead(UnitEvent::from_lua(value, lua)?),
256 9 => Event::PilotDead(UnitEvent::from_lua(value, lua)?),
257 10 => Event::BaseCaptured,
258 11 => Event::MissionStart,
259 12 => Event::MissionEnd,
260 13 => Event::TookControl,
261 14 => Event::RefuelingStop,
262 15 => Event::Birth(Birth::from_lua(value, lua)?),
263 16 => Event::HumanFailure,
264 17 => Event::DetailedFailure,
265 18 => Event::EngineStartup(AtPlace::from_lua(value, lua)?),
266 19 => Event::EngineShutdown(AtPlace::from_lua(value, lua)?),
267 20 => Event::PlayerEnterUnit(UnitEvent::from_lua(value, lua)?),
268 21 => Event::PlayerLeaveUnit(UnitEvent::from_lua(value, lua)?),
269 22 => Event::PlayerComment,
270 23 => Event::ShootingStart(WeaponUse::from_lua(value, lua)?),
271 24 => Event::ShootingEnd(ShootingEnd::from_lua(value, lua)?),
272 25 => Event::MarkAdded(MarkPanel::from_lua(value, lua)?),
273 26 => Event::MarkChange(MarkPanel::from_lua(value, lua)?),
274 27 => Event::MarkRemoved(MarkPanel::from_lua(value, lua)?),
275 28 => Event::Kill(WeaponUse::from_lua(value, lua)?),
276 29 => Event::Score(UnitEvent::from_lua(value, lua)?),
277 30 => Event::UnitLost(UnitEvent::from_lua(value, lua)?),
278 31 => Event::LandingAfterEjection,
279 32 => Event::ParatrooperLanding,
280 33 => Event::DiscardChairAfterEjection,
281 34 => Event::WeaponAdd(WeaponAdd::from_lua(value, lua)?),
282 35 => Event::TriggerZone,
283 36 => Event::LandingQualityMark,
284 37 => Event::Bda,
285 38 => Event::AiAbortMission(UnitEvent::from_lua(value, lua)?),
286 39 => Event::DayNight,
287 40 => Event::FlightTime,
288 41 => Event::PlayerSelfKillPilot,
289 42 => Event::PlayerCaptureAirfield,
290 43 => Event::EmergencyLanding,
291 44 => Event::UnitCreateTask,
292 45 => Event::UnitDeleteTask,
293 46 => Event::SimulationStart,
294 47 => Event::WeaponRearm,
295 48 => Event::WeaponDrop,
296 49 => Event::UnitTaskTimeout,
297 50 => Event::UnitTaskStage,
298 51 => Event::MacSubtaskScore,
299 52 => Event::MacExtraScore,
300 53 => Event::MissionRestart,
301 54 => {
302 info!("mission winner event {}", value_to_json(&value));
303 Event::MissionWinner
304 },
305 55 => Event::PostponedTakeoff(AtPlace::from_lua(value, lua)?),
306 56 => Event::PostponedLand(AtPlace::from_lua(value, lua)?),
307 57 => Event::Max,
308 n => bail!("unknown event {n}"),
309 })
310}
311
312impl<'lua> FromLua<'lua> for Event<'lua> {
313 fn from_lua(value: Value<'lua>, lua: &'lua Lua) -> LuaResult<Self> {
314 let id = as_tbl_ref("Event", &value)
315 .map_err(lua_err)?
316 .raw_get("id")?;
317 match translate(lua, id, value.clone()) {
318 Ok(ev) => Ok(ev),
319 Err(e) => {
320 let s = value_to_json(&value);
321 error!("error translating event {id}: {e:?}, value: {s}");
322 Err(lua_err(e))
323 }
324 }
325 }
326}