Skip to content

Commit

Permalink
Merge pull request #100 from MafiaHub/racing-ui
Browse files Browse the repository at this point in the history
Racing UI API
  • Loading branch information
Segfaultd authored Jan 12, 2025
2 parents 9d0d06f + b265c6c commit 32a85fb
Show file tree
Hide file tree
Showing 12 changed files with 321 additions and 3 deletions.
3 changes: 3 additions & 0 deletions code/client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,16 @@ set(MAFIAMP_SDK_FILES
srC/sdk/entities/c_human2.cpp
src/sdk/entities/c_player_2.cpp
src/sdk/entities/c_vehicle.cpp
src/sdk/c_inventory_wrapper.cpp
src/sdk/mafia/database/c_ui_database.cpp
src/sdk/mafia/framework/director/c_game_director.cpp
src/sdk/mafia/framework/c_mafia_dbs.cpp
src/sdk/mafia/framework/c_mafia_framework.cpp
src/sdk/mafia/framework/c_vehicles_database.cpp
src/sdk/mafia/streaming/c_actors_slot_wrapper.cpp
src/sdk/mafia/streaming/c_slot_wrapper.cpp
src/sdk/mafia/streaming/c_streaming_module.cpp
src/sdk/mafia/ui/hud/race_xbin.cpp
src/sdk/mafia/ui/menu/c_save_menu.cpp
src/sdk/mafia/ui/navigation/c_navigation.cpp
src/sdk/mafia/ui/support/c_fader.cpp
Expand Down
60 changes: 60 additions & 0 deletions code/client/src/core/ui/devs/debug_world.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
#include "sdk/entities/c_car.h"
#include "sdk/entities/c_player_2.h"
#include "sdk/entities/c_vehicle.h"
#include "sdk/mafia/database/c_ui_database.h"
#include "sdk/mafia/framework/c_mafia_dbs.h"
#include "sdk/mafia/ui/c_game_gui_2_module.h"
#include "sdk/mafia/ui/hud/race_xbin.h"
#include "sdk/mafia/ui/hud/c_hud_controller.h"
#include "sdk/ue/game/traffic/c_streaming_traffic_module.h"
#include "sdk/ue/gfx/environmenteffects/c_gfx_environment_effects.h"

Expand Down Expand Up @@ -242,6 +246,62 @@ namespace MafiaMP::Core::UI::Devs {
streamingTrafficModule->SetMaxHumanElements(m_iMaxHumanElements);
}
}

if (ImGui::CollapsingHeader("Racing")) {
SDK::mafia::ui::C_GameGUI2Module *GameGuiModule = SDK::mafia::ui::GetGameGui2Module();
SDK::ue::C_WeakPtr<SDK::ue::sys::sodb::C_DatabaseInterface> result = GameGuiModule->GetDatabase();
if (SDK::mafia::database::C_UIDatabase *database = reinterpret_cast<SDK::mafia::database::C_UIDatabase *>(result.Get())) {
SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = database->GetHUDTable();

ImGui::PushItemWidth(75.0f);

// VISIBLE
ImGui::Text("Racing HUDElement Visibility");
ImGui::Checkbox("##racing_visible_hudtable", &hudTable->m_bRacingVisible);

ImGui::Spacing();

// LAPS
ImGui::Text("Current Laps / Num Laps");
ImGui::InputScalar("##total_laps_hudtable", ImGuiDataType_U16, &hudTable->m_uCurLap);
ImGui::SameLine();
ImGui::InputScalar("##curent_lap_hudtable", ImGuiDataType_U16, &hudTable->m_uTotalLaps);

ImGui::Spacing();

// POSITIONS
ImGui::Text("Current Position / Max Position");
ImGui::InputScalar("##total_position_hudtable", ImGuiDataType_U16, &hudTable->m_uCurPosition);
ImGui::SameLine();
ImGui::InputScalar("##curent_position_hudtable", ImGuiDataType_U16, &hudTable->m_uTotalPositions);

ImGui::Spacing();

// CHECKPOINTS
ImGui::Text("Current Checkpoint / Max Checkpoints");
ImGui::InputScalar("##total_checkpoint_hudtable", ImGuiDataType_U16, &hudTable->m_uCurCheckpoint);
ImGui::SameLine();
ImGui::InputScalar("##curent_checkpoint_hudtable", ImGuiDataType_U16, &hudTable->m_uTotalCheckpoints);

ImGui::Spacing();

// UNKNOWN
ImGui::Text("Current UNKNOWN / Max UNKNOWN");
ImGui::InputScalar("##total_UNKNOWN_hudtable", ImGuiDataType_U16, &hudTable->m_uUnknown1);
ImGui::SameLine();
ImGui::InputScalar("##curent_UNKNOWN_hudtable", ImGuiDataType_U16, &hudTable->m_uUnknown2);

ImGui::Spacing();

// COUNTDOWN
ImGui::Text("Countdown");
ImGui::SameLine();
ImGui::TextDisabled("(3, 2, 1 for lights, 0 for GO). Sound is played automatically");
ImGui::InputScalar("##countdown_hudtable", ImGuiDataType_U8, &hudTable->m_uCountdown);

ImGui::PopItemWidth();
}
}
};

