mission_script_lua_event_derived.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. #include <array>
  2. #include <cstddef>
  3. #include <string_view>
  4. #include "mission_script_lua_event_internal.h"
  5. #include "mission_script_lua_internal.h"
  6. // The derived and internal event views. Every one carries mission_sequence. The Sense
  7. // edges also carry the slot identity; the phase, timer, world and session edges leave those fields
  8. // zero, so they must not expose them.
  9. namespace sunrise::server::activity::mission::lua_vm::detail {
  10. namespace {
  11. /** The type-60 target read out of one type-31 player-trigger incident. */
  12. [[nodiscard]] bool
  13. push_player_trigger_member(lua_State* state, const host::Event& event, std::string_view key) {
  14. if (key == "volume_registry_key") {
  15. lua_pushinteger(state, event.playerTriggerRegistryKey);
  16. } else if (key == "volume_slot_type") {
  17. lua_pushinteger(state, event.playerTriggerSlotType);
  18. } else if (key == "volume_slot_index") {
  19. lua_pushinteger(state, event.playerTriggerSlotIndex);
  20. } else if (key == "resolved_object_id") {
  21. lua_pushinteger(state, event.playerTriggerResolvedObjectId);
  22. } else {
  23. return false;
  24. }
  25. return true;
  26. }
  27. /** Runtime values carried beside the exact Type-6 source ClientRef. */
  28. [[nodiscard]] bool
  29. push_cinematic_member(lua_State* state, const host::Event& event, std::string_view key) {
  30. if (key == "runtime_object_id") {
  31. push_u64_string(state, event.cinematicRuntimeObjectId);
  32. } else if (key == "event_value") {
  33. lua_pushnumber(state, event.cinematicEventValue);
  34. } else {
  35. return false;
  36. }
  37. return true;
  38. }
  39. /** The three members every trigger volume occupancy edge carries. */
  40. [[nodiscard]] bool
  41. push_trigger_member(lua_State* state, const host::Event& event, std::string_view key) {
  42. if (key == "member_count") {
  43. lua_pushinteger(state, event.triggerCount);
  44. } else if (key == "value") {
  45. lua_pushinteger(state, event.triggerValue);
  46. } else if (key == "all_inside") {
  47. lua_pushboolean(state, event.triggerAll ? 1 : 0);
  48. } else {
  49. return false;
  50. }
  51. return true;
  52. }
  53. /** Squad totals plus the per-slot count list, pushed as a one-based Lua array. */
  54. [[nodiscard]] bool
  55. push_squad_state_member(lua_State* state, const host::Event& event, std::string_view key) {
  56. if (key == "alive_count") {
  57. lua_pushinteger(state, event.squadAliveCount);
  58. } else if (key == "objective_revision") {
  59. lua_pushinteger(state, event.squadObjectiveRevision);
  60. } else if (key == "task_costs") {
  61. lua_createtable(state, static_cast<int>(host::kSquadObjectiveGroupCount), 0);
  62. for (unsigned group = 0; group < host::kSquadObjectiveGroupCount; ++group) {
  63. if ((event.squadObjectiveCostMask & (1U << group)) == 0) {
  64. continue;
  65. }
  66. lua_pushnumber(state, event.squadObjectiveCosts[group]);
  67. lua_rawseti(state, -2, static_cast<lua_Integer>(group) + 1);
  68. }
  69. } else if (key == "previous_alive_count") {
  70. lua_pushinteger(state, event.squadPreviousAliveCount);
  71. } else if (key == "removal_flag") {
  72. lua_pushboolean(state, event.squadRemovalFlag ? 1 : 0);
  73. } else if (key == "slot_counts") {
  74. const std::size_t count = event.squadSlotCountLength;
  75. lua_createtable(state, static_cast<int>(count), 0);
  76. for (std::size_t index = 0; index < count; ++index) {
  77. lua_pushinteger(state, event.squadSlotCounts[index]);
  78. lua_rawseti(state, -2, static_cast<lua_Integer>(index + 1));
  79. }
  80. } else {
  81. return false;
  82. }
  83. return true;
  84. }
  85. /** The one squad slot that rose, and the count it held before. */
  86. [[nodiscard]] bool
  87. push_entity_spawned_member(lua_State* state, const host::Event& event, std::string_view key) {
  88. if (key == "member_slot") {
  89. lua_pushinteger(state, event.squadSlotOrdinal);
  90. } else if (key == "count") {
  91. lua_pushinteger(state, event.squadSlotValue);
  92. } else if (key == "previous_count") {
  93. lua_pushinteger(state, event.squadPreviousSlotValue);
  94. } else {
  95. return false;
  96. }
  97. return true;
  98. }
  99. /** The alive count after the death, and the count it replaced. */
  100. [[nodiscard]] bool
  101. push_entity_died_member(lua_State* state, const host::Event& event, std::string_view key) {
  102. if (key == "alive_count") {
  103. lua_pushinteger(state, event.squadAliveCount);
  104. } else if (key == "previous_alive_count") {
  105. lua_pushinteger(state, event.squadPreviousAliveCount);
  106. } else {
  107. return false;
  108. }
  109. return true;
  110. }
  111. /** The token the completed authored scene echoed back. */
  112. [[nodiscard]] bool
  113. push_scene_finished_member(lua_State* state, const host::Event& event, std::string_view key) {
  114. if (key != "activation_token") {
  115. return false;
  116. }
  117. lua_pushinteger(state, event.sceneActivationToken);
  118. return true;
  119. }
  120. /** The objective and task ordinals with the counter that rose. */
  121. [[nodiscard]] bool
  122. push_objective_progress_member(lua_State* state, const host::Event& event, std::string_view key) {
  123. if (key == "objective") {
  124. lua_pushinteger(state, event.objectiveOrdinal);
  125. } else if (key == "task") {
  126. lua_pushinteger(state, event.objectiveTaskOrdinal);
  127. } else if (key == "task_count") {
  128. lua_pushinteger(state, event.objectiveTaskCount);
  129. } else if (key == "previous_task_count") {
  130. lua_pushinteger(state, event.objectivePreviousTaskCount);
  131. } else {
  132. return false;
  133. }
  134. return true;
  135. }
  136. /** The committed mission phase and the phase it replaced. */
  137. [[nodiscard]] bool
  138. push_phase_member(lua_State* state, const host::Event& event, std::string_view key) {
  139. if (key == "phase") {
  140. lua_pushinteger(state, event.missionPhase);
  141. } else if (key == "previous_phase") {
  142. lua_pushinteger(state, event.previousMissionPhase);
  143. } else {
  144. return false;
  145. }
  146. return true;
  147. }
  148. /** Timer identity and its armed deadline. The name is a bounded buffer with its own length. */
  149. [[nodiscard]] bool
  150. push_timer_member(lua_State* state, const host::Event& event, std::string_view key) {
  151. if (key == "timer_name") {
  152. lua_pushlstring(state, event.timerName.bytes.data(), event.timerName.length);
  153. } else if (key == "timer_deadline_tick") {
  154. push_u64_string(state, event.timerDeadlineTick);
  155. } else if (key == "timer_sequence") {
  156. push_u64_string(state, event.timerSequence);
  157. } else {
  158. return false;
  159. }
  160. return true;
  161. }
  162. /** The peer identity both session edges carry. */
  163. [[nodiscard]] bool
  164. push_session_peer_member(lua_State* state, const host::Event& event, std::string_view key) {
  165. if (key == "session_id") {
  166. push_u64_string(state, event.peerSessionId);
  167. } else if (key == "session_generation") {
  168. push_u64_string(state, event.peerSessionGeneration);
  169. } else if (key == "member_key") {
  170. push_u64_string(state, event.peerMemberKey);
  171. } else {
  172. return false;
  173. }
  174. return true;
  175. }
  176. /** Mission state revision at the join. Only the join edge writes union 1's state arm. */
  177. [[nodiscard]] bool
  178. push_joined_revision_member(lua_State* state, const host::Event& event, std::string_view key) {
  179. if (key != "joined_revision") {
  180. return false;
  181. }
  182. push_u64_string(state, event.stateRevision);
  183. return true;
  184. }
  185. /** Reads one member of a trigger volume entry edge. */
  186. [[nodiscard]] int trigger_entered_index(lua_State* state) {
  187. const host::Event& event = check_event(state, 1);
  188. const std::string_view key = lua_string_view(state, 2);
  189. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  190. return 1;
  191. }
  192. if (event_surface_visible(state, event.kind)
  193. && (push_slot_identity_member(state, event, key)
  194. || push_trigger_member(state, event, key))) {
  195. return 1;
  196. }
  197. lua_pushnil(state);
  198. return 1;
  199. }
  200. /** Reads one member of a trigger volume exit edge. */
  201. [[nodiscard]] int trigger_exited_index(lua_State* state) {
  202. const host::Event& event = check_event(state, 1);
  203. const std::string_view key = lua_string_view(state, 2);
  204. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  205. return 1;
  206. }
  207. if (event_surface_visible(state, event.kind)
  208. && (push_slot_identity_member(state, event, key)
  209. || push_trigger_member(state, event, key))) {
  210. return 1;
  211. }
  212. lua_pushnil(state);
  213. return 1;
  214. }
  215. /** Reads one native player-trigger notification resolved to its authored type-31 source. */
  216. [[nodiscard]] int player_trigger_index(lua_State* state) {
  217. const host::Event& event = check_event(state, 1);
  218. const std::string_view key = lua_string_view(state, 2);
  219. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  220. return 1;
  221. }
  222. if (event_surface_visible(state, event.kind)
  223. && (push_slot_identity_member(state, event, key)
  224. || push_player_trigger_member(state, event, key))) {
  225. return 1;
  226. }
  227. lua_pushnil(state);
  228. return 1;
  229. }
  230. /** Reads one exact authored cinematic start edge. */
  231. [[nodiscard]] int cinematic_started_index(lua_State* state) {
  232. const host::Event& event = check_event(state, 1);
  233. const std::string_view key = lua_string_view(state, 2);
  234. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  235. return 1;
  236. }
  237. if (event_surface_visible(state, event.kind)
  238. && (push_slot_identity_member(state, event, key)
  239. || push_cinematic_member(state, event, key))) {
  240. return 1;
  241. }
  242. lua_pushnil(state);
  243. return 1;
  244. }
  245. /** Reads one exact authored cinematic terminal edge. */
  246. [[nodiscard]] int cinematic_terminated_index(lua_State* state) {
  247. return cinematic_started_index(state);
  248. }
  249. /** Reports the accepted member generation and native movement-path state. */
  250. [[nodiscard]] int actor_path_index(lua_State* state) {
  251. const auto& event = check_event(state, 1);
  252. const auto key = lua_string_view(state, 2);
  253. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  254. return 1;
  255. }
  256. if (event_surface_visible(state, event.kind)) {
  257. if (push_slot_identity_member(state, event, key)) {
  258. return 1;
  259. }
  260. if (key == "generation") {
  261. lua_pushinteger(state, event.actorGeneration);
  262. return 1;
  263. }
  264. if (key == "revision") {
  265. lua_pushinteger(state, event.actorPathRevision);
  266. return 1;
  267. }
  268. if (key == "path_state") {
  269. lua_pushinteger(state, event.actorPathState);
  270. return 1;
  271. }
  272. if (key == "delivery_revision" && event.actorDeliveryKnown) {
  273. lua_pushinteger(state, event.actorDeliveryRevision);
  274. return 1;
  275. }
  276. if (key == "delivery_state" && event.actorDeliveryKnown) {
  277. lua_pushinteger(state, event.actorDeliveryState);
  278. return 1;
  279. }
  280. if (key == "dead") {
  281. lua_pushboolean(state, event.actorDead);
  282. return 1;
  283. }
  284. }
  285. lua_pushnil(state);
  286. return 1;
  287. }
  288. /**
  289. * Exposes reported device values without giving unknown fields a numeric default.
  290. * @param state Lua call holding the device event and requested member name.
  291. * @return One reported value, flag or nil.
  292. */
  293. [[nodiscard]] int device_state_index(lua_State* state) {
  294. const auto& event = check_event(state, 1);
  295. const auto key = lua_string_view(state, 2);
  296. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)
  297. || push_slot_identity_member(state, event, key)) {
  298. return 1;
  299. }
  300. static constexpr std::array<std::string_view, 3> values{"position", "power", "lock"};
  301. static constexpr std::array<std::string_view, 3> sequences{
  302. "position_sequence", "power_sequence", "lock_sequence"};
  303. for (std::size_t channel = 0; channel < values.size(); ++channel) {
  304. if (key == values[channel]) {
  305. if ((event.deviceValueMask & (1U << channel)) != 0) {
  306. lua_pushnumber(state, event.deviceValues[channel]);
  307. } else {
  308. lua_pushnil(state);
  309. }
  310. return 1;
  311. }
  312. if (key == sequences[channel]) {
  313. if ((event.deviceSequenceMask & (1U << channel)) != 0) {
  314. lua_pushinteger(state, event.deviceSequences[channel]);
  315. } else {
  316. lua_pushnil(state);
  317. }
  318. return 1;
  319. }
  320. }
  321. if (key == "first_report") {
  322. lua_pushboolean(state, event.deviceFirstReport);
  323. } else if (key == "reset") {
  324. lua_pushboolean(state, event.deviceReset);
  325. } else {
  326. lua_pushnil(state);
  327. }
  328. return 1;
  329. }
  330. /** Lua index for one object interaction event: the common, slot and interaction members. */
  331. [[nodiscard]] int object_interaction_index(lua_State* state) {
  332. const host::Event& event = check_event(state, 1);
  333. const auto key = lua_string_view(state, 2);
  334. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)
  335. || (event_surface_visible(state, event.kind)
  336. && push_slot_identity_member(state, event, key))) {
  337. return 1;
  338. }
  339. if (event.kind == host::EventKind::damageState) {
  340. if (key == "health") {
  341. lua_pushnumber(state, event.damageHealth);
  342. } else if (key == "shield") {
  343. lua_pushnumber(state, event.damageShield);
  344. } else if (key == "revision") {
  345. lua_pushinteger(state, event.damageRevision);
  346. } else {
  347. lua_pushnil(state);
  348. }
  349. return 1;
  350. }
  351. if (key == "generation") {
  352. lua_pushinteger(state, event.objectGeneration);
  353. } else if (key == "present") {
  354. lua_pushboolean(state, event.objectPresent);
  355. } else if (key == "alive") {
  356. lua_pushboolean(state, event.objectAlive);
  357. } else if (key == "owner_known") {
  358. lua_pushboolean(state, event.objectOwnerKnown);
  359. } else if (key == "has_owner") {
  360. lua_pushboolean(state, event.objectHasOwner);
  361. } else if (key == "owner_key" && event.objectOwnerKey != 0) {
  362. push_u64_string(state, event.objectOwnerKey);
  363. } else {
  364. lua_pushnil(state);
  365. }
  366. return 1;
  367. }
  368. /** Reports native interaction progress without exposing raw Sense storage. */
  369. [[nodiscard]] int ghost_link_index(lua_State* state) {
  370. const host::Event& event = check_event(state, 1);
  371. const std::string_view key = lua_string_view(state, 2);
  372. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  373. return 1;
  374. }
  375. if (event_surface_visible(state, event.kind)) {
  376. if (push_slot_identity_member(state, event, key)) {
  377. return 1;
  378. }
  379. if (key == "generation") {
  380. lua_pushinteger(state, event.ghostGeneration);
  381. return 1;
  382. }
  383. if (key == "progress") {
  384. lua_pushnumber(state, event.ghostProgress);
  385. return 1;
  386. }
  387. if (key == "active") {
  388. lua_pushboolean(state, event.ghostActive);
  389. return 1;
  390. }
  391. }
  392. lua_pushnil(state);
  393. return 1;
  394. }
  395. /** Reads one member of a squad occupancy edge. */
  396. [[nodiscard]] int squad_state_index(lua_State* state) {
  397. const host::Event& event = check_event(state, 1);
  398. const std::string_view key = lua_string_view(state, 2);
  399. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  400. return 1;
  401. }
  402. if (event_surface_visible(state, event.kind)
  403. && (push_slot_identity_member(state, event, key)
  404. || push_squad_state_member(state, event, key))) {
  405. return 1;
  406. }
  407. lua_pushnil(state);
  408. return 1;
  409. }
  410. /** A gameplay provocation carries the exact squad reference, not a native Sense body. */
  411. [[nodiscard]] int squad_provoked_index(lua_State* state) {
  412. const auto& event = check_event(state, 1);
  413. const auto key = lua_string_view(state, 2);
  414. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  415. return 1;
  416. }
  417. if (key == "registry_key") {
  418. lua_pushinteger(state, event.firstRegistryKey);
  419. } else if (key == "slot_type") {
  420. lua_pushinteger(state, event.firstSlotType);
  421. } else if (key == "slot_index") {
  422. lua_pushinteger(state, event.firstSlotIndex);
  423. } else {
  424. lua_pushnil(state);
  425. }
  426. return 1;
  427. }
  428. /** Reads one member of a squad member spawn edge. */
  429. [[nodiscard]] int entity_spawned_index(lua_State* state) {
  430. const host::Event& event = check_event(state, 1);
  431. const std::string_view key = lua_string_view(state, 2);
  432. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  433. return 1;
  434. }
  435. if (event_surface_visible(state, event.kind)
  436. && (push_slot_identity_member(state, event, key)
  437. || push_entity_spawned_member(state, event, key))) {
  438. return 1;
  439. }
  440. lua_pushnil(state);
  441. return 1;
  442. }
  443. /** Reads one member of a squad member death edge. */
  444. [[nodiscard]] int entity_died_index(lua_State* state) {
  445. const host::Event& event = check_event(state, 1);
  446. const std::string_view key = lua_string_view(state, 2);
  447. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  448. return 1;
  449. }
  450. if (event_surface_visible(state, event.kind)
  451. && (push_slot_identity_member(state, event, key)
  452. || push_entity_died_member(state, event, key))) {
  453. return 1;
  454. }
  455. lua_pushnil(state);
  456. return 1;
  457. }
  458. /** Reads one member of an authored scene completion edge. */
  459. [[nodiscard]] int scene_finished_index(lua_State* state) {
  460. const host::Event& event = check_event(state, 1);
  461. const std::string_view key = lua_string_view(state, 2);
  462. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  463. return 1;
  464. }
  465. if (event_surface_visible(state, event.kind)
  466. && (push_slot_identity_member(state, event, key)
  467. || push_scene_finished_member(state, event, key))) {
  468. return 1;
  469. }
  470. lua_pushnil(state);
  471. return 1;
  472. }
  473. /** Reads one member of an objective task progress edge. */
  474. [[nodiscard]] int objective_progress_index(lua_State* state) {
  475. const host::Event& event = check_event(state, 1);
  476. const std::string_view key = lua_string_view(state, 2);
  477. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  478. return 1;
  479. }
  480. if (event_surface_visible(state, event.kind)
  481. && (push_slot_identity_member(state, event, key)
  482. || push_objective_progress_member(state, event, key))) {
  483. return 1;
  484. }
  485. lua_pushnil(state);
  486. return 1;
  487. }
  488. /** Reads one member of a mission phase commit edge. */
  489. [[nodiscard]] int phase_entered_index(lua_State* state) {
  490. const host::Event& event = check_event(state, 1);
  491. const std::string_view key = lua_string_view(state, 2);
  492. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  493. return 1;
  494. }
  495. if (event_surface_visible(state, event.kind)
  496. && (push_phase_member(state, event, key)
  497. || push_state_revision_member(state, event, key))) {
  498. return 1;
  499. }
  500. lua_pushnil(state);
  501. return 1;
  502. }
  503. /** Reads one member of a mission timer expiry edge. */
  504. [[nodiscard]] int timer_elapsed_index(lua_State* state) {
  505. const host::Event& event = check_event(state, 1);
  506. const std::string_view key = lua_string_view(state, 2);
  507. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  508. return 1;
  509. }
  510. if (event_surface_visible(state, event.kind) && push_timer_member(state, event, key)) {
  511. return 1;
  512. }
  513. lua_pushnil(state);
  514. return 1;
  515. }
  516. /** Reads the exact requested count from one committed msg-20 edge. */
  517. [[nodiscard]] int entity_slots_requested_index(lua_State* state) {
  518. const host::Event& event = check_event(state, 1);
  519. const std::string_view key = lua_string_view(state, 2);
  520. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  521. return 1;
  522. }
  523. if (event_surface_visible(state, event.kind) && key == "requested_count") {
  524. lua_pushinteger(state, event.requestedEntitySlots);
  525. return 1;
  526. }
  527. lua_pushnil(state);
  528. return 1;
  529. }
  530. /** Reads one member of a peer session join edge. */
  531. [[nodiscard]] int session_joined_index(lua_State* state) {
  532. const host::Event& event = check_event(state, 1);
  533. const std::string_view key = lua_string_view(state, 2);
  534. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  535. return 1;
  536. }
  537. if (event_surface_visible(state, event.kind)
  538. && (push_session_peer_member(state, event, key)
  539. || push_joined_revision_member(state, event, key))) {
  540. return 1;
  541. }
  542. lua_pushnil(state);
  543. return 1;
  544. }
  545. /** Reads one member of a peer session leave edge. */
  546. [[nodiscard]] int session_left_index(lua_State* state) {
  547. const host::Event& event = check_event(state, 1);
  548. const std::string_view key = lua_string_view(state, 2);
  549. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  550. return 1;
  551. }
  552. if (event_surface_visible(state, event.kind) && push_session_peer_member(state, event, key)) {
  553. return 1;
  554. }
  555. lua_pushnil(state);
  556. return 1;
  557. }
  558. /** Lua index for one fireteam state event: the alive, dead and unknown counts. */
  559. [[nodiscard]] int fireteam_state_index(lua_State* state) {
  560. const auto& event = check_event(state, 1);
  561. const auto key = lua_string_view(state, 2);
  562. if (push_common_member(state, event, key) || push_mission_sequence_member(state, event, key)) {
  563. return 1;
  564. }
  565. if (key == "alive_count") {
  566. lua_pushinteger(state, event.fireteamAlive);
  567. } else if (key == "dead_count") {
  568. lua_pushinteger(state, event.fireteamDead);
  569. } else if (key == "unknown_count") {
  570. lua_pushinteger(state, event.fireteamUnknown);
  571. } else {
  572. lua_pushnil(state);
  573. }
  574. return 1;
  575. }
  576. } // namespace
  577. /** Installs the derived and internal view metatables. */
  578. void register_derived_event_metatables(lua_State* state) {
  579. register_metatable(state, kFireteamStateEventMetatable, &fireteam_state_index);
  580. register_metatable(state, kTriggerEnteredEventMetatable, &trigger_entered_index);
  581. register_metatable(state, kTriggerExitedEventMetatable, &trigger_exited_index);
  582. register_metatable(state, kSquadStateEventMetatable, &squad_state_index);
  583. register_metatable(state, kSquadProvokedEventMetatable, &squad_provoked_index);
  584. register_metatable(state, kEntitySpawnedEventMetatable, &entity_spawned_index);
  585. register_metatable(state, kEntityDiedEventMetatable, &entity_died_index);
  586. register_metatable(state, kSceneFinishedEventMetatable, &scene_finished_index);
  587. register_metatable(state, kObjectiveProgressEventMetatable, &objective_progress_index);
  588. register_metatable(state, kPhaseEnteredEventMetatable, &phase_entered_index);
  589. register_metatable(state, kTimerElapsedEventMetatable, &timer_elapsed_index);
  590. register_metatable(state, kEntitySlotsRequestedEventMetatable, &entity_slots_requested_index);
  591. register_metatable(state, kSessionJoinedEventMetatable, &session_joined_index);
  592. register_metatable(state, kSessionLeftEventMetatable, &session_left_index);
  593. register_metatable(state, kPlayerTriggerEventMetatable, &player_trigger_index);
  594. register_metatable(state, kCinematicStartedEventMetatable, &cinematic_started_index);
  595. register_metatable(state, kCinematicTerminatedEventMetatable, &cinematic_terminated_index);
  596. register_metatable(state, kGhostLinkEventMetatable, &ghost_link_index);
  597. register_metatable(state, kObjectInteractionEventMetatable, &object_interaction_index);
  598. register_metatable(state, kDeviceStateEventMetatable, &device_state_index);
  599. register_metatable(state, kActorPathEventMetatable, &actor_path_index);
  600. }
  601. } // namespace sunrise::server::activity::mission::lua_vm::detail