ending.lua 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. -- Post-escape bookends are distinct native packed-region entries (1 and 2).
  2. -- Selection arms travel; offer playback only on the matching held-region receipt.
  3. -- Never confuse an offered command, a skip request, or a failed start with completion.
  4. return function(m)
  5. local movies = {
  6. {state = m.states.STATE_80B3C09E_0000_0001_80B3C091, slot = m.Slot.PF_CINEMATIC_BOOKEND_STM_CINEMATIC},
  7. {state = m.states.STATE_80B3C09E_0000_0002_80B3C093, slot = m.Slot.PF_CINEMATIC_BOOKEND_CNN_CINEMATIC},
  8. }
  9. local E = {}
  10. local music = require("mission_ember.music")(m)
  11. local function play(c, index)
  12. local row = assert(movies[index])
  13. c:set_variable("ember.ending", index)
  14. c:clear_variable("ember.ending.playing")
  15. c:clear_variable("ember.ending.runtime")
  16. c:clear_variable("ember.ending.stopping")
  17. c:select_state(assert(row.state))
  18. end
  19. function E.start(c, s)
  20. if s:variable("ember.ending") then return end
  21. music.update(c, s)
  22. play(c, 1)
  23. end
  24. function E.client(c, s, e)
  25. local index = s:variable("ember.ending")
  26. local row = index and movies[index]
  27. if not row or s:variable("ember.ending.offered") == index
  28. or e.held_region_index ~= row.state.region_index then return end
  29. c:set_variable("ember.ending.offered", index)
  30. c:slot(row.slot):set_cinematic_active{active = true}
  31. end
  32. local function matched(c, s, e)
  33. local index = s:variable("ember.ending")
  34. local row = index and movies[index]
  35. if not row then return end
  36. local slot = c:slot(row.slot)
  37. if e.registry_key ~= slot.registry_key or e.slot_type ~= slot.slot_type or e.slot_index ~= slot.slot_index then return end
  38. return index, slot
  39. end
  40. function E.started(c, s, e)
  41. local index = matched(c, s, e)
  42. if not index or s:variable("ember.ending.offered") ~= index or s:variable("ember.ending.playing") or type(e.runtime_object_id) ~= "string" then return end
  43. c:set_variable("ember.ending.playing", index)
  44. c:set_variable("ember.ending.runtime", e.runtime_object_id)
  45. end
  46. function E.skip(c, s, e)
  47. local index, slot = matched(c, s, e)
  48. if not index or s:variable("ember.ending.playing") ~= index
  49. or e.runtime_object_id ~= s:variable("ember.ending.runtime")
  50. or s:variable("ember.ending.stopping") then return end
  51. c:set_variable("ember.ending.stopping", true)
  52. slot:set_cinematic_active{active = false}
  53. end
  54. function E.terminated(c, s, e)
  55. local index, slot = matched(c, s, e)
  56. if not index or s:variable("ember.ending.playing") ~= index
  57. or e.runtime_object_id ~= s:variable("ember.ending.runtime") then return end
  58. slot:set_cinematic_active{active = false}
  59. if movies[index + 1] then play(c, index + 1)
  60. else
  61. c:set_variable("ember.ending", index + 1)
  62. c:set_variable("ember.complete", true)
  63. -- Native lifetime 6 enters the completion/reward branch (BEA9D0/B37100).
  64. c.lifetime:set{state = c.sdk.lifetime_states:at(6)}
  65. c:set_phase(100)
  66. end
  67. end
  68. return E
  69. end