https://github.com/modestimpala/libvotv
A modern C++ header-only library for interacting with VotV.
https://github.com/modestimpala/libvotv
cpp ue4 ue4ss votv
Last synced: 3 months ago
JSON representation
A modern C++ header-only library for interacting with VotV.
- Host: GitHub
- URL: https://github.com/modestimpala/libvotv
- Owner: modestimpala
- Created: 2025-01-10T14:27:39.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-01-18T06:14:56.000Z (5 months ago)
- Last Synced: 2025-01-18T06:27:00.277Z (5 months ago)
- Topics: cpp, ue4, ue4ss, votv
- Language: C++
- Homepage:
- Size: 25.4 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# libvotv
[](https://en.cppreference.com/w/cpp/17)
[](https://cmake.org/)
[](https://mrdrnose.itch.io/votvVoices_of_the_Void/)
[](https://docs.ue4ss.com/)
[]()A modern C++ header-only library for interacting with Voices of the Void game state, providing type-safe access to game objects, player state, and environment variables.
## Features
- 🎮 Type-safe game state access through a single header
- 🔒 Memory-safe field manipulation
- 🎯 Direct access to core game systems
- 🧰 Modern C++ wrapper around UE4/UE4SS objects
- 📡 Object lifetime tracking utilities
- 🔧 Struct manipulation macros for clean field access of custom fields### Todo
- Map VotV specific functions with same method
## Table of Contents
- [Prerequisites](#prerequisites)
- [Version Compatibility](#version-compatibility)
- [Installation](#installation)
- [Usage](#usage)
- [Utility Classes](#utility-classes)
- [API Reference](#api-reference)
- [Examples](#examples)
- [Contributing](#contributing)
- [Credits](#credits)## Prerequisites
- CMake 3.18 or higher
- [UE4SS C++ Dev Environment Setup](https://github.com/modestimpala/RE-UE4SS)## Installation
The library consists of three headers:
- `game.hpp` - Main game state and objects
- `ObjectLifetimeTracker.hpp` - UObject lifetime management
- `StructUtil.hpp` - Field access macros and utilities### As a CMake Subproject
1. Add the repository as a submodule:
```bash
git submodule add https://github.com/modestimpala/libvotv.git extern/libvotv
```2. Add to your CMakeLists.txt:
```cmake
add_subdirectory(extern/libvotv)
target_link_libraries(your_project PRIVATE libvotv)
```### Manual Installation / IDE Setup
Since the library is header-only:
1. Copy the three headers to your project
2. Add their location to your include path
3. Ensure UE4SS headers are available## Usage
### Basic Setup
```cpp
#include // Single header for all game functionality
#includeusing namespace votv::game;
// Get existing game mode from UE4SS
GameMode* gameMode = /* get from UE4SS */;// Validate object is still alive
auto& tracker = ObjectLifetimeTracker::Get();
if (!tracker.IsActorAlive(gameMode)) return;// Access player
MainPlayer* player = gameMode->mainPlayer;
if (!tracker.IsActorAlive(player)) return;// Check player state
if (player->inWater && player->air < 50.0f) {
// Handle low air situation
}
```## Utility Classes
### ObjectLifetimeTracker
The `ObjectLifetimeTracker` provides safe UObject lifetime tracking.
Initialize the ObjectLifetimeTracker as early as possible in your mod lifecycle:
```cpp
auto on_unreal_init() -> void override
auto& tracker = ObjectLifetimeTracker::Get(); // Get instance early
// Rest of initialization...
}
```Early initialization ensures no objects created during startup are missed by the tracking system.
Example:
```cpp
#include// Get singleton instance
auto& tracker = ObjectLifetimeTracker::Get();// Track specific types
tracker.RegisterTrackedType(Car::StaticClass());
tracker.RegisterTrackedName(L"specialDoor");// Check if objects are still valid
if (tracker.IsActorAlive(someActor)) {
// Safe to use
}
```Features:
- Default tracking of GameMode and MainPlayer objects
- Registering custom types/names to track
- Thread-safe operation
- RAII-based resource management
- Protection against use-after-free### StructUtil Macros
`StructUtil.hpp` provides type-safe field access macros:
```cpp
// Regular field access
FIELD(0x0600, MainPlayer*, mainPlayer); // Generates getters/setters// Vector field with component access
VECTOR_INT_FIELD(0x02F8, timeZ); // Adds _x, _y, _z component access// Enum field with type safety
ENUM_FIELD(0x01E1, GameModes::Type, gamemodeType);// Bit field for flags
BIT_FIELD(0x0480, 0x01, someFlag);// Array field access
ARRAY_FIELD(0x0208, RC::Unreal::TArray, scores);
```Features:
- Automatic getter/setter generation
- Type-safe field access
- Support for vectors, enums, arrays and bit fields
- Property syntax support through __declspec
- All methods marked noexcept where appropriate
- Proper reference handling (lvalue/rvalue)## API Reference
### Core Game Classes (game.hpp)
All game functionality is contained in a single header under the `votv::game` namespace.
```cpp
namespace votv::game {
class GameMode;
class MainPlayer;
class DayNightCycle;
class Car;
class Door;
class KerfurOmega;
class GameInst;
class SaveSlot;
}PowerInfo GetPowerInfo() const; // Get complete power system state
TimeInfo GetTimeInfo() const; // Get complete time info
WeatherInfo GetWeatherInfo() const; // Get complete weather info// Game Instance
class GameInst : public RC::Unreal::UObject {
SaveSlot* save; // Active save
GameModes::Type gamemodeType; // Game mode Type (Sandbox, Story, etc)
bool opened; // Instance opened
int32_t startDay; // Starting day
...
};// Save slot
class SaveSlot : public RC::Unreal::UObject {
float food; // Food level
float sleep; // Sleep level
int32_t Points; // Money
float health; // Current health
...
};```
See header file for complete API.
## Examples
### Safe Object Access Pattern
```cpp
#include
#includevoid SafeGameObjectAccess(votv::game::GameMode* gameMode) {
auto& tracker = ObjectLifetimeTracker::Get();
// Validate game mode
if (!tracker.IsActorAlive(gameMode)) return;// Access and validate player
auto* player = gameMode->mainPlayer;
if (!tracker.IsActorAlive(player)) return;// Safe to use objects
auto state = player->GetState();
auto power = gameMode->GetPowerInfo();if (state.inWater && power.ratio < 0.2f) {
// Handle dangerous situation
}
}
```### Custom Object Tracking
```cpp
#include
#includevoid SetupTracking() {
auto& tracker = ObjectLifetimeTracker::Get();// Track all cars
tracker.RegisterTrackedType(Car::StaticClass());// Track special objects
tracker.RegisterTrackedName(L"prop_important");// Later cleanup if needed
tracker.UnregisterTrackedType(Car::StaticClass());
tracker.UnregisterTrackedName(L"prop_important");
}
```### Time and Weather Management
```cpp
#includevoid HandleTimeChange(DayNightCycle* dnc) {
// Get complete time state
auto timeInfo = dnc->GetTimeInfo();
auto weather = dnc->GetWeatherInfo();
// Access raw day counter
int32_t currentDay = dnc->current_day();
// Modify time
dnc->set_timeZ(0, 0, currentDay + 1);
}
```## Defining Custom Fields from UE4SS Header Dumps
See [UE4SS Dumpers](https://docs.ue4ss.com/dev/feature-overview/dumpers.html#c-header-generator)
See [UE4SS Dumper Converter](https://github.com/modestimpala/RE-UE4SS/blob/main/DumpConverter.md)
Make sure DumpOffsetsAndSizes and LoadAllAssetsBeforeGeneratingCXXHeaders are 1 then dump headers from main menu.
Find specific class, then map offsets:
```cpp
// Dumped cremator.hpp
class Acremator_C : public Aactor_save_C
{
...
bool IsClosed; // 0x0351 (size: 0x1)
...
}#include
#include// Your custom wrapper class (e.g., extra_game.hpp)
class Cremator : public RC::Unreal::AActor {
public:
FIELD(0x0351, bool, isClosed); // Maps to IsClosed from dump
};
```And so on for any other custom fields needed.
## Contributing
1. Fork the repository
2. Create your feature branch (git checkout -b feature/extra-offsets)
3. Commit your changes (git commit -m 'More offsets')
4. Push to the branch (git push origin feature/extra-offsets)
5. Open a Pull Request## Credits
- MrDrNose for VotV
- UE4SS and their Discord Community
- agersant (gbvsr-frame-meter)