Jump to content

How to log all functions being called by the game?


Recommended Posts

Hello, I'm facing an issue I've been trying to solve for the past few days and I'm hoping someone with more experience than me may be able to share some insight.

What I'm ultimately trying to do is find the correct console command to use to open photo mode, so that I can bind it to a hotkey on my mouse and have instant photo mode access, since I use photo mode quite a lot while playing the game. (insert meme here: "Wait, you guys actually play the game? I just mess around with the files")

There does exist a simple command - "showmenu photomodemenu" - which does open photo mode, and it works in most situations. Unfortunately, when piloting your ship, it still enters photo mode but the camera is bugged. The starting point is wrong, the starting orientation is wrong, and the movement controls (wasd) don't work at all, at a minimum. If you have taken any camera-related actions since game load, additional issues occur (inverted/diagonal camera look controls, extremely distant camera starting point, etc.) the next time that command is used while piloting your ship. I can get into the details of which actions cause which additional camera issues if it helps. Again, these issues only occur when running the aforementioned command while piloting your ship - the command still works fine if not piloting your ship, and the normal cameras (when not in photo mode) remain perfectly fine too. Going to the pause menu or the scanner and opening photo mode from there also continues to work perfectly fine. 

Since the photo mode button in the pause menu (ESC) works great in all situations, and my command works great in all situations I've tested except when piloting your ship, I'm thinking the photo mode button in the pause menu must be calling additional function(s) or command(s) to properly set the camera, in addition to "showmenu photomodemenu". It might only be calling the extra function(s) when piloting (checking some internal function like isPlayerPiloting), or it might be always doing the same thing and it just happens that these extra functions aren't needed in most cases.

What I'd really like to do is log all the functions the game is calling so I can find this out. Is this even possible?

I've already enabled Papyrus debugging in my ini and am able to get some known debug commands to work, and others not. I haven't been able to find anything that would accomplish what I want though.

I've been poring through the game files trying to find clues as to how to do this. I've extracted all the scripts from the ESM file (and decompiled with Champollion) and looked through them to no avail. I haven't been able to find relevant references to photo mode, or useful debug functions that I can get to work. I checked the animations and the interface files (decompiled with FFdec) too. I wasn't even sure if the process of opening photo mode would be a script or an animation or some actionscript embedded in the interface files, so I looked through all of them.

Does anyone with more experience than me have any tips on how to do what I want, or to at least get more relevant information from the various debug functions in the game?

Any help would be greatly appreciated.

 

Please note that I'm not interested in using an autohotkey script or keyboard macro to automate the inputs required to manually open the pause menu and open photo mode. I already tried it and the game requires too much delay between inputs for my liking.

Link to comment
Share on other sites

Technically you'd need to attach a debugger to the game's process. This would be a C++ project with advanced level of reverse engineering. You're probably right though, ShowMenu only tries to initialize a menu instance with hardcoded menu data but different scenarios like {CurrentFurnitureHasKeyword (PilotSeatKeyword) Run on: Player == True} needs to be handled elsewhere in the code. Certain menus cannot even be opened with it because the EXE crashes if the menu instance is not provided with mandatory data (ContainerMenu comes to my mind).

Have you tried exiting first person mode before ShowMenu PhotoModeMenu? This should move the PhotoMode's camera node outside of the ship where the third person camera currently is. Or you'd like to enter PhotoMode in the pilot seat?

Edited by LarannKiar
Link to comment
Share on other sites

Thank you for your reply.

1 hour ago, LarannKiar said:

Technically you'd need to attach a debugger to the game's process. This would be a C++ project with advanced level of reverse engineering.

Sounds like this is beyond my capabilities, and probably not worth learning for this particular case. I'm assuming this would require analyzing assembly code line-by-line.

1 hour ago, LarannKiar said:

Have you tried exiting first person mode before ShowMenu PhotoModeMenu?

Yes - I tested it with a fresh save that starts you in the pilot's seat in third person - undocked.

Then, to test, I did all of the following steps in order:

  • I freshly loaded the game (without mods)
  • Then loaded the save
  • Then gave the game a few seconds to breathe (for good measure)
  • Then entered my command
  • Nothing else

