Working on a modder’s resource, CobbAPI, which will offer other mod authors access to a lot of the stuff I’ve reverse-engineered and used in my own mods. With so many APIs to offer, I need a nice way to test them in a variety of situations.

When making APIs for my own use, I would generally create a testing cell with custom scripted unit tests. However, tonight I had the idea of making a “test suite” MCM that lets me configure and fire calls to each API.

It’s a bit of an ugly solution… Under the hood, each API is defined similarly to MCM state options, with getters for parameter information and return types, and an interface for calling any individual method. However, it’s something that’ll be very easy to automate (though I’m currently filling the data in manually for testing’s sake). In fact, once I do automate it, I could even release the test suite itself as a modder’s resource!

(I could also release it alongside CobbAPI as a sort of downloadable demo.)

2 notes

ESO Death and Resurrection

On a whim, I decided to go looking for the code in Skyrim that handles actor deaths. I died in-game and found it boring, having to reload a previous save and lose progress. I was kinda curious as to whether I could implement something better – maybe respawning or an ESO-style resurrection.

I actually found 90% of what I’d need to intercept the death code in just one night. Here’s a video.

(I probably should’ve thrown the game’s vanilla intro in as a bonus highlight. It softlocks, and Lokir just keeps running into the side of a building as archers pelt him with arrows.)

Working on Cobb Positioner’s next version right now. The mod is currently capable of revealing all of the game’s invisible light emitters, by swapping their 3D models en masse at run-time. I’m extending that feature, to allow mods to declare a model swap for any object. The intention is to imitate the Creation Kit’s “editor markers.”

My main motive for this is to add more Atronach Crossing content – specifically, invisible decorations and non-solid decorations. Placeable fog, dust, and mist effects would be an example of the latter: with an editor marker feature, it’ll be possible to select and move these.

As for invisible decorations, the most notable application is for bookshelves. Imagine an invisible patch of air that functions as a bookshelf. When you put books “into” the “bookshelf,” they are arranged in a stack. Toggle an editor marker, and you can move the “bookshelf” around… allowing you to easily set up stacks of books on a desk or elsewhere in a room. Any arrangement would be possible: I could do an invisible “bookshelf” that arranges books in a straight line, and then you could use any shelf or surface as a bookshelf.

There are other applications as well, such as invisible markers for sitting or (depending on how the game’s animations are set up) meditating.

Assuming I get it published soon, the Cobb Encumbrance rebuild will let you choose the notification strings that appear for each encumbrance stage. There are a variety of options in first-person, second-person, and Khajiit third-person, for a total of 80 choices.

I kinda wanted to just let the screenshot stand on its own but Tumblr’s garbage-tier post editor still doesn’t offer the ability to set alt text on images a full seven years after people noticed the problem, so if you can’t see the screenshot for some reason, here are the Khajiit options visible:

  • How has this pack not torn off at the straps?!
  • Khajiit is being crushed under all of this junk!
  • This one is being flattened into a rug!
  • Why is Khajiit even carrying this much?!
  • Khajiit’s pack weighs even more than she does!

(That last one has “he” and “they” variants as well.)

1 note

[NOT DEV] Elder Scrolls Online, Thievery, Murder, and You!

So, you aren’t involved in a trade guild. You’re vaguely aware of what “writs” are, but you don’t get how to mass-complete them and rake in the gold. How do you make money in this game?

Yeah. You know what this article’s gonna be about. I’m gonna talk you through the basics of making a character that’ll make money. Here, you’ll learn the ins and outs of being a malevolent societal parasite. You’re gonna be the best damn tapeworm Abah’s Landing ever had.

Small caveat: you will need the Thieves Guild and Dark Brotherhood DLCs. You can get them separately, or save some cash by getting the Guilds and Glory pack from the in-game store.

Keep reading

Just reorganized all of NorthernUI’s patches. I was running into an issue where I needed a patch to check whether an asset file existed before being applied, but the game’s g_FileFinder wasn’t initialized yet. Turns out that OBSEPlugin_Load runs before the game does anything substantial, so most singletons are under construction or nullptr.

