Jump to content

Recommended Posts

Posted

I really can't express how much I'm looking forward to this working. I haven't had time to really dig into it myself, at first glance it looked like it would work ok if some lines were uncommented and/or moved out of that IFDEF block, but again, never took the time to test it out.

 

Having notifications of save/load/newgame would help me do so many things in sexout (via the extender) that are impossible now that I can't even list them all. I thought of watching the savefiles and stuff myself for new ones being created or existing ones being modified/deleted, but that doesn't work for new games so.. no joy.

 

I also thought of just calling the internal functions (the same ones NVSE exposes for getgamerestarted/getgameloaded) which in theory would work fine, but I'd still have to modify that code in NVSE in order for it to check the plugin handle in addition to the list of scripts it's already notified.

Posted

There's another way I can probably accomplish this but my brain isn't working at full speed right now so I'm missing a part. Maybe some of you interested parties can help me think it through and come up with a solution.

 

In sexout (or any mod) you can call the NVSE GetGameLoaded and GetGameRestarted functions. If I put if() blocks around those and make them independent then I can call an extender function in each case, something like NX_GameLoaded and NX_GameStarted.

 

NX_GameStarted is easy, it just zeros out all the internal state stuff and starts fresh, leaving just save and load detection.

 

Save detection is also fairly easy; I should be able to determine when a save is made, and which one, by watching the savegames directory for changes in the form of either new files, or the last modified time of an existing file. After I init, I can watch for changes here and save whenever I detect them. Of course the NX save would lag slightly behind the game save, but likely only by a few milliseconds so it shouldn't generally matter.

 

The problem becomes detecting which game was loaded when NX_GameLoaded is called. The few ideas I've had I either haven't had time to investigate (maybe it's in an NVSE structure that NX has access too, that I haven't found?), or seem like they wouldn't work right from the start.

 

File access time crossed my mind but won't work for about a million reasons.

 

Nothing else that will actually work is coming to mind..

Posted

I got the notification working. Just had to add the equivalent of OBSEMessagingInterface to nvse and add the register and dispatch message calls to PluginManager. So far it seems to work fine, at least for the load game event. In theory, event notification between plugins should work, but I have not had time to create multiple plugins and all that. It is just a mirror of the OBSE code, without the serialization stuff.

 

I'll put the modified nvse in github later tonight, just have to clean up the VS project files. Then you can build it and test it with the extender, since I won't have much time to play FNV the rest of the week.

Posted

it is https://github.com/ashmedai/NVSE . There are three projects in the repo, the two NVSE ones (common and nvse) and an example plugin (NVSEExtender really).

 

Event registry should work pretty much as in Oblivion. Details about the changes are in the spoiler below.

 

 

 

NVSE changed files:

- PluginAPI.h: added the NVSEMessagingInterface. This allows a plugin to register a listener for events

- PluginManager.cpp: added plugin listener register and message dispatch

- PluginManager.h: declarations for the new methods in PluginManager

- Hooks_SaveLoad.cpp: call PluginManager::Dispatch_Message when DoLoadGameHook is executed

 

NVSE Example:

This is the NVSE extender with code added to register for event notification.

- nvse_extender.cpp: after registering the commands, query NVSE for the messaging interface, and register the plugin as a listener:

   NVSEMessagingInterface* msgIntfc = (NVSEMessagingInterface*)nvse->QueryInterface(kInterface_Messaging);
   msgIntfc->RegisterListener(g_pluginHandle, "NVSE", MessageHandler);

 

where MessageHandler simply logs the name of the file:

  void MessageHandler(NVSEMessagingInterface::Message* msg)
  {
switch (msg->type)
{
case NVSEMessagingInterface::kMessage_LoadGame:
	_MESSAGE("Plugin Example received load message with file path %s", msg->data);
	break;
case NVSEMessagingInterface::kMessage_SaveGame:
	_MESSAGE("Plugin Example received save message with file path %s", msg->data);
	break;
default:
	_MESSAGE("Plugin Example received unknown message");
	break;
}
  }

 

 

 

Hopefully I didn't mangle the VS project files while cleaning them up. Only file load is sending a message, but adding save should be simple. I'll be able to work on this further later this week.

Posted

Thanks! I'll give it a whirl and let you know!

 

As it turns out, this is an instance where FOSE has more functionality than NVSE. All the plugin callback stuff is in FOSE. BTW, I created a FOSE version of the NVSE extender.

Posted

hah sweet! Feel free to make your own project wherever, or if you like, branch the NX project on sourceforge for it.

 