The result I saw was somehow even worse than entering it from first person (sitting in pilot's seat in both cases). That is, photo mode was entered, but the camera had all of the following problems:

  • Extremely distant initial camera location - I could see my ship but it was very small due to the distance
  • Incorrect initial camera pan - the camera was not pointed at the ship after initially running the command
  • Incorrect initial camera orientation - the camera was not oriented (rotationally) to match the ship's orientation
  • Very strange camera controls with mouse:
    • Mouse straight up -> pans camera up+left
    • Mouse straight down -> pans camera down+right
    • Mouse straight left -> rolls camera counter-clockwise
    • Mouse straight right -> rolls camera clockwise
  • No ability to move the camera with WASD

 

So it's very confusing as to what exactly is going on. Do you have any advice as to any additional debug commands or Papyrus functions (called with cgf) that could be useful here? Or, alternatively, any idea if any of the game's source files would reveal the actual actions the game takes when a user clicks on "Photo Mode" from the ESC menu?

Link to comment
Share on other sites

I somehow forgot about this post. Yes assembly is part of it too. It can be quite time consuming..

If PauseMenu >> PhotoMode works, you can try manipulating the menu to open PhotoMode for you. Currently SFSE has no Papyrus >> UI script so accessing/editing AS3 variables through Papyrus is not possible. Editing the menu itself might be the easiest option. To do so, you'll need to find the actual function that selects the entry 'PhotoMode' in PauseMenu, select ("highlight") it, then fake a button press or mouse click. I made a "Starfield Console Extender" (SFSE plugin) that has UI >> Invoke function. If you make and add a custom "OpenPhotoMode" to PauseMenu (in JPEXS for example), after opening it with the command "ShowMenu PauseMenu" you should be able to call OpenPhotoMode with Invoke. To call Invoke, you'd need to use Papyrus >> Debug.ExecuteConsole. You can also implement a "pause game time" function by calling the console command SetGlobalTimeMultiplier.

Another approach could be locating the Action that starts PhotoMode (if there's any) then invoking it with PlayIdleAction. Triggering certain "partially hardcoded" behavior with PlayIdleAction sometimes work but in many times it doesn't..

Edited by LarannKiar
Link to comment
Share on other sites

  • 1 month later...
On 2/26/2024 at 6:58 PM, LarannKiar said:

I somehow forgot about this post. Yes assembly is part of it too. It can be quite time consuming..

If PauseMenu >> PhotoMode works, you can try manipulating the menu to open PhotoMode for you. Currently SFSE has no Papyrus >> UI script so accessing/editing AS3 variables through Papyrus is not possible. Editing the menu itself might be the easiest option. To do so, you'll need to find the actual function that selects the entry 'PhotoMode' in PauseMenu, select ("highlight") it, then fake a button press or mouse click. I made a "Starfield Console Extender" (SFSE plugin) that has UI >> Invoke function. If you make and add a custom "OpenPhotoMode" to PauseMenu (in JPEXS for example), after opening it with the command "ShowMenu PauseMenu" you should be able to call OpenPhotoMode with Invoke. To call Invoke, you'd need to use Papyrus >> Debug.ExecuteConsole. You can also implement a "pause game time" function by calling the console command SetGlobalTimeMultiplier.

Another approach could be locating the Action that starts PhotoMode (if there's any) then invoking it with PlayIdleAction. Triggering certain "partially hardcoded" behavior with PlayIdleAction sometimes work but in many times it doesn't..

That's awesome. I tried something approaching that where's I'd intercept a console command if it starts with "$", then skipping the printing out of the command history and going directly to BGSCodeObject.Execute(). It's also theoretically possible to encode some commands that map to AS3 functions and objects, if not direct calls to objects in string form with dot notation, for instance:
"$ "AnimHolder_mc.AddHistory" 'adding some history''"
In the swf:
var FuncMap:Array  = new Array();

FuncMap['AddHistory'] = function (text:String)
{
       AnimHolder_mc.AddHistory(text);
}

etc, then splitting the incoming string into path segments.

Link to comment
Share on other sites

On 4/4/2024 at 12:49 AM, RaidersClamoring said:

That's awesome. I tried something approaching that where's I'd intercept a console command if it starts with "$", then skipping the printing out of the command history and going directly to BGSCodeObject.Execute(). It's also theoretically possible to encode some commands that map to AS3 functions and objects, if not direct calls to objects in string form with dot notation, for instance:
"$ "AnimHolder_mc.AddHistory" 'adding some history''"
In the swf:
var FuncMap:Array  = new Array();

FuncMap['AddHistory'] = function (text:String)
{
       AnimHolder_mc.AddHistory(text);
}

etc, then splitting the incoming string into path segments.

Unfortunately Invoke is underdeveloped, it can only call simple AS3 functions, parameters aren't implemented.

Actually, I originally made it for the ClearConsoleLog/ClearLog function that internally calls "root1.AnimHolder_mc.Menu_mc.ClearHistory" to clear the console log as the vanilla ClearConsole/Clear console command is no-op.

Edited by LarannKiar
Link to comment
Share on other sites

On 4/7/2024 at 3:30 PM, LarannKiar said:

Unfortunately Invoke is underdeveloped, it can only call simple AS3 functions, parameters aren't implemented.

Actually, I originally made it for the ClearConsoleLog/ClearLog function that internally calls "root1.AnimHolder_mc.Menu_mc.ClearHistory" to clear the console log as the vanilla ClearConsole/Clear console command is no-op.

So you made it work then. Are you putting code inside onKeyUp() or are you creating your own function inside Console.swf which you call using some SFSE endpoint? Or something else.

Link to comment
Share on other sites

3 hours ago, RaidersClamoring said:

So you made it work then. Are you putting code inside onKeyUp() or are you creating your own function inside Console.swf which you call using some SFSE endpoint? Or something else.

Vanilla Console.swf has "ClearHistory", I call it from the SFSE plugin.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...