Built an entire system for queueing patches, defining prereqs, and running them when all prereqs are ready, so now, I can do this:

man.RegisterPatch("XXNMenus", &CobbPatches::XXNMenus::Apply, { PatchManager::Req::G_FileFinder });

PatchManager sets up some basic hooks in its constructor – things like g_FileFinder being constructed – and those hooks fire calls like

PatchManager::GetInstance().FireEvent(PatchManager::Req::G_FileFinder);

Pretty fun. Even found a minimally hideous workaround for a language limitation involving enums. You can try

enum Req : size_t {
   G_FileFinder,
   // ...
};

but enums don’t reliably implicit-cast to their underlying types, so something like std::initializer_list<Req> won’t cast to std::initializer_list<size_t>. This is a problem because an initializer list with only Req values in it will be a Req initializer list, and that was breaking things. I needed a workaround…

GENTLEMEN… BEHOLD!!

class Req { // can't implicitly convert so we're going with this trash
   Req() = delete;
   //
   public:
      static constexpr size_t G_FileFinder = 0; // g_FileFinder created yet?
      static constexpr size_t P_XInput     = 1; // applied XInput patch (or not) yet?
      static constexpr size_t X_PostLoad   = 2; // OBSE PostLoad event
      static constexpr size_t COUNT        = 3;
};

Externally, you use it exactly the same as an enum! Internally, it has to be manually maintained! Conceptually, it’s a little bit hideous!

It’s perfect C++.

(And yes, I know it’s super basic, but when you search this kind of thing, sometimes you find all the over-engineered solutions first. Having to route enums through templates and whatnot isn’t a problem I run into often, so as basic as this solution was, coming up with it was more like building something than pulling something out of a library — especially since templates interfere with IntelliSense stuff and you can’t tell at a glance whether something is busted. In a few ways, it was fun.)

1 note

The menu that NorthernUI offers to customize gamepad controls. You can create and manage multiple control schemes. If you pay close attention, you’ll see the button prompt for speaking to NPCs change as I switch schemes or remap the Activate control.

Default control schemes are loaded from a plaintext file, so I don’t have to recompile the DLL to change them, and translators can edit them freely. (Not that I expect anyone to translate the mod or anything – and if any particular language uses a different binary, e.g. for a multi-byte text encoding, then there’s absolutely nothing I can do to ensure compatibility. But I did try to build this so that localization would be easy, just because that’s the right way to build it.)

All that’s left to do now is polishing, and then the mod should be ready to ship.

1 note

NorthernUI - brief update

Turns out, getting MenuQue compatibility didn’t entail nearly as much work as I thought it would. I only had to replace the one subroutine that MenuQue replaced. So that’s good.

The much harder thing to fix was this: after an hour or so of casual play, all of the menus would show broken display behavior. The most noticeable symptom was that menus like the barter menu would be cut off on all edges of the screen – almost as if the menu was rendering larger than the screen. There were other odd behaviors, too: within scrollable lists, list items would be cut off even if the list container was large enough to hold them – and sometimes, they’d be cut off on the top and left edges! This broken display behavior would last until the game was restarted.

After a few days of digging into this, I got lucky in two ways.

Keep reading

NorthernUI and MenuQue

Several of NorthernUI’s features stop working if MenuQue is installed. This is because MenuQue completely replaces a subroutine that I need to patch, so my hooks don’t run. (This subroutine allows the XML parser to properly recognize new “traits” and “operators” in a UI’s code. NorthernUI and MenuQue both need to patch the subroutine to get their stuff recognized, so it’s perfectly understandable that we’d collide with each other – though it’s hard not to be just a little bit salty, given that MenuQue’s added features in this area are literally all 100% undocumented and apparently not even meant for public use.)

