How YimMenuV2 Reads and Writes Named and Packed Player Stats
YimMenuV2 reads and writes player stats by performing a binary search on a sorted array of stat mappings in CStatsMgr, returning a pointer to the packed sStatData structure where values are modified directly and marked dirty for synchronization.
The YimMenuV2 stats system provides a high-performance interface for manipulating Grand Theft Auto V player statistics through both Lua scripts and native C++ code. Understanding how this menu handles named and packed player stats requires examining the CStatsMgr class and its binary search implementation. This article breaks down the exact mechanism used to read and write stat values based on the actual source code in the YimMenu/YimMenuV2 repository.
The Architecture of YimMenuV2's Stats System
Named Stats vs. Packed Stats
In YimMenuV2, named stats are identified by their Jenkins hash (e.g., 0x123ABC45 for MP0_CASH), while packed stats refer to the concrete memory structures (sStatData) that store the actual values. The system maintains a clear separation between the symbolic hash identifiers used by scripts and the raw data storage accessed by the game engine.
The CStatsMgr Singleton
The CStatsMgr class serves as the central authority for all stat operations. It stores a pre-sorted array of sStatMap entries in m_Stats, where each entry maps a hash ID to a pointer to its corresponding sStatData. This array is populated at startup by src/types/stats/CStatsMpCharacterMappingData.cpp, ensuring all character-specific stats are indexed before any queries occur.
How Stat Lookup Works: Binary Search in CStatsMgr
When the menu needs to access a stat, it calls CStatsMgr::GetStat(uint32_t statHash) defined in src/types/stats/CStatsMgr.cpp. This function executes a binary search (bsearch) over the sorted m_Stats array to locate the matching sStatMap entry. If found, the function returns the sStatData* pointer stored in that entry; otherwise, it returns nullptr.
The binary search implementation provides O(log n) lookup complexity, which is critical for real-time modifications that may query hundreds of stats per tick without impacting frame rates.
The sStatMap and sStatData Structures
The sStatMap structure acts as a bridge between names and data, containing the stat hash and a pointer to its sStatData. The sStatData structure holds the actual values in union-like fields (intValue, floatValue, boolValue) along with a dirty boolean flag that signals the game's native sync system to propagate changes to Rockstar's servers.
Reading Player Stats
Lua API Implementation
The Lua binding layer in src/game/scripting/libraries/Stats.cpp exposes functions like Stats.GET_INT(hash) and Stats.GET_FLOAT(hash). These wrappers call CStatsMgr::GetStat(hash) to retrieve the sStatData*, then read the appropriate field and push the value to the Lua stack.
Writing Player Stats
Writing stats follows the same lookup path but adds modification logic. When a script calls Stats.SET_INT(hash, value), the system retrieves the sStatData* via GetStat, overwrites the intValue field, and sets the dirty flag to true. This marks the stat for synchronization without immediately triggering network traffic, allowing batch modifications.
Dirty Flag Synchronization
The dirty flag inside sStatData is crucial for performance. Instead of calling native Rockstar functions (STAT_SET_INT, etc.) immediately on every write, YimMenuV2 modifies the memory directly and relies on the game's existing stat sync mechanism to detect changes via the dirty flag. This approach minimizes overhead and prevents excessive native call overhead.
Practical Code Examples
Reading an Integer Stat (Player Cash)
local CASH_HASH = 0x123ABC45 -- hash for "MP0_CASH"
local cash = Stats.GET_INT(CASH_HASH)
print("Current cash:", cash)
Implementation path: Stats.GET_INT → CStatsMgr::GetStat(hash) → data->intValue.
Writing a Float Stat (Player Stamina)
local STAMINA_HASH = 0x98765432
Stats.SET_FLOAT(STAMINA_HASH, 100.0) -- max out stamina
Implementation path: Stats.SET_FLOAT → CStatsMgr::GetStat(hash) → data->floatValue = 100.0 → data->dirty = true.
Batch Modifying Packed Stats via C++
For direct memory manipulation of multiple fields, access the packed structure directly:
sStatData* stats = CStatsMgr::GetStat(customHash);
if (stats) {
stats->intValue = 42;
stats->floatValue = 3.14f;
stats->dirty = true; // mark for sync
}
This pattern appears in src/types/stats/CStatsMgr.cpp where the binary search returns the raw pointer for in-place modification.
Key Source Files and Implementation Details
| Component | Description | Source Path |
|---|---|---|
CStatsMgr.cpp |
Core manager implementing binary search lookup (GetStat) over the sorted m_Stats array. |
src/types/stats/CStatsMgr.cpp |
Stats.cpp |
Lua library exposing GET_* and SET_* functions, handling type conversion and dirty flags. |
src/game/scripting/libraries/Stats.cpp |
CStatsMpCharacterMappingData.cpp |
Initializes the stat mapping table for multiplayer characters at startup. | src/types/stats/CStatsMpCharacterMappingData.cpp |
Summary
- YimMenuV2 uses
CStatsMgrwith a binary search (bsearch) over a sortedm_Statsarray to resolve named stat hashes to packedsStatDatapointers in O(log n) time. - Reads return values directly from
sStatDatafields (intValue,floatValue,boolValue). - Writes modify the packed structure in-place and set a
dirtyflag to trigger the game's native synchronization system. - Source files
src/types/stats/CStatsMgr.cppandsrc/game/scripting/libraries/Stats.cppcontain the core implementation and Lua bindings respectively.
Frequently Asked Questions
What is the time complexity of stat lookups in YimMenuV2?
Stat lookups operate in O(log n) time complexity due to the binary search implementation in CStatsMgr::GetStat. The m_Stats array is pre-sorted at initialization, ensuring consistent performance even with thousands of registered stats.
How does YimMenuV2 handle stat synchronization with Rockstar's servers?
Rather than calling native functions immediately, YimMenuV2 sets a dirty flag in the sStatData structure when values change. The game's internal stat sync mechanism detects these flags and handles network propagation, reducing overhead from excessive native calls.
What is the difference between named stats and packed stats in YimMenuV2?
Named stats refer to the Jenkins hash identifiers (e.g., 0x123ABC45) used to look up values, while packed stats are the concrete sStatData memory structures containing the actual values and dirty flags. The CStatsMgr class bridges these two layers.
Where are the stat mappings initialized in YimMenuV2?
The mapping table is populated during startup by src/types/stats/CStatsMpCharacterMappingData.cpp, which inserts multiplayer character stats into the sorted m_Stats array before any Lua scripts or menu functions attempt to access them.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →