Advertisement
fig02

Player Cutscenes (csMode)

Apr 20th, 2021
136
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.23 KB | None | 0 0
  1. Anything detailed in this doc was figured out by myself and tharo going back and forth in a DM.
  2.  
  3. Link has a system for performing actions that are typically associated with cutscnes. Going forward it'll be important to distinguish between the different types of cutscenes.
  4.  
  5. When I refer to a "scripted cutscene", I am talking about a cutscene that is executed by running commands. For those in the speedrunning community, you are familiar with these as cutscenes that set the "cutscene pointer".
  6.  
  7. When I refer to a "player cutscene", I am talking about short actions/animations that link does. These are not scripted cutscenes, but they invoked by a scripted cutscene.
  8.  
  9. ---
  10.  
  11. There are two arrays that are going to be important here: `D_80854B18` and `D_80854E50`. The structure of the data in these arrays are as follows:
  12.  
  13. typedef struct {
  14. /* 0x00 */ s8 type;
  15. /* 0x04 */ union {
  16. void* ptr;
  17. void (*func)(GlobalContext*, Player*, CsCmdActorAction*);
  18. };
  19. } struct_80854B18; // size = 0x08
  20.  
  21. type needs a bit more research, and is not too important for what I'm talking about here.
  22. The second field can either be a function pointer, or some arbitrary data. If type is -1, it will treat whatever is there as a function.
  23. Otherwise it uses whatever data is provided. Passing an animation pointer is common.
  24.  
  25. There are two arrays because one is ran only one time, intended to "set up" the upcoming cutscene. The second is ran every frame as an "update".
  26. `D_80854B18` contains the setup list, and `D_80854E50` contains the update list.
  27.  
  28. ---
  29. How player cutscenes are invoked:
  30.  
  31. In z_actor.c there is a function: `func_8002DF54`
  32. This gets called many times throughout the codebase and takes a few args:
  33. global context, an actor pointer, and an index. NULL is valid for an actor pointer, as long as the cutscene being called does not expect an actor to work properly. Don't expect the cutscene actions to error check this for you.
  34.  
  35. From here on, the index into this function will be referred to as `csMode`.
  36.  
  37. After csMode is set by `func_8002DF54`, player is constantly checking if his current csMode is the same as the last csMode. This check is performed in `func_80852E14`.
  38. If the current csMode and previous csMode do not match, this means the action was changed. When this is true, the setup array mentioned earlier is used. `D_80854B18` gets indexed by the csMode number. If the data pointer is an animation, it will set links animation to that value. If its a function, it will run the function (which usually has a bit more involved setup).
  39.  
  40. Outside of the if block checking for the changed csMode, this function is also indexing the update array. This happens unconditionally every frame, unlike the setup info. Typically these update modes contain a function, which then calls skelanime_update and whatever else may be required every frame. The master sword cutscene for example uses an update function that does specific things on specific animation frames via code.
  41.  
  42. -
  43.  
  44. Now, for the elephant in the room. What do scripted cutscenes have to do with this system?
  45. Scripted cutscenes interface with player cutscenes a bit indirectly. A scripted cutscene provides a action number via its cutscene commands in the script. This action number is NOT the same as a csMode index.
  46.  
  47. The way this was implemented is kind of interesting. csMode 6 specifically is used internally by link for scripted cutscenes. If link sees a non-null actor action, he will invoke csMode 6 on his own. Index 6 in the setup array is null, so no setup is performed. Then it calls the update function which is `func_80852C50`.
  48. `func_80852C50` itself will handle scripted cutscene specific behavior, which includes calling the setup and update functions AGAIN, but with a new index provided by the cutscene command.
  49.  
  50. To reiterate the process of executing a scripted cutscene action:
  51. Link sees an actor action pointer -> csMode 6 is invoked, which runs the update function -> the update function runs the setup and update functions AGAIN, but with a new index provided by the script.
  52.  
  53. To make things more confusing, the index provided by the cutscene command does NOT correspond to the indices used for the setup and update arrays.
  54. Instead, it passes the action index provided by the script into an array `D_808547C4` which will then give you the proper index to be used for setup and update.
  55. The indices in this array can be positive or negative. More in depth research to understand this needs to be done. But positive indices seem to have extra logic that runs to see if the player has reached a specified point.
  56.  
  57. To give a practical example, lets step through how a scripted cutscene will make link walk:
  58. - A scripted cutscene is playing
  59. - A cutscene command in the script sets `globalCtx->csCtx.linkAction`
  60. - Link sees that this value is not null. Immediately calls `func_8002DF54` to set csMode to 6 (scripted cs mode)
  61. - csMode 6 has no init function, but has an update.
  62. - The update function indexes `D_808547C4` with the action number provided by the linkAction. For walking this index is 2. 3 is returned from the array
  63. - Index 3 recieved from the array is used to call the third setup and update func. Since 3 is a positive number, it will do the special handling related to making sure link is near the specified point from the cutscene command.
  64.  
  65. ---
  66.  
  67. What does this mean for me as the programmer?
  68. This system requires that you know the implementation details of each action to be able to use it properly. You need to know if the given csMode index will call any functions that require either an actor pointer or a cutscene command to be present.
  69. You can technically call any of these csModes outside of a scripted cutscnene, but if you use one that expects a scripted cutscene to be playing you will crash.
  70.  
  71. At minimum, only those indices listed in D_808547C4 will require a scripted cutscene to be playing. Some of them listed here will not, but any action numbers *not* present here are safe to use outside of a script.
  72.  
  73. For details on what each csMode index does, I've started a page that I am maintaining here: https://docs.google.com/spreadsheets/d/12RpxLB-AhiilGi6aG7MNKia2lhkAKivjly9V8GL-utg/edit?ts=607f77bf#gid=1431542613
  74.  
  75. Others in the community are doing interesting player docs on other pages.
  76.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement