20 posts / 0 new
Last post
ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Developing OBSE plugins for Morroblivion

First, I need to give a BIG thank you to llde for his tips on how to build the obse library and plugins!! (original post by him here: https://tesrenewal.com/comment/84757#comment-84757)  Following your directions, the build succeeded on the first attempt!  Awesome!

Now that I'm finally able to build OBSE plugins, here are some of the things that I have on my todo list:

- A better Universal Silent Voice plugin which plays one of Oblivion's generic greeting dialogs in the appropriate race and gender whenever you start dialog.
- Custom EquipItem function to allow for an arbitrary number of clothing/armor slots.
- Also Custom EquipItem: Disable the cast-on-equip bug when Equipping OnTarget items like Ring of Fireball
-   Implement Morrowind-style combat: miss-miss-miss-miss-hit



 

ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
llde's original post for

llde's original post for convenience:

llde wrote:

There are several reasons for this:

 

First the original OBSE v21 source code is bugged. Compiling a plugin make the compiler and the linker search for symbols that do not exist in a plugin project (ShowRuntimeError and similia).

 

You will need to use my fork: https://github.com/llde/Oblivion-Script-Extender  (Target Release only. Debug Target is not buildable)

 

The other errors are caused by MSVC2015  or above compiler.

 

1) The use of reference in va_start is illegal in C++ standard. It was silently allowed on  previous MSVC version. From VS2015 you need to define _CRT_NO_VA_START_VALIDATION in the project. Note that this piece of code probably never worked completly as intended

 

2)A struct use the hashmap type, but in VS2015 it was deprecated. However has I don't know ATM if this type is an abstraction on a game implementend object, it may not be safe to blindly replace it with a different, albeit similar in scope, type as unordered_map. You need to define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS in preprocessor defines to allow this.

 

However what you wanted to do may be really difficult on the native side.

 

The game doesn't seem to export function in the VTBLs  to manage equipment and slot in a raw fashion. (However many functions are still to be decoded) So all this code should be hand written (you may also need to do an assembly hook)

 

However... Alenet in the new version of OR equipment mode /combat mode is working (or the work is already done) to extend the actual number of slots adding a new weapon slot. You may extend his work when the source is published (He may accept a pull request), or it may be persuaded to add a "robe" specific slot.

 

Raubkopiesäbel
Raubkopiesäbel's picture
Member
Offline
Last seen: 2 weeks 1 day ago
Joined: 05/02/2014 - 09:04
Karma: 85
ponyrider0 wrote:

ponyrider0 wrote:

-   Implement Morrowind-style combat: miss-miss-miss-miss-hit

Will hopefully be optional. 

Greeting 
roxon_55
roxon_55's picture
Contributor
Offline
Last seen: 1 hour 18 min ago
Joined: 04/24/2010 - 22:03
Karma: 1711
Dose not  Need to Be Optional

Dose not  Need to Be Optional If Controlled Blade\Strength\Health  Skills

Raubkopiesäbel
Raubkopiesäbel's picture
Member
Offline
Last seen: 2 weeks 1 day ago
Joined: 05/02/2014 - 09:04
Karma: 85
roxon_55 wrote:

roxon_55 wrote:

Dose not  Need to Be Optional If Controlled Blade\Strength\Health  Skills

The main motivation for Morroblivion is for me that I can play Morrowind with the Oblivion combat system, because it is more realistic and more fun.  

It would be a pity which one the other features then can not use. 

Greeting 

ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
I've been combing over the

I've been combing over the internet for more information on Oblivion's internals to do the Universal Silent Voice update and the EquipItem slot implementation, but not having much luck.  The one bit of luck was that the memory address to hook into the EquipItem function was easy to find in the OBSE source code.  I briefly tried to set up a debugger/disassembler environment with Visual Studio 2015 but it is beyond my simple brain... Visual C++ 5 was so much more intuitive to use, and it already supported cross-compiling to RISC, mobile and Version Control back then: 20 frickin years ago.  Gah!

Well, anyway, with regards to a USV update, I'm going to have to reach out to Ely to see if I can get source code or at least some more direction as to what to modify.  If I can get get it working, my goal would be to dynamically choose the best MP3 source files for any NPC -- whether it is Oblivion voices, Voice-acted voices or CG voices -- that way, we won't have to deal with huge overlapping, disorganized directories of mp3s.  Maybe I could even dynamically generate the CG voices and forego a library of mp3s entirely.  Too bad Microsoft's voice technology is far behind what's offered by Apple or even Amazon.

And as for the EquipItem hack, right now, I've made a enough progress with the script-only version of More-Armor-Slots that I think I can back-burner this project for the time being.

llde
llde's picture
Member
Offline
Last seen: 6 hours 53 min ago
Joined: 09/17/2013 - 07:04
Karma: 359
For the disassembler I

For the disassembler I recommend Ida Pro with the script from JRoush. Note that many parts of  the code is horribly complicated, and many things were not decoded.

You might want to reach Alenet or Tiawar for the EquipItem.

For the Universal Silent Voice update: I wanted to do something similar myself, however never found the correct entrypoint.

