mission_ember_controller_test.lua 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package.path = "scripts/?.lua;" .. package.path
  2. local names = {
  3. "LANDING_MERCURY_ANCHOR_SQUAD",
  4. "LANDING_MERCURY_BONUS_ANCHOR_A_SQUAD", "LANDING_MERCURY_SUPPORT_A_SQUAD",
  5. "LANDING_MERCURY_SUPPORT_B_SQUAD", "LANDING_MERCURY_SUPPORT_C_SQUAD",
  6. "LANDING_MERCURY_RANGED_A_SQUAD", "LANDING_MERCURY_RANGED_B_SQUAD",
  7. "LANDING_MERCURY_BONUS_SUPPORT_A_SQUAD", "LANDING_MERCURY_BONUS_SUPPORT_B_SQUAD",
  8. "LANDING_MERCURY_BONUS_SUPPORT_C_SQUAD", "LANDING_MERCURY_BONUS_SUPPORT_D_SQUAD",
  9. }
  10. local mission = {
  11. Squad = {}, Slot = {M_DIRECTIVE_SENSOR_80B3C90A = "directive"},
  12. states = {
  13. STATE_80B3C09E_0008_0000_80B3C09C = {region_index = 64},
  14. STATE_80B3C09E_0006_0001_80B3C09A = {region_index = 49},
  15. },
  16. DialogueCue = {M_DIALOG_SENSOR_80B3C90A = {CUE_0 = 0, CUE_3 = 3}},
  17. Directive = {
  18. FIND_AND_DISABLE_THE_ALMIGHTY_S_WEAPONS_A70DA4A6 = "clear",
  19. FIND_AND_DISABLE_THE_ALMIGHTY_S_WEAPONS_2700C0C5 = "controls",
  20. },
  21. }
  22. for _, name in ipairs(names) do
  23. mission.Squad[name] = name
  24. mission.Slot[name] = name
  25. end
  26. local devices = {
  27. "POWERHOUSE_BRIDGE_ARM_MERCURY_DEVICE", "POWERHOUSE_BRIDGE_GEAR_MERCURY_BOTTOM_DEVICE",
  28. "POWERHOUSE_BRIDGE_GEAR_MERCURY_TOP_DEVICE", "POWERHOUSE_BRIDGE_ARM_SUN_DEVICE",
  29. "POWERHOUSE_BRIDGE_GEAR_SUN_BOTTOM_DEVICE", "POWERHOUSE_BRIDGE_GEAR_SUN_TOP_DEVICE",
  30. }
  31. for _, name in ipairs(devices) do mission.Slot[name] = name end
  32. mission.Slot.EMBER_POWERHOUSE_BRIDGE_OBJECTIVE = "bridge_objective"
  33. mission.Slot.PF_CINEMATIC_BOOKEND_CINEMATIC = "cinematic"
  34. mission.Slot.M_DIALOG_SENSOR_80B3C90A = "dialogue"
  35. package.preload.missions = function() return {MISSION_EMBER = "test_mission"} end
  36. package.preload.test_mission = function() return mission end
  37. local program = require("mission_ember")
  38. assert(program.initial_state == mission.states.STATE_80B3C09E_0006_0001_80B3C09A,
  39. "fresh launches must declare the authored cinematic state")
  40. local vars, directives, placements, seeds = {}, {}, 0, 0
  41. local state = {variable = function(_, key) return vars[key] end}
  42. local closed, resets, movies, cues = {}, 0, {}, {}
  43. local context = {sdk = {squad_modes = {replace = "replace"}, device_transitions = {close = "close"}}}
  44. function context:set_phase(value) vars.phase = value end
  45. function context:set_variable(key, value) vars[key] = value end
  46. function context:clear_variable(key) vars[key] = nil end
  47. function context:select_state(entry)
  48. assert(entry.region_index == 64)
  49. seeds = seeds + 1
  50. end
  51. function context:squad(name)
  52. assert(mission.Squad[name])
  53. return {default_counts = {1}, place = function() placements = placements + 1 end}
  54. end
  55. function context:slot(name)
  56. if name == "cinematic" then
  57. return {registry_key = 9, slot_type = 6, slot_index = 0,
  58. set_cinematic_active = function(_, args) movies[#movies + 1] = args.active end}
  59. end
  60. if name == "dialogue" then
  61. return {play_dialogue_cue = function(_, args) cues[#cues + 1] = args.cue end}
  62. end
  63. for _, device in ipairs(devices) do
  64. if name == device then
  65. return {transition = function(_, args)
  66. assert(args.transition == "close" and args.snap == true)
  67. closed[#closed + 1] = name
  68. end}
  69. end
  70. end
  71. if name == "bridge_objective" then
  72. return {reset_objectives = function() resets = resets + 1 end}
  73. end
  74. if name == "directive" then
  75. return {set_directive = function(_, args) directives[#directives + 1] = args.directive end}
  76. end
  77. for index, value in ipairs(names) do
  78. if name == value then return {registry_key = 7, slot_type = 1, slot_index = index} end
  79. end
  80. error("unknown slot " .. name)
  81. end
  82. local function region(index)
  83. program.on_event_client_state_changed(context, state, {current_region_index = index})
  84. end
  85. local function cleared()
  86. for index = 1, #names do
  87. program.on_event_squad_state(context, state, {
  88. registry_key = 7, slot_type = 1, slot_index = index,
  89. alive_count = 0, previous_alive_count = 1,
  90. })
  91. end
  92. end
  93. assert(#closed == 0 and resets == 0 and placements == 0)
  94. program.on_event_client_state_changed(context, state, {region_index = 49})
  95. assert(#movies == 0, "a requested region is not a held cinematic")
  96. region(49); region(49)
  97. assert(#movies == 1 and movies[1] == true and placements == 0)
  98. program.on_event_cinematic_terminated(context, state, {registry_key = 8, slot_type = 6, slot_index = 0})
  99. assert(seeds == 0, "unrelated movie termination cannot advance the mission")
  100. local termination = {registry_key = 9, slot_type = 6, slot_index = 0}
  101. program.on_event_cinematic_terminated(context, state, termination)
  102. program.on_event_cinematic_terminated(context, state, termination)
  103. assert(seeds == 1 and #movies == 2 and movies[2] == false)
  104. region(40)
  105. assert(placements == 0 and #closed == 0)
  106. region(64); region(64)
  107. assert(placements == #names and directives[1] == "clear")
  108. assert(#closed == 6 and resets == 1, "initialize devices only after playable region is held")
  109. program.on_event_client_state_changed(context, state, {teleport_state = 0})
  110. assert(#cues == 0)
  111. region(nil); region(nil)
  112. assert(#cues == 1 and cues[1] == 0, "arrival dialogue follows spawn settlement once")
  113. cleared(); cleared()
  114. assert(#directives == 2 and directives[2] == "controls")
  115. assert(#cues == 2 and cues[2] == 3, "settle deltas must preserve encounter ownership")
  116. package.loaded.mission_ember = nil
  117. program = require("mission_ember")
  118. region(64); cleared()
  119. assert(seeds == 1 and placements == #names and #directives == 2 and #cues == 2)
  120. assert(#closed == 6 and resets == 1, "transit and reload must not reset the bridge")
  121. print("cinematic handoff, held-region initialization, dialogue and reload checks passed")