Giter Club home page Giter Club logo

soulsy's Introduction

Soulsy

Test Rust features Build mod archive

Soulsy is a lightweight, fast Souls-style hotkey HUD mod for Skyrim SE and AE. It is inspired by hotkey mods like Elden Equip, iEquip, and LamasTinyHud. It started life as a fork of LamasTinyHud, though it has since diverged significantly.

Screenshot of the hud

The NexusMods page has screenshots and videos of the HUD in use as well as player documentation. The documentation is more readable here in markdown. See Configuring the HUD and Customizing Layouts.

Development goals

My goals are two-fold: make a Souls-style equip HUD that is exactly what I want to use, and learn how to do Rust FFI. A bonus is demonstrating how to write Skyrim native-code mods in Rust.

This project has been released and is in active use. My eventual goal is to move everything except the SKSE plugin glue code to Rust, and have the C++ mostly vanish. There will always be some C++ in the project to interact with the Skyrim reverse-engineered library, which is all in C++ as is the game itself.

Building

Soulsy is a Rust and C++ project, using CMake to drive Cargo to build the Rust parts. The application logic is implemented in Rust, with a bridge to the C++ libraries required to implement an SKSE plugin. It requires the following to build:

The plugin requires the following vcpkg libraries, which will be installed for you:

Finally, CommonLibSSE-NG is pulled in as a git submodule and built. The repo used is my fork of CommonLib, which has some minor fixes in addition to the upstream.

There are a number of development conveniences in the justfile, including build recipes for Powershell. cargo install just if you do not have it. Because I am more comfortable on Unixes than on Windows, some recipes are written in Bash. The just recipes can build, copy to a test mod directory, update version numbers and tag a new release, and build archives for upload to the Nexus.

cargo --doc open displays programmer documentation for the Rust side of the plugin. The C++ side is commented, but not to the same degree.

You are absolutely invited to contribute. This project follows the standard Contributor's Covenant.

Credits

I could not have approached the rendering code without the work in LamasTinyHud, so mlthelama gets all the props. I also learned a lot about how to make an SKSE plugin by reading their source. Give that HUD a try if you don't like the souls-game style, or want a UI you can edit in-game. The original is the only hotkeys hud mod I tried that worked well in my game, so that's a testimonial.

The icons for the built-in theme are the usual SkyUI icons, plus the futura-book-bt true-type font. The background assets were built from scratch but were inspired by the Untarnished UI skin for LamasTinyHUD by MinhazMurks.

The built-in icons are the SkyUI icons by psychosteve, which are used in so many places I am not sure how to credit them. The icons for the Ceej remix layout are licensed to me from the Noun Project for use without attribution, but I am going to give attribution anyway because they're great icons. I am using the Role Playing Game collection by Maxicons. The THICC icon pack uses icons with permission from the THICC icon mod.

The font in use for some layouts is Inter.

cxx made developing the C++/Rust bridge a snap. This crate unlocks Rust as a viable language for all of your modding needs. bindgen is also available for doing this, but cxx generates safer C++ bindings by restricting the kinds of code generated. Its major drawback is that async Rust is not yet supported, but there are workarounds described in the docs.

License

GPL-3.0.

soulsy's People

Contributors

aphosis avatar ceejbot avatar komegaki avatar vainlystrain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

soulsy's Issues

Text drop shadows or background

It would be nice to have drop shadows or text specific background for easier readability. At the moment, the text can be harder to read depending on the game world light level/texture.

tighten up brief peek timing

The brief peek is the term in the HUD rendering code for the HUD showing itself briefly if it's hidden when you cycle. It needs to become visible much more quickly. It can fade out using the player's setting for fade-out, but it needs to become visible faster. It should still use the easing function to slide in nicely.

Classify spells more deeply for better icon coloring and selection.

This is independent from the OCF work, because the OCF keywords do not cover spells AFAIK. There might be an additional project that does, in which case I should support it. In the meantime, I should push the work in the icons branch all the way forward with spells.

gracefully retire the TOML serialization code

I'll want to keep the deserialization for a while, but we want to stop writing fresh TOML in version 0.9. This will in turn allow me to clean up the fairly awful bincode serialization shadow structs.

consider adding favorited items to cycles

This is a little funky with picking a hand. Some selections obviously go into one slot or another, but for spells and one-handers I think it'll need either a preference or just letting the user override afterward.

auto-sheathing when sitting in a chair is wonky

When you stand and ready your weapons again, the left hand item is not properly re-equipped. E.g., a torch in the left hand won't start burning again. The un-equipping is happening out of band of the HUD, possibly? I'm not sure why it's not just a regular weapon un-ready. Need to look at logs.

