mirror of
https://github.com/YimMenu/YimMenuV2.git
synced 2026-10-10 03:43:15 +08:00
Random Event Fixes & Improvements (#170)
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
#include "core/backend/ScriptMgr.hpp"
|
||||
#include "core/frontend/Notifications.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/backend/Tunables.hpp"
|
||||
#include "game/gta/Scripts.hpp"
|
||||
#include "game/gta/ScriptFunction.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
#include "types/script/globals/GPBD_FM_2.hpp"
|
||||
#include "types/script/globals/GSBD_RandomEvents.hpp"
|
||||
#include "types/script/locals/FMRandomEvents.hpp"
|
||||
#include "types/script/ScriptEvent.hpp"
|
||||
@@ -66,7 +68,7 @@ namespace YimMenu::Submenus
|
||||
"Community Outreach"
|
||||
};
|
||||
|
||||
static constexpr std::array RandomEventScripts = {
|
||||
static constexpr std::array randomEventScripts = {
|
||||
"fm_content_drug_vehicle"_J,
|
||||
"fm_content_movie_props"_J,
|
||||
"fm_content_golden_gun"_J,
|
||||
@@ -90,14 +92,66 @@ namespace YimMenu::Submenus
|
||||
"fm_content_community_outreach"_J
|
||||
};
|
||||
|
||||
static YimMenu::ScriptFunction getNumFMMCVariations("GMFV", "freemode"_J, "5D ? ? ? 01 72 02 39 04", 1, true);
|
||||
static constexpr std::array randomEventCooldowns = {
|
||||
"SUM22_RE_DRUG_VEHICLE_INACTIVE_TIME"_J,
|
||||
"SUM22_RE_MOVIE_PROPS_INACTIVE_TIME"_J,
|
||||
"SUM22_RE_GOLDEN_GUN_INACTIVE_TIME"_J,
|
||||
"SUM22_RE_VEHICLE_LIST_INACTIVE_TIME"_J,
|
||||
"STANDARDCONTROLLERVOLUME_COOLDOWN"_J,
|
||||
"STANDARDTARGETTINGTIME_COOLDOWN"_J,
|
||||
"SSP2_COOLDOWN"_J,
|
||||
"SUM22_RE_SMUGGLER_TRAIL_INACTIVE_TIME"_J,
|
||||
"NC_SOURCE_TRUCK_COOLDOWN"_J,
|
||||
"SUM22_RE_SMUGGLER_PLANE_INACTIVE_TIME"_J,
|
||||
"SUM22_RE_CRIME_SCENE_INACTIVE_TIME"_J,
|
||||
"SUM22_RE_METAL_DETECTOR_INACTIVE_TIME"_J,
|
||||
"XM22_RE_GANG_CONVOY_INACTIVE_TIME"_J,
|
||||
"XM22_RE_ROBBERY_INACTIVE_TIME"_J,
|
||||
"STANDARD_KEYBIND_COOLDOWN"_J,
|
||||
"XM22_RE_BANK_SHOOTOUT_INACTIVE_TIME"_J,
|
||||
(joaat_t)NULL,
|
||||
"STANDARDCONTROLLERVOLUME_COOLDOWN"_J,
|
||||
"SUM23_RE_GHOSTHUNT_INACTIVE_TIME"_J,
|
||||
"XMAS_TRUCK_INACTIVE_TIME"_J,
|
||||
"RE_COMMUNITY_OUTREACH_INACTIVE_TIME"_J
|
||||
};
|
||||
|
||||
static constexpr std::array randomEventAvailabilities = {
|
||||
"SUM22_RE_DRUG_VEHICLE_AVAILABLE_TIME"_J,
|
||||
"SUM22_RE_MOVIE_PROPS_AVAILABLE_TIME"_J,
|
||||
"SUM22_RE_GOLDEN_GUN_AVAILABLE_TIME"_J,
|
||||
"SUM22_RE_VEHICLE_LIST_AVAILABLE_TIME"_J,
|
||||
"STANDARDCONTROLLERVOLUME_AVAILABILITY"_J,
|
||||
"STANDARDTARGETTINGTIME_AVAILABILITY"_J,
|
||||
"SSP2_AVAILABILITY"_J,
|
||||
"SUM22_RE_SMUGGLER_TRAIL_AVAILABLE_TIME"_J,
|
||||
"NC_SOURCE_TRUCK_AVAILABILITY"_J,
|
||||
"SUM22_RE_SMUGGLER_PLANE_AVAILABLE_TIME"_J,
|
||||
"SUM22_RE_CRIME_SCENE_AVAILABLE_TIME"_J,
|
||||
"SUM22_RE_METAL_DETECTOR_AVAILABLE_TIME"_J,
|
||||
"XM22_RE_GANG_CONVOY_AVAILABLE_TIME"_J,
|
||||
"XM22_RE_ROBBERY_AVAILABLE_TIME"_J,
|
||||
"STANDARD_KEYBIND_AVAILABILITY"_J,
|
||||
"XM22_RE_BANK_SHOOTOUT_AVAILABLE_TIME"_J,
|
||||
(joaat_t)NULL,
|
||||
"STANDARDCONTROLLERVOLUME_AVAILABILITY"_J,
|
||||
"SUM23_RE_GHOSTHUNT_AVAILABLE_TIME"_J,
|
||||
"XMAS_TRUCK_AVAILABLE_TIME"_J,
|
||||
"RE_COMMUNITY_OUTREACH_AVAILABLE_TIME"_J
|
||||
};
|
||||
|
||||
static ScriptFunction getNumFMMCVariations("GNFMMCV", "freemode"_J, "5D ? ? ? 01 72 02 39 04", 1, true);
|
||||
static GPBD_FM_2* GPBDFM2 = nullptr;
|
||||
static GSBD_RandomEvents* GSBDRandomEvents = nullptr;
|
||||
static RANDOM_EVENTS_FREEMODE_DATA* FMRandomEvents = nullptr;
|
||||
static eRandomEvent selectedEvent = DRUG_VEHICLE;
|
||||
static int selectedSubvariation = 0;
|
||||
static int numSubVariations = 30;
|
||||
static int numSubvariations = 29;
|
||||
static int setCooldown = 1800000;
|
||||
static int setAvailability = 900000;
|
||||
static bool applyInMinutes = false;
|
||||
|
||||
std::string GetEventTimeLeftStr(int eventTime, int timer)
|
||||
static std::string GetEventTimeLeftStr(int eventTime, int timer)
|
||||
{
|
||||
int timePassed = (*Pointers.NetworkTime - timer) < 0 ? -(*Pointers.NetworkTime - timer) : (*Pointers.NetworkTime - timer);
|
||||
int diff = (eventTime - timePassed);
|
||||
@@ -129,20 +183,53 @@ namespace YimMenu::Submenus
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
static int GetNumLocallyActiveEvents()
|
||||
{
|
||||
int numEvents{};
|
||||
|
||||
for (int event = DRUG_VEHICLE; event < MAX_EVENTS; event++)
|
||||
{
|
||||
if (GPBDFM2->Entries[Self::GetPlayer().GetId()].RandomEventsClientData.EventData[event].State != eRandomEventClientState::INACTIVE)
|
||||
numEvents++;
|
||||
}
|
||||
|
||||
return numEvents;
|
||||
}
|
||||
|
||||
static void ResetEventTunables(eRandomEvent event)
|
||||
{
|
||||
if (event == ARMOURED_TRUCK) // It doesn't have tunables
|
||||
{
|
||||
setCooldown = *ScriptGlobal(262145).At(33719).As<int*>();
|
||||
setAvailability = *ScriptGlobal(262145).At(33720).As<int*>();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Phantom Car's cooldown is actually 2147483647ms if STANDARDTARGETTINGTIME is not enabled
|
||||
setCooldown = *Tunables::GetTunable(randomEventCooldowns[event]).As<int*>();
|
||||
setAvailability = *Tunables::GetTunable(randomEventAvailabilities[event]).As<int*>();
|
||||
}
|
||||
}
|
||||
|
||||
static void OnComboChange()
|
||||
{
|
||||
selectedSubvariation = 0;
|
||||
numSubvariations = getNumFMMCVariations.Call<int>(FMRandomEvents->MissionData.FMMCData[selectedEvent].FMMCType, 0) - 1;
|
||||
ResetEventTunables(selectedEvent);
|
||||
}
|
||||
|
||||
std::shared_ptr<Category> BuildRandomEventsMenu()
|
||||
{
|
||||
auto menu = std::make_shared<Category>("Random Events");
|
||||
|
||||
menu->AddItem(std::make_unique<ImGuiItem>([] {
|
||||
GSBDRandomEvents = nullptr;
|
||||
FMRandomEvents = nullptr;
|
||||
|
||||
GPBDFM2 = GPBD_FM_2::Get();
|
||||
GSBDRandomEvents = GSBD_RandomEvents::Get();
|
||||
if (!GSBDRandomEvents)
|
||||
return ImGui::Text("Freemode global block is not loaded yet.");
|
||||
if (!GPBDFM2 || !GSBDRandomEvents)
|
||||
return ImGui::Text("Freemode global block is not loaded.");
|
||||
|
||||
if (GSBDRandomEvents->InitState != eRandomEventInitState::INITIALIZED)
|
||||
return ImGui::Text("Random Events are not initialized yet.");
|
||||
if (GPBDFM2->Entries[Self::GetPlayer().GetId()].RandomEventsClientData.InitState != eRandomEventClientInitState::INITIALIZED)
|
||||
return ImGui::Text("Random Events are not initialized.");
|
||||
|
||||
if (auto freemode = Scripts::FindScriptThread("freemode"_J))
|
||||
{
|
||||
@@ -176,8 +263,8 @@ namespace YimMenu::Submenus
|
||||
if (ImGui::Selectable(randomEventNames[event], event == selectedEvent))
|
||||
{
|
||||
FiberPool::Push([event] {
|
||||
selectedEvent = (eRandomEvent)event;
|
||||
numSubVariations = getNumFMMCVariations.Call<int>(FMRandomEvents->MissionData.FMMCData[selectedEvent].FMMCType, 0) - 1;
|
||||
selectedEvent = (eRandomEvent)event;
|
||||
OnComboChange();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -187,11 +274,18 @@ namespace YimMenu::Submenus
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
if (ImGui::InputInt(std::format("Select Location (0-{})", numSubVariations).c_str(), &selectedSubvariation))
|
||||
if (ImGui::InputInt(std::format("Select Location (0-{})", numSubvariations).c_str(), &selectedSubvariation))
|
||||
{
|
||||
selectedSubvariation = std::clamp(selectedSubvariation, 0, numSubVariations);
|
||||
selectedSubvariation = std::clamp(selectedSubvariation, 0, numSubvariations);
|
||||
}
|
||||
|
||||
int numActiveEvents = GetNumLocallyActiveEvents();
|
||||
int maxActiveEvents = *Tunables::GetTunable("FMREMAXACTIVATEDEVENTS"_J).As<int*>();
|
||||
if (numActiveEvents >= maxActiveEvents)
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "Active Events: %d/%d", numActiveEvents, maxActiveEvents);
|
||||
else
|
||||
ImGui::Text("Active Events: %d/%d", numActiveEvents, maxActiveEvents);
|
||||
|
||||
if (ImGui::Button("Launch Event"))
|
||||
{
|
||||
FiberPool::Push([] {
|
||||
@@ -214,10 +308,6 @@ namespace YimMenu::Submenus
|
||||
}
|
||||
});
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Force launches the event.");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -230,7 +320,7 @@ namespace YimMenu::Submenus
|
||||
}
|
||||
else if (GSBDRandomEvents->EventData[selectedEvent].State == eRandomEventState::ACTIVE)
|
||||
{
|
||||
ScriptFunction terminateFMContentScript("TFMCS", RandomEventScripts[(int)selectedEvent], "2D 01 05 00 00 5D ? ? ?");
|
||||
ScriptFunction terminateFMContentScript("TFMCS", randomEventScripts[(int)selectedEvent], "2D 01 05 00 00 5D");
|
||||
terminateFMContentScript.Call<void>(false); // Is it ok to do this when we're not host?
|
||||
}
|
||||
else
|
||||
@@ -239,10 +329,6 @@ namespace YimMenu::Submenus
|
||||
}
|
||||
});
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Terminates the event.");
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -267,14 +353,10 @@ namespace YimMenu::Submenus
|
||||
}
|
||||
});
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::SetTooltip("Teleports to the event.");
|
||||
}
|
||||
|
||||
if (GSBDRandomEvents->EventData[selectedEvent].State == eRandomEventState::ACTIVE)
|
||||
{
|
||||
if (auto eventThread = Scripts::FindScriptThread(RandomEventScripts[(int)selectedEvent]))
|
||||
if (auto eventThread = Scripts::FindScriptThread(randomEventScripts[(int)selectedEvent]))
|
||||
{
|
||||
if (auto netComponent = reinterpret_cast<GtaThread*>(eventThread)->m_NetComponent)
|
||||
{
|
||||
@@ -296,8 +378,37 @@ namespace YimMenu::Submenus
|
||||
}
|
||||
|
||||
ImGui::Text("State: %s", GetEventStateString().c_str());
|
||||
ImGui::Text("Location: %d", GSBDRandomEvents->EventData[selectedEvent].Subvariation);
|
||||
ImGui::Text("Trigger Range: %.2f", GSBDRandomEvents->EventData[selectedEvent].TriggerRange); // Default value is 400, it will be updated once the event switches to the available state
|
||||
if (GSBDRandomEvents->EventData[selectedEvent].State == eRandomEventState::INACTIVE)
|
||||
{
|
||||
ImGui::Text("Location: N/A");
|
||||
ImGui::Text("Trigger Range: N/A");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Location: %d", GSBDRandomEvents->EventData[selectedEvent].Subvariation);
|
||||
ImGui::Text("Trigger Range: %.2f", GSBDRandomEvents->EventData[selectedEvent].TriggerRange); // Default value is 400, it will be updated once the event switches to the available state
|
||||
}
|
||||
|
||||
// We should probably put this into a separate group, but I just don't want to do the same safety checks before rendering it
|
||||
ImGui::SeparatorText("Cooldown & Availability");
|
||||
|
||||
ImGui::InputInt("##cooldown", &setCooldown);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Set Cooldown"))
|
||||
{
|
||||
int value = applyInMinutes ? (setCooldown * 60000) : setCooldown;
|
||||
FMRandomEvents->EventData[selectedEvent].InactiveTime = value;
|
||||
}
|
||||
|
||||
ImGui::InputInt("##availability", &setAvailability);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Set Availability"))
|
||||
{
|
||||
int value = applyInMinutes ? (setAvailability * 60000) : setAvailability;
|
||||
FMRandomEvents->EventData[selectedEvent].AvailableTime = value;
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Apply in Minutes", &applyInMinutes);
|
||||
}));
|
||||
|
||||
return menu;
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
#include "../Timer.hpp"
|
||||
#include "../types.hpp"
|
||||
|
||||
enum class eRaceRoundType
|
||||
{
|
||||
NOT_SELECTED = -1,
|
||||
FINISH_FIRST,
|
||||
MOST_POINTS,
|
||||
FASTEST_TIME
|
||||
};
|
||||
|
||||
enum class eRaceFinalRoundType
|
||||
{
|
||||
NOT_SELECTED,
|
||||
HEAD_TO_HEAD
|
||||
};
|
||||
|
||||
enum class eRandomEventClientState
|
||||
{
|
||||
INACTIVE,
|
||||
TRIGGERING, // This is different than the server available state
|
||||
ACTIVE,
|
||||
CLEANUP
|
||||
};
|
||||
|
||||
enum class eRandomEventClientFlags
|
||||
{
|
||||
FORCE_LAUNCH
|
||||
};
|
||||
|
||||
enum class eRandomEventClientInitState
|
||||
{
|
||||
INITIALIZING,
|
||||
INITIALIZED
|
||||
};
|
||||
|
||||
struct GANGOPS_DATA
|
||||
{
|
||||
SCR_INT UNK_0000; // 0
|
||||
SCR_ARRAY<uint64_t, 4> PlayerIndexes; // 1
|
||||
SCR_ARRAY<uint64_t, 4> PlayerRoles; // 6
|
||||
SCR_ARRAY<uint64_t, 4> ArePlayersReady; // 11
|
||||
SCR_ARRAY<uint64_t, 5> PlayerCuts; // 16
|
||||
SCR_INT HighlightedPlayer; // 22
|
||||
SCR_INT GangopsFlowMissionProgFlags; // 23
|
||||
SCR_INT GangopsFMMissionProgFlags; // 24
|
||||
SCR_INT GangopsFMMissionSkipFlags; // 25
|
||||
SCR_INT GangopsHeistStatusFlags; // 26
|
||||
SCR_INT Flags; // 27
|
||||
SCR_BOOL IsPlanningScreenReady; // 28
|
||||
SCR_BOOL QuittedPlanningScreen; // 29
|
||||
SCR_BOOL IsTutorialActive; // 30
|
||||
SCR_ARRAY<uint64_t, 4> IsTutorialActiveForPlayer; // 31
|
||||
TIMER FinaleForceLaunchTimer; // 36 (H2_FINALE_FORCE_LAUNCH_TIME)
|
||||
SCR_BOOL IsFinaleForceLaunched; // 38 (if players don't click ready in 3 minutes)
|
||||
};
|
||||
static_assert(sizeof(GANGOPS_DATA) == 39 * 8);
|
||||
|
||||
struct RANDOM_EVENTS_CLIENT_EVENT_DATA
|
||||
{
|
||||
alignas(8) eRandomEventClientState State; // 0
|
||||
SCR_ARRAY<SCR_BITSET<eRandomEventClientFlags>, 1> Flags; // 1
|
||||
};
|
||||
static_assert(sizeof(RANDOM_EVENTS_CLIENT_EVENT_DATA) == 3 * 8);
|
||||
|
||||
struct RANDOM_EVENTS_CLIENT_DATA
|
||||
{
|
||||
alignas(8) eRandomEventClientInitState InitState; // 0
|
||||
SCR_ARRAY<RANDOM_EVENTS_CLIENT_EVENT_DATA, 21> EventData; // 1
|
||||
SCR_BITSET<uint64_t> IsParticipantInEventFlags; // 65
|
||||
SCR_INT UNK_0066; // 66 (unused)
|
||||
};
|
||||
static_assert(sizeof(RANDOM_EVENTS_CLIENT_DATA) == 67 * 8);
|
||||
|
||||
struct GPBD_FM_2_Entry
|
||||
{
|
||||
SCR_INT NumTeams; // 0
|
||||
SCR_INT NumRounds; // 1
|
||||
SCR_INT RoundsPlayed; // 2
|
||||
SCR_INT RoundScore; // 3
|
||||
SCR_INT CurrentTeam; // 4
|
||||
SCR_INT Flags; // 5
|
||||
SCR_INT TotalScore; // 6
|
||||
SCR_INT TotalKills; // 7
|
||||
SCR_INT TotalDeaths; // 8
|
||||
SCR_INT RPEarned; // 9
|
||||
SCR_INT CashEarned; // 10
|
||||
uint64_t PAD_0011[2]; // 11
|
||||
SCR_INT APEarned; // 13
|
||||
SCR_INT Duration; // 14
|
||||
alignas(8) eRaceRoundType RaceRoundType; // 15
|
||||
alignas(8) eRaceFinalRoundType RaceFinalRoundType; // 16
|
||||
SCR_INT Flags2; // 17
|
||||
SCR_INT Vote; // 18
|
||||
SCR_INT NumVotes; // 19
|
||||
SCR_INT MaxVotes; // 20
|
||||
SCR_INT PlayerTeam; // 21
|
||||
uint64_t PAD_0022[8]; // 22 (mission stuff)
|
||||
SCR_INT TunableCloudCRC; // 30
|
||||
SCR_INT CatalogCloudCRC; // 31
|
||||
SCR_INT UNK_0032; // 32
|
||||
SCR_INT Flags3; // 33
|
||||
SCR_INT UNK_0034; // 34
|
||||
SCR_BOOL HasVoted; // 35
|
||||
TIMER UNK_0036; // 36
|
||||
TIMER UNK_0038; // 38
|
||||
SCR_VEC3 CoronaPosition; // 40
|
||||
GANGOPS_DATA GangopsData; // 43
|
||||
RANDOM_EVENTS_CLIENT_DATA RandomEventsClientData; // 82
|
||||
};
|
||||
static_assert(sizeof(GPBD_FM_2_Entry) == 149 * 8);
|
||||
|
||||
struct GPBD_FM_2
|
||||
{
|
||||
SCR_ARRAY<GPBD_FM_2_Entry, 32> Entries;
|
||||
|
||||
static GPBD_FM_2* Get();
|
||||
};
|
||||
static_assert(sizeof(GPBD_FM_2) == 4769 * 8);
|
||||
@@ -16,7 +16,7 @@ enum class eRandomEventState
|
||||
CLEANUP
|
||||
};
|
||||
|
||||
enum class eRandomEventBitset
|
||||
enum class eRandomEventFlags
|
||||
{
|
||||
TRIGGERED_BY_CLIENT,
|
||||
FORCE_LAUNCH,
|
||||
@@ -36,7 +36,7 @@ struct RANDOM_EVENTS_DATA
|
||||
{
|
||||
alignas(8) eRandomEventState State; // 0
|
||||
TIMER TimerState; // 1
|
||||
SCR_ARRAY<SCR_BITSET<eRandomEventBitset>, 1> Bitset; // 3
|
||||
SCR_ARRAY<SCR_BITSET<eRandomEventFlags>, 1> Flags; // 3
|
||||
SCR_INT Variation; // 5
|
||||
SCR_INT Subvariation; // 6
|
||||
RANDOM_EVENTS_RESERVATION_DATA ReservationData; // 7
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "GlobalPlayerBD.hpp"
|
||||
#include "GPBD_FM.hpp"
|
||||
#include "GPBD_FM_2.hpp"
|
||||
#include "GPBD_FM_3.hpp"
|
||||
#include "GPBD_Kicking.hpp"
|
||||
#include "GPBD_MissionName.hpp"
|
||||
@@ -23,6 +24,7 @@
|
||||
|
||||
DEFINE_GLOBAL_ACCESSOR(GlobalPlayerBD, 2657994);
|
||||
DEFINE_GLOBAL_ACCESSOR(GPBD_FM, 1845270);
|
||||
DEFINE_GLOBAL_ACCESSOR(GPBD_FM_2, 1882925);
|
||||
DEFINE_GLOBAL_ACCESSOR(GPBD_FM_3, 1887694);
|
||||
DEFINE_GLOBAL_ACCESSOR(GPBD_Kicking, 1874328);
|
||||
DEFINE_GLOBAL_ACCESSOR(GPBD_MissionName, 1873815);
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace rage
|
||||
class scrThread;
|
||||
}
|
||||
|
||||
enum class eRandomEventFlags
|
||||
enum class eRandomEventFMFlags
|
||||
{
|
||||
RESTART = 2,
|
||||
DISABLE_DISTANCE_CHECK = 4
|
||||
@@ -22,7 +22,7 @@ struct RANDOM_EVENTS_LOCAL_DATA
|
||||
SCR_INT AvailablePtr; // 5
|
||||
SCR_INT InactiveTime; // 6
|
||||
SCR_INT AvailableTime; // 7
|
||||
SCR_BITSET<eRandomEventFlags> Flags; // 8
|
||||
SCR_BITSET<eRandomEventFMFlags> Flags; // 8
|
||||
TIMER LastTriggerAttempt; // 9
|
||||
SCR_INT UNK_0011; // 11 (unused, ranges from 0 to 4)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user