In my plan, I would have update USV to fix the "localized race folder"  beheviour. In practice when a dialogue start the game search for the corresponding sound in the specific race folder but it search for it by the "Name" field and not by the "Editor ID". I wanted to do a sort of fallback cascade:  Check Localized name -> Check English Name -> Check EditorIds.

And only after checking all three it would have loaded the empty sound. How this sound to you?

If you is able to contact Elys and obtain a copy of the source code or at least the entrypoint I may be able to help you on this.

ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Cool -- your ideas for USV

Cool -- your ideas for USV sound similar to mine.  On top of your voice file search functionality, I would also like to add an optional ability to search different races (if no altmer, then look for dunmer, then look for imperial, etc.)  In the case of the computer-generated voice files, they are all under the imperial race, so doing a fallback to that for every other race would allow for a less complicated CG-voice setup with full voicing of dialog.  Of course, if we could generate voices from a voice-synth SDK in real-time, that would be even more awesome.  It's too bad MacOS is far more advanced than Windows in this regard -- they have voice libraries for hundreds of languages, multiple accents for English language and even multiple voices for each accent.

I'll try to contact Elys through the Nexus contact page and will let you know what happens.

ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Good news!

Good news!

I got a reply back from Elys with very helpful information / source code.  I will try to re-implement as a C++ plugin and will then post my code here.... 

Update: It's actually (in my opinion) a very elegant solution, the silent-voice function hook seems to be at a point where the game engine code has just failed at loading the voice file from disk.  Elys then overwrites the memory address in the stackbuffer (ESP + 0x64) where the filename should go and then is probably jumping back to the start of that function to re-attempt to load the filename from disk. 

I will hopefully have a working re-implementation of USV written in C++/asm in a week.  From there, we will need to figure out how to read the original filename.  Hopefully, this original filename is intact at the memory address that Elys uses to overwrite with the filename of the silent MP3 (ESP + 0x64).  The original filename will then allow us to generate alternative filename paths to search for the voice file.

PS - I don't think dynamically generating synthesized voice files on the fly (in "real-time") is feasible at the moment with affordable hardware... the steps needed would be to synthesize the full voice file, encode into mp3, write to disk, then pass the filename to the game-engine.  On my computer, just loading the voice file from disk alone is enough to cause stuttering and the loss of the first few milliseconds of audio as the game-engine skips ahead to maintain proper animation sync.... Of course, if I write directly into buffered disk cache instead of the physical disk and then if I'm able to pass the memory address directly to the game-engine then we might shave off enough milliseconds to make it work (the bottleneck/latency would then be how fast the CPU can generate the synthesized voice and encode into mp3). --hehe, unfortunately, this method also assumes that we can access and read the dialog text to be synthesized.

llde
llde's picture
Member
Offline
Last seen: 6 hours 53 min ago
Joined: 09/17/2013 - 07:04
Karma: 359
Shouldn't be too much work to

Shouldn't be too much work to reimplement in C++. Or in a memory safe language like Rust.

Also digging inside OBSE sourcecode it seems that TESDialogue structure is not aviable.

ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Alright, I had some time

Alright, I had some time today and made a quick working test version.  FYI, the path-name of the original missing voice file is indeed at that memory address that I mentioned above!  All we need to do now is parse the original pathname, modify it to what we want and write it back into memory.

Update:  I just confirmed that I can successfully replace the string with a filename found inside a BSA!  I've attached a test plugin with preliminary source code.  The source code files are made for llde's version of obse source.  Just drop it into the obse_plugin_example directory.

If you want to try out this plugin, all you need to do is put the test_usv.dll into \Data\OBSE\Plugins directory.  Then remove Elys_USV.dll.  When you run Oblivion, all missing voice files will be replaced by a line from Socucius Ergalla.  A test_usv.log file will be generated in the \Oblivion main folder with output of all the missing original filenames that it redirected.

To do: 
1. Implement hooks for dialog subtitles and lip files.
2. Parse original pathname string.
3. Replace original pathname with redirected path.

AttachmentSize
File test_usv.7z60.88 KB
roxon_55
roxon_55's picture
Contributor
Offline
Last seen: 1 hour 18 min ago
Joined: 04/24/2010 - 22:03
Karma: 1711
This is Running test_usv in

This is Running test_usv in Plugins.

Plugin List plus test_usv.log in second z7 file

Edit:

Removed Clip.

AttachmentSize
File obse_test.7z850 bytes
ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
haha -- it looks/sounds funny

haha -- it looks/sounds funny when put into a video, but the plugin is working as intended.  This version is just to demonstrate that I could rewrite Elys_USV -- intercepting missing voice files and replace it with a test voice file of my choosing.  I chose Socucius Ergala instead of using a silent MP3 so you can more easily see that it's my plugin and not Elys_USV that is running.  Now I need to finish the next few steps on my to-do list before it's actually usable in gameplay (sorry, should have made that more clear).

roxon_55
roxon_55's picture
Contributor
Offline
Last seen: 1 hour 18 min ago
Joined: 04/24/2010 - 22:03
Karma: 1711
No Prob will wait for the


