Skip to content

Commit

Permalink
Rebranding, Map Editor and Improvements (#217)
Browse files Browse the repository at this point in the history
String Commands
Map Editor
Rewrite Global Editor and add Local Editor
Added Option to Force Enable Snow and Halloween Events
Improved Shows Menu
Improved Native Invoker
...and more + lots of bug fixes
  • Loading branch information
Rxann authored Jan 31, 2025
1 parent ceed442 commit 8727e0b
Show file tree
Hide file tree
Showing 113 changed files with 12,677 additions and 7,750 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
BasedOnStyle: Microsoft
AccessModifierOffset: '-4'
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: 'true'
AlignConsecutiveAssignments: 'false'
AlignEscapedNewlines: Left
AlignOperands: 'false'
AlignTrailingComments: 'true'
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ jobs:
run: cmake -D CMAKE_BUILD_TYPE=Release -S. -Bbuild -G Ninja

- name: Build 64bit release DLL
run: cmake --build ./build --config Release --target HorseMenu --
run: cmake --build ./build --config Release --target Terminus --

- name: Check if DLL got built
run: if (-Not (Test-Path -path "build/HorseMenu.dll")) {throw 1}
run: if (-Not (Test-Path -path "build/Terminus.dll")) {throw 1}

- name: Rename DLL to HorseMenu-dev-{GITHUB_SHA}.dll
- name: Rename DLL to Terminus-dev-{GITHUB_SHA}.dll
run: |
del HorseMenu-dev-*.dll
ren HorseMenu.dll HorseMenu-dev-${{github.sha}}.dll
del Terminus-dev-*.dll
ren Terminus.dll Terminus-dev-${{github.sha}}.dll
working-directory: build/

- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: binary
path: build/HorseMenu-dev-*.dll
path: build/Terminus-dev-*.dll
14 changes: 7 additions & 7 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ jobs:
run: cmake -D CMAKE_BUILD_TYPE=RelWithDebInfo -D OPTIMIZE=YES -S. -Bbuild -G Ninja

- name: Build 64bit release DLL
run: cmake --build ./build --config RelWithDebInfo --target HorseMenu --
run: cmake --build ./build --config RelWithDebInfo --target Terminus --

- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: binary
path: |
build/HorseMenu.dll
build/HorseMenu.pdb
build/Terminus.dll
build/Terminus.pdb
- name: Generate Build Info
id: var
Expand Down Expand Up @@ -126,7 +126,7 @@ jobs:
- name: Echo build sha256
id: build_sha
run: |
sha256sum HorseMenu.dll > sha256.checksum
sha256sum Terminus.dll > sha256.checksum
echo "build_sha=$(cat sha256.checksum)" >> $GITHUB_OUTPUT
cat sha256.checksum
Expand All @@ -148,8 +148,8 @@ jobs:
You can download the build artifacts, generate a SHA256 checksum and compare it with the below binary.
Build artifacts ARE NOT automatically the same as release assets since release assets can be modified afterwards.
These are nightly builds of HorseMenu, they are provided for testing purposes only:
- Test if your build environment produces a broken HorseMenu.dll
These are nightly builds of Terminus, they are provided for testing purposes only:
- Test if your build environment produces a broken Terminus.dll
- Test if source code is out of date and no longer compatible with the current version of Red Dead Redemption 2
If you wish to use this menu as-is you are on your own, no warranty is provided.
Expand All @@ -159,4 +159,4 @@ jobs:
${{ needs.build_nightly.outputs.full_sha }}
```
files: |
HorseMenu.dll
Terminus.dll
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.20.x)

project(HorseMenu VERSION 0.0.1 DESCRIPTION "HorseMenu, a beta-stage mod menu for Red Dead Redemption 2 and Red Dead Online, inspired by YimMenu, that protects against crashes and enhances your experience.")
project(Terminus VERSION 0.0.1 DESCRIPTION "Terminus, a beta-stage mod menu for Red Dead Redemption 2 and Red Dead Online, inspired by YimMenu, that protects against crashes and enhances your experience.")

# libs
include(cmake/vulkan.cmake)
Expand Down Expand Up @@ -37,7 +37,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE
message(STATUS "Setting up linked libraries")
target_link_libraries(${PROJECT_NAME} PRIVATE AsyncLogger imgui minhook nlohmann_json::nlohmann_json dbghelp RDR-Classes "${DEPS_DIR}/vulkan-1.lib")

add_compile_definitions(${PROJECT_NAME} "_CRT_SECURE_NO_WARNINGS" "NOMINMAX" "WIN32_LEAN_AND_MEAN")
add_compile_definitions("_CRT_SECURE_NO_WARNINGS" "NOMINMAX" "WIN32_LEAN_AND_MEAN")

if(MSVC)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /LTCG /OPT:REF,ICF /GUARD:NO")
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# HorseMenu
# Terminus (formerly HorseMenu)

A mod menu for Red Dead Redemption 2 and Red Dead Online published by Rockstar Games. Strictly for educational purposes.

## How to use
Use a popular injector (FateInjector/Xenos/Etc.) and inject into rdr2.exe
Use a popular injector (Xenos/Extreme Injector/Etc.) and inject into rdr2.exe

(INSERT) Open/Close the menu

Expand Down
2 changes: 1 addition & 1 deletion cmake/rdr-classes.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ message(STATUS "RDR-Classes")
FetchContent_Declare(
RDR-Classes
GIT_REPOSITORY https://github.com/YimMenu/RDR-Classes.git
GIT_TAG a61459d3b100408f736f32046ed2545dc729e617
GIT_TAG 30ffb972079e1f61b7035d2dfc23d2ce642e7513
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(RDR-Classes)
Expand Down
1 change: 1 addition & 0 deletions src/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace YimMenu

using namespace std::chrono_literals;
using namespace std::string_literals;
using namespace std::string_view_literals;

extern std::atomic<bool> g_Running;
extern HINSTANCE g_DllInstance;
Expand Down
2 changes: 1 addition & 1 deletion src/core/commands/Commands.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ namespace YimMenu
return reinterpret_cast<T*>(GetInstance().GetCommandImpl(hash));
}

static std::unordered_map<joaat_t, Command*> GetCommands()
static std::unordered_map<joaat_t, Command*>& GetCommands()
{
return GetInstance().m_Commands;
};
Expand Down
61 changes: 34 additions & 27 deletions src/core/commands/HotkeySystem.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "HotkeySystem.hpp"

#include "game/rdr/Natives.hpp" // TODO: game import in core
#include "game/backend/FiberPool.hpp" // TODO: yet another game import in core
// we should migrate the FiberPool to core eventually
#include "game/backend/ScriptMgr.hpp"
#include "Commands.hpp"
#include "LoopedCommand.hpp"
Expand All @@ -16,12 +16,12 @@ namespace YimMenu

void HotkeySystem::RegisterCommands()
{
auto Commands = Commands::GetCommands();
auto& cmds = Commands::GetCommands();

for (auto [Hash, Command] : Commands)
for (auto& [hash, cmd] : cmds)
{
CommandLink link;
m_CommandHotkeys.insert(std::make_pair(Command->GetHash(), link));
m_CommandHotkeys.insert(std::make_pair(hash, link));
}

LOG(INFO) << "Registered " << m_CommandHotkeys.size() << " commands";
Expand Down Expand Up @@ -64,54 +64,61 @@ namespace YimMenu
}

// Meant to be called in a loop
void HotkeySystem::CreateHotkey(std::vector<int>& Hotkey)
void HotkeySystem::CreateHotkey(std::vector<int>& chain)
{
static auto IsKeyUnique = [this](int Key, std::vector<int> List) -> bool {
static auto is_key_unique = [this](int Key, std::vector<int> List) -> bool {
for (auto& Key_ : List)
if (GetHotkeyLabel(Key_) == GetHotkeyLabel(Key))
return false;

return true;
};

int PressedKey = 0;
ListenAndApply(PressedKey, Hotkey);

int pressed_key = 0;
ListenAndApply(pressed_key, chain);

if (PressedKey > 1)
if (pressed_key > 1)
{
if (IsKeyUnique(PressedKey, Hotkey))
if (is_key_unique(pressed_key, chain))
{
Hotkey.push_back(PressedKey);
chain.push_back(pressed_key);
}
}

MarkStateDirty();
}

void HotkeySystem::FeatureCommandsHotkeyLoop()
void HotkeySystem::Update()
{
for (auto& [Hash, Link] : m_CommandHotkeys)
for (auto& [hash, link] : m_CommandHotkeys)
{
if (Link.Hotkey.empty() || Link.Listening)
if (link.m_Chain.empty() || link.m_BeingModified)
continue;

bool AllKeysPressed = true;
bool all_keys_pressed = true;

for (auto HotkeyModifier : Link.Hotkey)
for (auto modifier : link.m_Chain)
{
if (!(GetAsyncKeyState(HotkeyModifier) & 0x8000))
if (!(GetAsyncKeyState(modifier) & 0x8000))
{
AllKeysPressed = false;
all_keys_pressed = false;
}
}

if (AllKeysPressed && GetForegroundWindow() == *Pointers.Hwnd && std::chrono::system_clock::now() - m_LastHotkeyTriggerTime > 100ms)
if (all_keys_pressed && std::chrono::system_clock::now() - m_LastHotkeyTriggerTime > 100ms)
{
auto Command = Commands::GetCommand(Hash);
if (Command)
auto command = Commands::GetCommand(hash);
if (command)
{
Command->Call();
// TODO: this is the only way I can prevent chat from blocking the main loop while keeping everything else fast
if (hash != "chathelper"_J)
command->Call();
else
{
FiberPool::Push([command] {
command->Call();
});
}
}
m_LastHotkeyTriggerTime = std::chrono::system_clock::now();
}
Expand All @@ -122,9 +129,9 @@ namespace YimMenu
{
for (auto& hotkey : m_CommandHotkeys)
{
if (!hotkey.second.Hotkey.empty())
if (!hotkey.second.m_Chain.empty())
{
state[std::to_string(hotkey.first).data()] = hotkey.second.Hotkey;
state[std::to_string(hotkey.first).data()] = hotkey.second.m_Chain;
}
}
}
Expand All @@ -134,7 +141,7 @@ namespace YimMenu
for (auto& [key, value] : state.items())
{
if (m_CommandHotkeys.contains(std::atoi(key.data())))
m_CommandHotkeys[std::atoi(key.data())].Hotkey = value.get<std::vector<int>>();
m_CommandHotkeys[std::atoi(key.data())].m_Chain = value.get<std::vector<int>>();
}
}
}
6 changes: 3 additions & 3 deletions src/core/commands/HotkeySystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace YimMenu
struct CommandLink
{
public:
std::vector<int> Hotkey{};
bool Listening = false;
std::vector<int> m_Chain{};
bool m_BeingModified = false;

CommandLink(){};
};
Expand All @@ -26,7 +26,7 @@ namespace YimMenu
std::string GetHotkeyLabel(int hotkey_modifiers);
void CreateHotkey(std::vector<int>& Hotkey);

void FeatureCommandsHotkeyLoop();
void Update();

virtual void SaveStateImpl(nlohmann::json& state) override;
virtual void LoadStateImpl(nlohmann::json& state) override;
Expand Down
36 changes: 36 additions & 0 deletions src/core/commands/StringCommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "StringCommand.hpp"

namespace YimMenu
{
void StringCommand::OnCall()
{
}

void StringCommand::SaveState(nlohmann::json& value)
{
value = m_StringValue;
}

void StringCommand::LoadState(nlohmann::json& value)
{
m_StringValue = value.get<std::string>();
}

StringCommand::StringCommand(std::string name, std::string label, std::string description, std::string defaultValue) :
Command(name, label, description, 0),
m_StringValue(defaultValue)
{
}

std::string StringCommand::GetString() const
{
return m_StringValue;
}

void StringCommand::SetStringValue(const std::string& value)
{
m_StringValue = value;
OnChange();
MarkDirty();
}
}
25 changes: 25 additions & 0 deletions src/core/commands/StringCommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include "Command.hpp"

namespace YimMenu
{
class StringCommand : public Command
{
protected:
std::string m_StringValue;

virtual void OnChange()
{
}

virtual void OnCall() override;
virtual void SaveState(nlohmann::json& value) override;
virtual void LoadState(nlohmann::json& value) override;

public:
StringCommand(std::string name, std::string label, std::string description, std::string defaultValue = "");

std::string GetString() const;
void SetStringValue(const std::string& value);
};
}
2 changes: 1 addition & 1 deletion src/core/frontend/manager/UIManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace YimMenu
}
ImGui::EndChild();

ImGui::Text("HorseMenu");
ImGui::Text("Terminus");

pos.y -= 28;
ImGui::SetCursorPos(ImVec2(pos.x + 130, pos.y));
Expand Down
7 changes: 7 additions & 0 deletions src/core/frontend/widgets/imgui_colors.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

namespace ImGui
{
// https://easyrgb.com/en/convert.php
struct Colors
{
// CSS colors
inline static ImColor AliceBlue{0.94f, 0.97f, 1.0f, 1.0f}; // ARGB: #FFF0F8FF
inline static ImColor AntiqueWhite{0.98f, 0.92f, 0.84f, 1.0f}; // ARGB: #FFFAEBD7
inline static ImColor Aqua{0.0f, 1.0f, 1.0f, 1.0f}; // ARGB: #FF00FFFF
Expand Down Expand Up @@ -146,5 +148,10 @@ namespace ImGui
inline static ImColor WhiteSmoke{0.96f, 0.96f, 0.96f, 1.0f}; // ARGB: #FFF5F5F5
inline static ImColor Yellow{1.0f, 1.0f, 0.0f, 1.0f}; // ARGB: #FFFFFF00
inline static ImColor YellowGreen{0.60f, 0.80f, 0.20f, 1.0f}; // ARGB: #FF9ACD32

// others
inline static ImColor Freemode{0.17647f, 0.43137f, 0.72549, 1.0f}; // ARGB: #FF2D6EB9
inline static ImColor IngameBg{0.0f, 0.0f, 0.0f, 0.54901f}; // ARGB: #8C000000
inline static ImColor DisabledText{0.0f, 0.0f, 0.0f, 0.8f}; // ARGB: #CC000000
};
}
4 changes: 4 additions & 0 deletions src/core/hooking/Hooking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace YimMenu
BaseHook::Add<Hooks::Script::RunScriptThreads>(new DetourHook("RunScriptThreads", Pointers.RunScriptThreads, Hooks::Script::RunScriptThreads));
BaseHook::Add<Hooks::Script::InitNativeTables>(new DetourHook("InitNativeTables", Pointers.InitNativeTables, Hooks::Script::InitNativeTables));
BaseHook::Add<Hooks::Script::ScriptVM>(new DetourHook("ScriptVM", Pointers.ScriptVM, Hooks::Script::ScriptVM));
BaseHook::Add<Hooks::Script::RegisterCompappNatives>(new DetourHook("RegisterCompappNatives", Pointers.RegisterCompappNatives, Hooks::Script::RegisterCompappNatives));

BaseHook::Add<Hooks::Protections::HandleNetGameEvent>(new DetourHook("HandleNetGameEvent", Pointers.HandleNetGameEvent, Hooks::Protections::HandleNetGameEvent));
BaseHook::Add<Hooks::Protections::HandleCloneCreate>(new DetourHook("HandleCloneCreate", Pointers.HandleCloneCreate, Hooks::Protections::HandleCloneCreate));
Expand Down Expand Up @@ -86,6 +87,9 @@ namespace YimMenu

BaseHook::Add<Hooks::Misc::ThrowFatalError>(new DetourHook("ThrowFatalError", Pointers.ThrowFatalError, Hooks::Misc::ThrowFatalError));
BaseHook::Add<Hooks::Misc::IsAnimSceneInScope>(new DetourHook("IsAnimSceneInScope", Pointers.IsAnimSceneInScope, Hooks::Misc::IsAnimSceneInScope));
BaseHook::Add<Hooks::Misc::GetTextLabel>(new DetourHook("GetTextLabel", Pointers.GetTextLabel, Hooks::Misc::GetTextLabel));
BaseHook::Add<Hooks::Misc::CheckConditionIsMale>(new DetourHook("CheckConditionIsMale", Pointers.CheckConditionIsMale, Hooks::Misc::CheckConditionIsMale));
BaseHook::Add<Hooks::Misc::CheckConditionIsFemale>(new DetourHook("CheckConditionIsFemale", Pointers.CheckConditionIsFemale, Hooks::Misc::CheckConditionIsFemale));

BaseHook::Add<Hooks::Info::NetworkRequest>(new DetourHook("NetworkReqeust", Pointers.NetworkRequest, Hooks::Info::NetworkRequest));

Expand Down
Loading

0 comments on commit 8727e0b

Please sign in to comment.