CreateUIWindow("World debug", windowContent, &_open);
Expand Down
1 change: 1 addition & 0 deletions code/client/src/sdk/mafia/database/c_ui_database.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "c_ui_database.h"
39 changes: 39 additions & 0 deletions code/client/src/sdk/mafia/database/c_ui_database.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include "../../ue/sys/sodb/c_database_interface.h"

namespace SDK {
namespace mafia::database {
class C_UIDatabase: public ue::sys::sodb::C_DatabaseInterface {
public:
class C_HUDTable {
public:
uint8_t pad0[0x1E]; // 0000 - 001E
bool m_bRacingVisible = false; // 001E - 001F
uint8_t pad1[0x3]; // 001F - 0022
uint8_t pad2[0x346]; // 0022 - 0368
float m_fElapsedTime = 0.0f; // 0368 - 036C
float m_fTargetTime = 0.0f; // 036C - 0370
uint16_t m_uCurCheckpoint = 0; // 0370 - 0372
uint16_t m_uTotalCheckpoints = 0; // 0372 - 0374
uint16_t m_uCurPosition = 0; // 0374 - 0376
uint16_t m_uTotalPositions = 0; // 0376 - 0378
uint16_t m_uUnknown1 = 0; // 0378 - 037C
uint16_t m_uUnknown2 = 0; // 0378 - 037C
uint16_t m_uCurLap = 0; // 037C - 037E
uint16_t m_uTotalLaps = 0; // 037E - 0380
uint8_t m_uCountdown = 0; // 0380 - 0381
};

C_HUDTable *GetHUDTable() const {
return m_pHUDTable;
}

private:
// NB: Atleast 0x38 is part of C_DatabaseInterface
// Since m_pHUDTable is at 0x20, that could actually be part of base class
uint8_t pad0[0x20]; // 0000 - 0020
C_HUDTable *m_pHUDTable = nullptr; // 0020 - 0028
};
}; // namespace mafia::database
}; // namespace SDK
5 changes: 5 additions & 0 deletions code/client/src/sdk/mafia/ui/c_game_gui_2_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ namespace SDK {
hook::this_call(gPatterns.C_GameGUI2Module__SendMessageMovie, this, title, msg, varArgs, unk2);
}

ue::C_WeakPtr<ue::sys::sodb::C_DatabaseInterface> C_GameGUI2Module::GetDatabase() {
ue::C_WeakPtr<ue::sys::sodb::C_DatabaseInterface> database;
return hook::this_call<ue::C_WeakPtr<ue::sys::sodb::C_DatabaseInterface> &>(gPatterns.C_GameGUI2Module__GetDatabase, this, database);
}

C_GameGUI2Module *C_GameGUI2Module::GetInstance() {
return *reinterpret_cast<C_GameGUI2Module **>(gPatterns.C_GameGUI2Module__Instance);
}
Expand Down
4 changes: 4 additions & 0 deletions code/client/src/sdk/mafia/ui/c_game_gui_2_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "support/c_fader.h"

#include "../../ue/c_variant.h"
#include "../../ue/c_weak_ptr.h"
#include "../../ue/sys/sodb/c_database_interface.h"

#include <cstdint>

Expand Down Expand Up @@ -40,6 +42,8 @@ namespace SDK {
return *reinterpret_cast<mafia::ui::menu::C_MainMenu **>((uint64_t)this + 0x0C0);
}

ue::C_WeakPtr<ue::sys::sodb::C_DatabaseInterface> GetDatabase();

