ending.lua 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. -- Authored post-escape cinematic states; exact native completion/skip incidents advance once.
  2. --
  3. -- An authored region is `sliceSetIndex + stateOrdinal`, so apex gameplay (region 0) and both
  4. -- ending bookends (regions 1 and 2) are sibling states of one slice set. Selecting a bookend
  5. -- instantiates no new world, so no slice-set teleport is armed for it -- and that also means the
  6. -- client never sends another region report. Waiting for one leaves the movie unstarted forever,
  7. -- which is exactly what a run with the teleport removed showed: the state was selected and no
  8. -- cinematic was ever enqueued.
  9. --
  10. -- So the activation is queued with the selection instead of on a later callback. Intents are
  11. -- dispatched in order and a state selection completes only once its own roster revision has
  12. -- published, so the cinematic Auth always follows the seed that carries its slot. Slot handles
  13. -- resolve against the static SDK definition table, not the selected state, so naming the
  14. -- bookend before its state is live is safe.
  15. return function(m)
  16. local movies = {
  17. {state = m.states.STATE_80B3C09E_0000_0001_80B3C091, slot = m.Slot.PF_CINEMATIC_BOOKEND_STM_CINEMATIC},
  18. {state = m.states.STATE_80B3C09E_0000_0002_80B3C093, slot = m.Slot.PF_CINEMATIC_BOOKEND_CNN_CINEMATIC},
  19. }
  20. local E = {}
  21. local music = require("mission_ember.music")(m)
  22. local function play(c, index)
  23. local row = assert(movies[index])
  24. c:set_variable("ember.ending", index)
  25. c:set_variable("ember.ending.playing", index)
  26. c:select_state(assert(row.state))
  27. c:slot(assert(row.slot)):set_cinematic_active{active = true}
  28. end
  29. function E.start(c, s)
  30. if s:variable("ember.ending") then return end
  31. music.update(c, s)
  32. play(c, 1)
  33. end
  34. function E.terminated(c, s, e)
  35. local index = s:variable("ember.ending")
  36. local row = index and movies[index]
  37. if not row or s:variable("ember.ending.playing") ~= index then return end
  38. local slot = c:slot(row.slot)
  39. if e.registry_key ~= slot.registry_key or e.slot_type ~= slot.slot_type or e.slot_index ~= slot.slot_index then return end
  40. slot:set_cinematic_active{active = false}
  41. if movies[index + 1] then play(c, index + 1)
  42. else
  43. c:set_variable("ember.ending", index + 1)
  44. c:set_variable("ember.complete", true)
  45. -- Native lifetime 6 enters the completion/reward branch (BEA9D0/B37100).
  46. c.lifetime:set{state = c.sdk.lifetime_states:at(6)}
  47. c:set_phase(100)
  48. end
  49. end
  50. return E
  51. end