The only real way to address this incompatibility is to revert MenuQue’s patch to that subroutine and try to just handle things in a way that MenuQue can function with (i.e. have my patch make my traits and operators and MenuQue’s traits and operators recognizable)… but doing that causes the game to crash.

After maybe two days of work, I think I finally understand why.

MenuQue patches throughout the entire XML parser, and adds a ton of features – some of which are great ideas! It’s tempting to just blow them all away so my mod can work (and implement the ones I care about on my own) since they’re not documented on the mod page, the CS wiki, or in any readme files… but there’s no telling who might be using them or where (e.g. because MenuQue’s author documented them on a dead site, or just told their friends about them), and it’s not like anyone around to update their old Oblivion mods anymore if I break them. That means that I do need to retain compatibility, rather than simply reverting the entire parser to vanilla and then applying my own patches.

The game uses a two-point-five-stage parser. Stage 1 reads the XML characters and produces a set of small objects, representing tokens – an object for the start of a tag; an object for an attribute value; and so on. Stage 1.5 reads these tokens and “refines” them into something meaningful – the start of a tile, the start of a trait, the start of an operator, the end of a tile, and so on. Stage 2 happens at the latest possible moment, and actually converts these tokens into a hierarchy of active Tile objects – that is, a menu with full behavior, ready to display. This parse process is done for both entire menus and for templates (e.g. list items that can be shown in a menu at run-time, such as for the inventory), with templates undergoing Stage 2 parsing right as they’re added to an already-open menu.

Each of those token objects has a small code identifying its purpose, e.g. 0xA for a generic start tag and 0x28 for the start of a tile (and in fact, Stage 1.5 converts the former code to the latter). MenuQue patches in new codes that I can’t identify: 0xD and 0x2A. (This is in addition to tons of other parse-time stuff it adds to the engine.)

The solution, then, is “simple.”

I need to fully translate (rather than transliterate in place) the entire vanilla XML parser from x86 to C++, so I can understand it, and then translate MenuQue’s respective hooks in the same way. Then, I can see exactly what it’s changing, and endeavor to replicate all of those features in my mod. I don’t have to copy code (and don’t want to!), but I need to know what MenuQue is even doing before I can find my own way to do the same thing and maintain compatibility.

The XML parser isn’t set up to be extensible. It’s a lot like records in an ESP file, undergoing the Rule of One. The only way to be compatible with MenuQue – at least, for anything handled at the parser level – is to completely blow away all of its changes and then just do the same things myself.

NorthernUI has just hit a very important development milestone!

I have now reskinned every single vanilla menu and added complete or near-complete gamepad support to them! The last of the menus was the PersuasionMenu, which you can see in action here. This video even manages to demonstrate the gamepad support: the first time you see me start the minigame, keep your eye on the in-game cursor and the minigame circle, and you just might spot how I got keynav to play nice with the mouse-oriented minigame code.

This milestone doesn’t mean that the mod is done. I have to fix a small snafu involving small text (you may notice that the version number on the main menu is in a vanilla font), fix some bugs within the DLL, add missing features to some of the DLL’s mechanisms (e.g. generating missing resource files with default values), and create and patch in menus to customize the mod itself and the gamepad controls. Still, reskinning every vanilla menu and patching several of them (sometimes extensively) is an enormous amount of progress. We’re in the eleventh hour of development now.

1 note

Finished reskinning the World Map for NorthernUI. The tooltip is nice and stylish, and you can page through the journal content using gamepad face buttons and bumpers. (It was more challenging to get that working sensibly and intuitively than you might expect.) Still no map panning for the gamepad yet, though.

Also, I know what I’m going to be doing next: completely replacing all of the code for the Save and Load menus with a total rewrite that doesn’t make it so easy to delete your save files by accident, with no backups or possibility of recovery. Why do they show the same number of confirmation dialogs for loading as for deleting, and why did they use Shift + Click for deletion if they couldn’t get the game to properly detect when you release the Shift key?

I lost maybe a dozen hours of playtime to get this screenshot. Enjoy.