static C_GameGUI2Module *GetInstance();
};

Expand Down
33 changes: 33 additions & 0 deletions code/client/src/sdk/mafia/ui/hud/c_hud_controller.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
#pragma once

#include "../../../patterns.h"

namespace SDK {
namespace mafia::ui::hud {

class C_RaceTimer {
public:

// This starts C_RaceManager!
// If you do not wish to use C_RaceManager, use mafia::ui::hud::RaceXBin instead!
void SetVisible(const bool visible) {
hook::this_call(gPatterns.C_RaceTimer_SetVisible, this, visible);
}

// This starts C_RaceManager!
// If you do not wish to use C_RaceManager, Use mafia::ui::hud::RaceXBin instead!
void StartRace(const uint32_t numCheckpoints, const float targetTime, const uint32_t numLaps) {
hook::this_call(gPatterns.C_RaceTimer_StartRace, this, numCheckpoints, targetTime, numLaps);
}

private:
void *m_pVtable = nullptr; // 0000 - 0008
void *m_pUnk0 = nullptr; // 0008 - 0010
float m_fTimer = 0.0f; // 0010 - 0014
uint32_t m_uCurrentCheckpoint = 0; // 0014 - 0018
uint32_t m_uCurrentLap = 0; // 0018 - 001C
};

class C_HudController {
public:
C_RaceTimer *GetRacingTimer() {
return m_pRaceTimer;
}

private:
char pad0[0x5A8]; // 0000 - 05A8
C_RaceTimer *m_pRaceTimer = nullptr; // 05A8 - 05B0
};
} // namespace mafia::ui::hud
} // namespace SDK
82 changes: 82 additions & 0 deletions code/client/src/sdk/mafia/ui/hud/race_xbin.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "race_xbin.h"

#include "../../database/c_ui_database.h"
#include "../c_game_gui_2_module.h"

namespace RaceXBinUtils
{
// Handy little utility function to fetch the HUDTable, for the Racing XBin.
SDK::mafia::database::C_UIDatabase::C_HUDTable *GetHUDTable() {

// Fetch database
SDK::mafia::ui::C_GameGUI2Module *GameGuiModule = SDK::mafia::ui::GetGameGui2Module();
SDK::ue::C_WeakPtr<SDK::ue::sys::sodb::C_DatabaseInterface> result = GameGuiModule->GetDatabase();

// need to cast to C_UIDatabase
// TODO: Feels like this should be dynamic_cast, rather than reinterpret_cast
if (SDK::mafia::database::C_UIDatabase *database = reinterpret_cast<SDK::mafia::database::C_UIDatabase *>(result.Get())) {
return database->GetHUDTable();
}

return nullptr;
}
}

namespace SDK {
namespace mafia::ui::hud {

void RaceXBin::SetVisible(const bool visibility) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_bRacingVisible = visibility;
}
}

void RaceXBin::SetTargetTime(const float targetTime) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_fTargetTime = targetTime;
}
}

void RaceXBin::SetPosition(const uint16_t currentPosition) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_uCurPosition = currentPosition;
}
}

void RaceXBin::SetPositionTotal(const uint16_t totalPositions) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_uTotalPositions = totalPositions;
}
}

void RaceXBin::SetLaps(const uint16_t currentLap) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_uCurLap = currentLap;
}
}

void RaceXBin::SetLapsTotal(const uint16_t totalLaps) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_uTotalLaps = totalLaps;
}
}

void RaceXBin::SetCheckpoints(const uint16_t currentCheckpoint) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_uCurCheckpoint = currentCheckpoint;
}
}

void RaceXBin::SetCheckpointsTotal(const uint16_t totalCheckpoint) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_uTotalCheckpoints = totalCheckpoint;
}
}

void RaceXBin::SetCountdown(const uint8_t countdown) {
if (SDK::mafia::database::C_UIDatabase::C_HUDTable *hudTable = RaceXBinUtils::GetHUDTable()) {
hudTable->m_uCountdown = countdown;
}
}
} // namespace mafia::ui::hud
} // namespace SDK
77 changes: 77 additions & 0 deletions code/client/src/sdk/mafia/ui/hud/race_xbin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#pragma once

#include <stdint.h>