Might be an opportunity to do something that the silverlock guys haven't (but should) do -- ifdef the including/linking so that one codebase can be used to build both the NVSE and FOSE versions. All the handbuilt functions should work more or less correctly I'd think, what needs changed between releases are..

 

-- what is included linked, obviously.

-- opcode range

-- function macro names, if different.

 

Might be more work than it's worth though, not really sure.

Posted

Version 7 now available in OP

 

(ref.)NX_GetConversationPartner

Available since: V7 Thanks a ton, jaam!

- Returns the current conversation partner if in a conversation AND the NPC initiated the conversation via StartConversation topic. Only makes sense when called on the player.

someref.startconversation sometopic
; wait a bit, and be in a menumode block
ref = player.NX_GetConversationPartner
; ref now == someref

 

SexoutNG (the current beta, any version .67+) uses this internally for dialog callbacks. If you want to use it yourself, the best way I've found so far is with a block like this in a quest script:

 

ref dlgSelf
Begin MenuMode
 ; dialog callback support
 if (MenuMode 1009)
   set dlgSelf to player.NX_GetConversationPartner
   player.NX_SetEVFo "Sexout:CHANGE:THIS:TO:SUIT" dlgSelf
 endif
End

 

This will continually set the NX variable of your choosing to the reference of the NPC the player is conversing with, so long as the conversation was started by the NPC (looking into a work around for this). Then, in your other script(s), you can look at that NX var to use it as you see fit.

 

You can also just use a quest var of course, if there's only ever one reference (or a few and you don't mind making them static) you care about.

 

Other options are possible such as comparing tmpSelf to the ref of your choosing and then setting a flag, etc.

 

You cannot effectively use this in any other script type, since blocks like GameMode, ScriptEffectUpdate, OnAdd, etc., only run in game mode -- and a conversation is a menu mode.

 

If there is enough demand I may store this ref in NX and add an NX_GetLastConversationPartner call that can be used inside of gamemode blocks to return the last NPC that initiated contact with the player, if any. No telling how long ago that conversation may have taken place though, so I think the utility is limited compared to using this with a script/NX var that you can reset to nil yourselves.

Posted

Code @ sourceforge updated.

 

Ashmedai do you want access to the sourceforge repo' date=' or are you going to try and get me to move over to github? ;)

[/quote']

 

Well, Git works nicely with remote collaboration. I haven't missed subversion since I began using it. But I can use sourceforge, no problem.

Posted

I use both but still prefer subversion myself.. merging is not as hard as the git fans make it out to be. Both have some pretty pathological worst cases. If you want access to the sourceforge repo just send me a request there and I'll make it happen. If not we can do the 'git thing'. I already forked your NVSE there but haven't had time to look into it, waiting on you to (hopefully) have time to get the other hooks implemented. If that's not going to happen or will be indefinitely delayed, I can take a stab at it myself.

Posted

I'll have some time in a few days to add the save game event. Unfortunately, that is the only other address in NVSE that a hook can be added to. Other than those, none of the hooks available in OBSE are in NVSE.

Posted

New game has an address, but is commented out and it matches the values in FOSE, so chances are good that is not the real address for new game.

 

For the purposes of generating your own save file, load game may be enough. If there is no file associated to the name in the load file event, assume it is a new game. At least 'new' for the purposes of the plugin.

Posted

If the load hook fires and there's no name then yes, that should work fine. I just need that notification so I can reset the internal state. There must be something in there, because NVSE supplies the GetGameRestarted function to in-game scripts. I've been so busy I haven't been able to look for the source of 'how it knows' that though.

Posted

If the load hook fires and there's no name then yes' date=' that should work fine. I just need that notification so I can reset the internal state. There must be something in there, because NVSE supplies the GetGameRestarted function to in-game scripts. I've been so busy I haven't been able to look for the source of 'how it knows' that though.

[/quote']

 

GetGameRestarted does nothing with the hooks. NVSE keeps a set of all scripts. When s script calls GetGameRestarted, it checks on that set whether that script has called GetGameRestarted before. If it hasn't, it returns true and it updates its set. So next time the script calls the function, it returns false. Next time the game starts, the cycle repeats.

Posted

Right, what I mean is MVSE somehow knows when a game is restarted, in order to reset that list of notified scripts. When it does that, it could also call the newgame notification hook for subscribing plugins, rather than hooking the game for a notification.

Posted

The set is not really reset. It is initialized empty, as calls are made the ref id of the script is added to the set. GetGameRestarted returns true only once per game session.

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

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