move all format strings from rust code to translation files

So they can be translated. Some implementation notes:

  • They don't have to be the same translation files as the MCM strings. They can be in their own UTF-8 files.
  • Parallel structure to the MCM translation files, though. One per language, in the same directory, named for the mod.
  • Format strings themselves will need work. Numbered parameters, for instance.

Use keywords from the Object Categorization Framework

The keyword reference is in their wiki.

Tasks to get this done:

  • Generate useful enums from relevant keywords. Probably these will have to be shared enums. Segregate them from the API bridge, probably with a separate cxx bridge. Sigh.
  • Update the ItemKind enum to include additional categories as it makes sense. Note that the core list has to remain and remain in the order given because the repr value for icons is used in persisted cycle data.
  • Rename icons to match the derived display strings from the OCF-matching enums. This will make life better in the long term.
  • At item entry creation time, look up keywords for spells, weapons, and armor. Assign icons based on keywords. Fall back to game data icon assigment.
  • Implement on-the-fly coloring for icons, not preset in layouts. Alpha transparency will be respected still, however.
  • Look up coloring using color keywords. This varies by category. E.g., ammo colors vs spell colors.
  • Map icons to categories. Remove all item coloring from icons and use white svgs, so on the fly coloring works.

Use the existing ceej/icons branch for this work.

funky behavior with fade-out

  • The HUD briefly fades out at launch, no matter what your setting is.
  • It doesn't remember last-visible state. Store this in the cycles file, probably.
  • The show/hide key sometimes doesn't work, and I think this is related.

The entire fade-out implementation needs a look-over and probably a simplification.

CTD when equipping a ring/amulet

I get a crash to desktop whenever I equip a ring or amulet.
This happens with both vanilla and modded rings/amulets.

Here are the top few lines from the crash report, though I don't know if it will help.

PROBABLE CALL STACK:

[ 0] 0x07FEBF8F7069  SoulsyHUD.dll+00E7069	cmp [rax+r8*1], dil |  C:\Users\ceej\source\repos\ceejbot\soulsy\src\game\equippable.cpp:248 ?collect@KeywordAccumulator@equippable@@SA?AW4ForEachResult@BSContainer@RE@@AEAVBGSKeyword@5@@Z
	

[ 1] 0x07FEBF94169C  SoulsyHUD.dll+013169C	test eax, eax |  ?ForEachKeyword@BGSKeywordForm@RE@@QEBAXV?$function@$$A6A?AW4ForEachResult@BSContainer@RE@@AEAVBGSKeyword@3@@Z@std@@@Z_13169C
	

[ 2] 0x07FEBF8F6160  SoulsyHUD.dll+00E6160	mov rcx, rdi |  C:\Users\ceej\source\repos\ceejbot\soulsy\src\game\equippable.cpp:134 ?hudItemFromForm@equippable@@YA?AV?$Box@UHudItem@@@cxxbridge1@rust@@PEAVTESForm@RE@@@Z
	

[ 3] 0x07FEBF940666  SoulsyHUD.dll+0130666	mov rax, [rsp+0x20] |  C:\Users\ceej\source\repos\ceejbot\soulsy\target\cxxbridge\soulsy\src\lib.rs.cc:1433 helpers$cxxbridge1$formSpecToHudItem C:\Users\ceej\source\repos\ceejbot\soulsy\target\cxxbridge\soulsy\src\lib.rs.cc:1447 helpers$cxxbridge1$formSpecToHudItem
	

[ 4] 0x07FEBF8757D1  SoulsyHUD.dll+00657D1	movups xmm0, [rax+0x60] |  _ZN6soulsy4data10item_cache9ItemCache16get_with_refresh17h7808334febc6c33cE_657D1
	

[ 5] 0x07FEBF86B9B7  SoulsyHUD.dll+005B9B7	movzx eax, byte ptr [rbp+0x2A6] |  _ZN6soulsy10controller7control10Controller20handle_item_equipped17h8105c115dfaee55eE_5B9B7
	

[ 6] 0x07FEBF8446DE  SoulsyHUD.dll+00346DE	mov ebx, eax |  _ZN3cxx6unwind14prevent_unwind17ha00217cc511c0f0dE_346DE
	

[ 7] 0x07FEBF815C5D  SoulsyHUD.dll+0005C5D	nop |  cxxbridge1$handle_item_equipped_5C5D
	