namespace SDK {
namespace mafia::ui::hud {

/**
* Handy structure which provides an API to update the Racing HUD Element.
* Note that there are some discrepancies with the executable code however
* all functionality should be the same.
*/
class RaceXBin {
public:

/**
* Set the visibility of the Racing HUD Element.
* @param bVisibility - Should the HUD Element be visible
*/
static void SetVisible(const bool visiblity);

/**
* Set the Target Time on the Racing HUD Element.
* Note that this may not have an effect (eg. appear on the HUD)
* @param InTargetTime - Target Time to show on the HUD
*/
static void SetTargetTime(const float targetTime);

/**
* Set the current Position on the Racing HUD Element.
* Note that 'Total Positions' may need to be set before this to have an effect.
* @param InPosition - The current position out of Total Positions
*/
static void SetPosition(const uint16_t currentPosition);

/**
* Set the max amount of Positions on the Racing HUD Element
* @param InTotalPosition - Max number of positions
*/
static void SetPositionTotal(const uint16_t totalPositions);

/**
* Set the current Lap on the Racing HUD Element.
* Note that 'Total Laps' may need to be set before this to have an effect.
* @param InLaps - The current Lap out of Total Laps
*/
static void SetLaps(const uint16_t currentLap);

/**
* Set the number of Laps on the Racing HUD Element
* @param InTotalPosition - Number of Laps
*/
static void SetLapsTotal(const uint16_t totalLaps);

/**
* Set the current Checkpoint on the Racing HUD Element.
* Note that 'Total Checkpoints' may need to be set before this to have an effect.
* @param InPosition - The current Checkpoint out of Total Checkpoints
*/
static void SetCheckpoints(const uint16_t currentCheckpoint);

/**
* Set the max amount of Checkpoints on the Racing HUD Element
* @param InTotalPosition - Max number of checkpoints
*/
static void SetCheckpointsTotal(const uint16_t totalCheckpoints);

/**
* Set the countdown. Max is 3, Minimum is 0.
* The HUD automatically plays the noise when the countdown is updated.
* The caller will have to manage a timer for the countdown.
* @param InCountdown - Current step in the Countdown
*/
static void SetCountdown(const uint8_t countdown);
};
} // namespace mafia::ui::hud
} // namespace SDK
5 changes: 5 additions & 0 deletions code/client/src/sdk/patterns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ namespace SDK {
uint64_t C_GameGUI2Module = hook::get_opcode_address("E8 ? ? ? ? 41 8D 56 11");
uint8_t *C_GameGUI2Module_Bytes = reinterpret_cast<uint8_t *>(C_GameGUI2Module);

gPatterns.C_GameGUI2Module__GetDatabase = reinterpret_cast<uint64_t>(hook::get_pattern("48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8D B9 ? ? ? ? 48 8B F2"));
gPatterns.C_GameGUI2Module__GetGameGui2Module = hook::get_opcode_address<uint64_t>("E8 ? ? ? ? 40 80 F6 01");
gPatterns.C_GameGUI2Module__Instance = reinterpret_cast<uint64_t>(C_GameGUI2Module_Bytes + *(int32_t *)(C_GameGUI2Module_Bytes + 3) + 7);
gPatterns.C_GameGUI2Module__SendHUDSimpleBooleanMessage = hook::get_opcode_address<uint64_t>("E8 ? ? ? ? 49 8B 97 ? ? ? ? 4C 8D 05 ? ? ? ?");
Expand Down Expand Up @@ -312,6 +313,10 @@ namespace SDK {

// C_Quat
gPatterns.C_Quat__SetDir = hook::get_opcode_address("E8 ? ? ? ? F3 44 0F 59 5D ?");

// C_RaceTimer
gPatterns.C_RaceTimer_SetVisible = reinterpret_cast<uint64_t>(hook::get_pattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 56 41 57 48 83 EC ? 0F B6 F2"));
gPatterns.C_RaceTimer_StartRace = reinterpret_cast<uint64_t>(hook::get_pattern("48 89 5C 24 ? 57 48 83 EC ? 48 8B F9 C7 41 ? ? ? ? ? 41 0F B7 C9"));

// C_SceneObject
gPatterns.C_SceneObject__SetTransform = reinterpret_cast<uint64_t>(hook::get_pattern("40 53 48 83 EC ? 48 8D 41 ? 48 8B D9 0F 10 02"));
Expand Down
Loading

0 comments on commit 32a85fb

Please sign in to comment.