Header-only C++ library for Voices of the Void modding. Type-safe game object access with memory safety utilities.
- Type-safe wrappers for game objects (Player, GameMode, Car, etc.)
- Object lifetime tracking to prevent use-after-free
- Utility functions for common modding patterns
- Field access macros for custom UE4 structs
- Hook parameter extraction helpers
- CMake 3.18+
- UE4SS C++ Dev Environment
- Lib targets VotV 082c_0011
git submodule add https://github.com/modestimpala/libvotv.git extern/libvotvadd_subdirectory(extern/libvotv)
target_link_libraries(your_mod PRIVATE libvotv)Copy headers to your project and add to include path:
game.hppStructUtil.hppObjectLifetimeTracker.hppFunctionUtil.hppCommonUtil.hpp
class GameMode {
MainPlayer* mainPlayer;
SaveSlot* saveSlot;
DayNightCycle* daynightCycle;
float totalPower;
float usedPower;
bool isHalloween;
// ...
PowerInfo GetPowerInfo() const;
};
class MainPlayer {
bool underwater;
bool inWater;
bool dead;
float air;
float foodDrain;
float sleepDrain;
AActor* holdObject;
// ...
PlayerState GetState() const;
};
class DayNightCycle {
int32_t current_day() const;
float phase;
float rain;
bool isRaining;
// ...
TimeInfo GetTimeInfo() const;
WeatherInfo GetWeatherInfo() const;
};See game.hpp for complete API.
Prevents use-after-free by tracking UObject lifetimes.
auto& tracker = ObjectLifetimeTracker::Get();
// Track custom types
tracker.RegisterTrackedType(Car::StaticClass());
tracker.RegisterTrackedName(L"door");
// Check validity
if (tracker.IsActorAlive(someActor)) {
// Safe to use
}
// Find tracked objects
auto cars = tracker.FindObjectsByClass(Car::StaticClass());Call Blueprint functions without boilerplate.
auto* actor = /* get actor */;
auto* func = FunctionUtil::FindFunction(actor, STR("SomeFunction"));
// No parameters
FunctionUtil::CallFunction(actor, func);
// Single parameter
FunctionUtil::CallFunction(actor, func, {{"Name", username}});
// Multiple parameters
FunctionUtil::CallFunction(actor, func, {
{"Name", username},
{"Message", message}
});
// With return value
bool result;
FunctionUtil::CallFunction(actor, func, {{"Name", username}}, &result);// String conversion
auto wide = StringConv::ToWide("hello");
auto narrow = StringConv::ToNarrow(L"hello");
// Color utilities
auto color = Color::FromHex("#FF5733");
uint32_t bgra = color.ToPackedBGRA();
// Async worker
AsyncWorker worker;
worker.queue_task([&]() {
// Background task
});
// Safe parameter allocation (RAII)
ParamGuard params(function->GetParmsSize());
if (!params) return false;
// Automatically freed on scope exit
// Hook parameter extraction
auto username = HookUtil::ExtractParamAsString(ctx, STR("Chatter"));
if (username) {
// Use *username
}Map UE4SS header dump offsets to C++ classes:
- Generate headers with UE4SS dumper (enable DumpOffsetsAndSizes)
- Find your class in dumps
- Map fields using macros
// From UE4SS dump: Acremator_C
// bool IsClosed; // 0x0351 (size: 0x1)
#include <votv/game.hpp>
#include <StructUtil.hpp>
class Cremator : public RC::Unreal::AActor {
public:
UE4SS_FIELD(bool, isClosed); // Generates getter/setter
};Available macros:
UE4SS_FIELD(type, name)- Basic fieldUE4SS_FIELD_PTR(type, name)- Pointer fieldUE4SS_VECTOR_FIELD(name)- FVector fieldUE4SS_INT_VECTOR_FIELD(name)- FIntVector with component accessUE4SS_ENUM_FIELD(enum, name)- Enum field
See UE4SS Dumpers for dump generation.
void DoSomething(GameMode* gm) {
auto& tracker = ObjectLifetimeTracker::Get();
if (!tracker.IsActorAlive(gm)) return;
if (!tracker.IsActorAlive(gm->mainPlayer)) return;
// Safe to use both objects
auto state = gm->mainPlayer->GetState();
auto power = gm->GetPowerInfo();
}auto* func = FunctionUtil::FindFunction(actor, STR("TwitchChat"));
if (!func) return;
FunctionUtil::CallFunction(actor, func, {
{"Name", StringConv::ToWide(username)},
{"Message", StringConv::ToWide(message)}
});UObjectGlobals::RegisterHook(
STR("/Game/Path/To/Function"),
[](auto& ctx, void*) {}, // pre
[](auto& ctx, void*) { // post
if (auto name = HookUtil::ExtractParamAsString(ctx, STR("Chatter"))) {
// Use *name
}
},
nullptr
);Submit PRs for:
- Additional game object mappings
- Offset updates for new game versions
- Utility function improvements
- Bug fixes
- MrDrNose - VotV
- UE4SS and their Discord Community
- agersant (gbvsr-frame-meter)