[ 8] 0x07FEBF92048D  SoulsyHUD.dll+011048D	lea rcx, [rsp+0x20] |  C:\Users\ceej\source\repos\ceejbot\soulsy\src\plugin\sinks.cpp:52 ?ProcessEvent@EquipEventSink@@MEAA?AW4BSEventNotifyControl@RE@@PEBUTESEquipEvent@3@PEAV?$BSTEventSource@UTESEquipEvent@RE@@@3@@Z C:\Users\ceej\source\repos\ceejbot\soulsy\src\plugin\sinks.cpp:75 ?ProcessEvent@EquipEventSink@@MEAA?AW4BSEventNotifyControl@RE@@PEBUTESEquipEvent@3@PEAV?$BSTEventSource@UTESEquipEvent@RE@@@3@@Z

implement support for adding "unarmed" to cycles

I now understand why iEquip did this the way it did, and I am going to borrow their approach.

  • Add a boolean setting for auto-including unarmed options in left & right hand cycles.
  • Update cycles when this setting toggles.
  • Make sure the update gets flushed to disk.
  • Test both removing and adding.

Commit fdccbf7 implements most of this.

find a way to show poisons on weapons

Take some inspiration from iEquip here, I think. A green or purple droplet would be great.

Consider adding on-the-fly colors from item statuses to hud draws.

feedback on equip change

A brief highlight flash on a changed slot OR a slot that's cycling and in mid-timer has been requested by several people.

test two-handed spells

I might want to add an item kind for each variety of two-handed spell. By this I mean a spell that requires two hands, not merely one that can be dual-wielded for more damage.

is a toml file the right way to handle persistent per-character state?

It's far easier for me to cope with, and very easy to inspect out of game, but doing it this way has some drawbacks. The file sticks around when characters are deleted. Old files stick around when a character is renamed. It cannot roll back to a previous state if the user re-loads a save, though the cycle will be re-validated.

My laziness says to leave it as-is, but it bothers me.

CTD issue when equipping a scroll that uses both hands - v0.8.3

Version used - v0.8.3

Hi, I have encountered a CTD that may relate to Soulsy HUD. The crash happened at the start of a fight when I tried to equip a scroll of mass paralysis, and the game crashed instantly with the following crash log. The scroll was not added to any slots of the Soulsy HUD and is directly accessed through inventory.

Crash Log

I narrowed the problematic scrolls to those that use both hands (e.g., Mass Paralysis, single-hand scrolls can be equipped with no issues).

As I tested more, it does not matter what weapons the player uses/equips. As long as I switch to a scroll that will use both hands, the game CTDed with the crash log above.

test with CGO enabled and handle any oddnesses

In particular, test using a two-handed weapon with the single-hand grip. If there's a spell in the left hand, cycling that hand will force a change in the right to a one-hander. This is obviously wrong when CGO is up.

Things to figure out: How to tell if CGO is present. How to tell if CGO is in grip-switch mode.

arrow cycling is not working right

It skips arrow types and it doesn't filter ammo appropriately. As in, it includes bolts when it shouldn't, and so on.

I think the right solution is going to be to build an ammo list when the ranged weapon is equipped, and manage it on the Rust side until it's unequipped. Trying to be stateless isn't sparking joy atm.

use keywords to mark items that are in cycles

This is more of an investigation than a feature spec. helpers.cpp has notes on how to add and remove keywords from forms on the fly. Is there a way to use these keywords to control how an item is displayed in SkyUI? The inventory menus show is-favorite and is-poisoned, but those are built into the game. Would this have to be built into the flash for a menu?

Cannot cycle when only one item in left/right hand cycle (also, missing "unarmed")

It seems that in v0.7.1, the default "unarmed" is missing for both left and right-hand cycles, and when you only have exactly one item added to either cycle, pressing the corresponding cycle key will not change the desired item.

Example:

Iron Greatsword added to right-hand cycle (the only item)
Equip iron sword in the right hand
Press Cycle Key (e.g., mine is 4)
Player will not equip Iron Greatsword

Display enchant/poison status for equipped items.

Something as simple as a green or purple colored droplet icon for poison plus a filled bar for enchant charge would work. However, this is an addition to the left and right hand hud widgets that is not applicable to the others. It also needs design for what aspects of the widget need to be controlled by the layout.

Comb out auto-hide vs the toggle key

Some of this code is left over from the initial fork and I don't think it's working very well. Simplify.

Hide the hud when out of combat: toggle

Autofade time: shown & honored if toggle enabled.
HUD show/hide key: shown and honored if toggle disabled.

It's possibly this simple, but the code is evolved and tangled.

losing all items out of band doesn't update the cycles

To repro: Get arrested and go to jail. The cycles don't update and you might lock up.

Probably there's an event I need to handle better? I would think this would go through the usual inventory-changed or equip-changed event paths, but maybe I'm not handling these two the same way. In which case that would be the bug.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.