No Prob will wait for the next 1.

ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Test_USV_2:

Test_USV_2:
- Completed implementing remaining hooks (dialog subtitles, general subtitles, .LIP file loading).
- Unfortunately, I can't figure out a CTD when calling the Oblivion internal CheckFile() routine to check for existence of a LIP file.  I wrote a workaround replacement with PathFileExists() but this is worthless since it doesn't check inside BSAs.
- I'm going to put the lip files aside and focus on implementing the voice file redirection code for now.

UPDATE: okay, I really didn't put the CheckFile routine aside... I kept searching through all the offsets in OBSE and found an indirect match with the offset for the FileFinder object... BINGO: FileFinder->FindFile() looks like an exact match for what Elys calls CheckFile()... now I just need to figure out what I did wrong when calling it.... FIXED!!!

UPDATE2:
Test_USV_3: fully re-implements Elys_USV.dll.  You will still need Elys_USV.mp3 and Elys_USV.lip, just remove the Elys_USV.dll and replace with test_usv.dll.  The \Oblivion\test_usv.log will contain information of all missing MP3/LIP files.  I'm going to start working on a generic greeting behavior when you talk to someone (ala Baldur's Gate) and a race name redirection for the computer-generated voices mod.  I'll probably rename the plugin to something else too, since I've advanced out of just "testing".

 

AttachmentSize
File test_usv_3.7z62.17 KB
junkacc
junkacc's picture
Offline
Last seen: 9 hours 32 min ago
Joined: 11/21/2013 - 03:49
Karma: 9
Wow, does this mean the huge

Wow, does this mean the huge computer generated voice file can now be optimized and further more improved upon with better voices?

AWESOME!!!

ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Test_USV_4:

Test_USV_4:
- The first version to now extend Elys_USV.dll!! 
- This version will search for missing greetings and insert a generic Oblivion greeting, otherwise the silent voice will take over. 
- Unfortunately, the generic greetings will go by quickly (about 3-4 seconds), so you may miss dialog if it's a long greeting -- but the real question is: why aren't you using the Protocolled Dialogs Mod???  Seriously, go install it right now.  It gives you a dialog history window for the current conversation.

To Do:
- Implement fallback system to look in the Imperial race directory for users of the computer-generated voices mod.
- Implement random generic greetings instead of one phrase per race.
- Create framework to receive information from ESP script.

ALSO:  As I mentioned above, OBSE allows plugins to communicate with ESP scripts.  That means we could potentially get information on race, sex, disposition, class, and the actual dialog text...  And that means: real-time synthesized voices may be back on!  Of course, not anytime soon.

AttachmentSize
File test_usv_4.7z63.71 KB
ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Test_USV_5:

Test_USV_5:
- Things are getting interesting!  Users of the computer-generated voice mod rejoice!  Missing voice files will now fallback to searching the Imperial race -- so you can get rid of all those symlinks and just keep an Imperial race folder!
- If no voice files are found in the Imperial race, the fallback cascade continues:  next, the plugin checks for generic greetings.  If no generic greetings are present, it falls back to Elys_USV.mp3/lip files.
- I haven't thought of a good name for the plugin yet, so it stays in "test" form until I do, hehe.

To Do:
- Nothing for now!  I'm going to put creating the ESP script communications system on hold, so I can focus on finishing all of my mainquest script patches.  After that, I'll clean up the source code and maybe rename it to something other than "test".
- If anyone wants to pick up where I left off, feel free!  Post your progress on this thread.

Thanks again to Elys, llde and the entire Morroblivion/TESRenewal community!
 

AttachmentSize
File test_usv_5.7z64.55 KB
roxon_55
roxon_55's picture
Contributor
Offline
Last seen: 1 hour 18 min ago
Joined: 04/24/2010 - 22:03
Karma: 1711
( Kool )  More Life to

( Kool )  More Life to Morroblivion, did not capture the first section

Thanks,, dont let that Spark go Out.

Do you want test-usv.log

Edit:

Question: Doe's the Dialog that has no Audio Listing, Record it self in the Log. There is some Dialog up in Solstheim has no Audio.

AttachmentSize
File test_usv_05.7z13.58 MB
ponyrider0
ponyrider0's picture
Member
Online
Last seen: 37 sec ago
Joined: 07/22/2016 - 05:01
Karma: 398
Thanks, roxon_55.

Thanks, roxon_55.

If you find dialog without audio, it should be recorded in the log with Ely_usv.mp3 as the replacement voicefile like this:

test_usv: Silent Voice Hook: replacing 'data\sound\voice\cm partners.esm\redguard\f\cmpartnersquest_cmshare_00010c97_1.mp3' with 'Data\OBSE\Plugins\elys_usv.mp3'

​You can look at the original filepath that the elys_usv.mp3 replaces to find out more about where that dialog came from.  In the above example, it is "cm partners.esm" and the quest is "cmpartnersquest", the topic is "cmshare" and the actual dialog line has the (non-load order) Form ID 00010c97.  In the future, one thing we could do with this plugin is update it to detect mod names and try to redirect it to another mod directory.  That way, we can store all related audio in one directory for simplicity.