Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 61 additions & 16 deletions mods/src/patches/parts/galactic_anomaly_timer.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include "config.h"
#include "errormsg.h"
#include "patches/screen_update_hook.h"
#include "prime/Color.h"
#include "prime/Hub.h"
#include "prime/Vector2.h"

#include <il2cpp/il2cpp_helper.h>
#include <il2cpp-tabledefs.h>
#include <il2cpp/il2cpp_helper.h>
#include <spdlog/spdlog.h>

#include <chrono>
Expand Down Expand Up @@ -166,10 +168,46 @@ void Clear()
anomalyManager.reset();
}

Il2CppObject* Find(Il2CppClass* type)
bool InSystemNavigation()
{
static auto* hub = Class("Assembly-CSharp", "Digit.Client.Core", "Hub");
static auto* sectionsGetter = IL2CppClassHelper(hub).GetMethodInfo("get_SectionManager", 0);
Il2CppObject* sections = nullptr;
std::int32_t section = 0;
return TryInvoke(sectionsGetter, nullptr, nullptr, &sections) && Value(sections, "get_CurrentSection", section)
&& static_cast<SectionID>(section) == SectionID::Navigation_System;
}

Il2CppObject* NavigationHud()
{
static auto* screen = Class("Assembly-CSharp", "Digit.Client.UI", "ScreenManager");
static auto* top = IL2CppClassHelper(screen).GetMethodInfo("GetTopCanvas", 1);
bool visibleOnly = true;
void* args[] = {&visibleOnly};
Il2CppObject* canvas = nullptr;
if (!TryInvoke(top, nullptr, args, &canvas) || !Alive(canvas))
return nullptr;
static auto* hud = Class("Assembly-CSharp", "Digit.Prime.Navigation.UI", "HudNavigationViewController");
return WithType(TypeMethod(canvas->klass, "GetComponentInChildren"), canvas, hud);
}

Il2CppObject* ExistingAnomalyManager(Il2CppClass* managerClass)
{
static auto* method = TypeMethod(UnityObject(), "FindObjectOfType");
return WithType(method, nullptr, type);
// get_Instance may search the scene or create a replacement. Read only the
// native owner's existing singleton, and retry when it has not initialized.
static auto* parent = managerClass ? il2cpp_class_get_parent(managerClass) : nullptr;
if (!parent || std::strcmp(il2cpp_class_get_name(parent), "MonoSingleton`1"))
return nullptr;
static auto* instance = il2cpp_class_get_field_from_name(parent, "s_instance");
if (!instance || !(il2cpp_field_get_flags(instance) & FIELD_ATTRIBUTE_STATIC) || !instance->type
|| il2cpp_type_is_byref(instance->type))
return nullptr;
const auto kind = il2cpp_type_get_type(instance->type);
if (kind != IL2CPP_TYPE_CLASS && kind != IL2CPP_TYPE_GENERICINST && kind != IL2CPP_TYPE_VAR)
return nullptr;
Il2CppObject* value = nullptr;
il2cpp_field_static_get_value(instance, &value);
return value && il2cpp_class_is_assignable_from(managerClass, value->klass) && Alive(value) ? value : nullptr;
}

Il2CppObject* Component(Il2CppObject* object, Il2CppClass* type)
Expand Down Expand Up @@ -199,7 +237,8 @@ Il2CppObject* NewObject(const char* name, Il2CppObject* parent, Root& root)
auto* transform = WithType(TypeMethod(go, "AddComponent"), object, rt);
bool worldPositionStays = false;
void* parentArgs[] = {parent, &worldPositionStays};
if (!transform || !TryInvoke(IL2CppClassHelper(transform->klass).GetMethodInfo("SetParent", 2), transform, parentArgs))
if (!transform
|| !TryInvoke(IL2CppClassHelper(transform->klass).GetMethodInfo("SetParent", 2), transform, parentArgs))
return nullptr;
return transform;
}
Expand Down Expand Up @@ -273,12 +312,13 @@ bool Create(Il2CppObject* nav)
if (!TryInvoke(IL2CppClassHelper(names->klass).GetMethodInfo("get_Item", 1), names, args, &name) || !Alive(name))
return false;
static auto* drawerClass = Class("Assembly-CSharp", "Digit.Prime.HUD", "HudAllianceAndNewsViewController");
auto* drawer = Find(drawerClass);
auto* chest = Get(Field(drawer, "_chestPromotion"), "get_transform");
auto* parent = Get(chest, "get_parent");
static auto* tmp = Class("Unity.TextMeshPro", "TMPro", "TextMeshProUGUI");
auto* source = Component(name, tmp);
auto* font = Get(source, "get_font");
auto* uiRoot = Get(Get(nav, "get_transform"), "get_root");
auto* drawer = uiRoot ? WithType(TypeMethod(uiRoot->klass, "GetComponentInChildren"), uiRoot, drawerClass) : nullptr;
auto* chest = Get(Field(drawer, "_chestPromotion"), "get_transform");
auto* parent = Get(chest, "get_parent");
static auto* tmp = Class("Unity.TextMeshPro", "TMPro", "TextMeshProUGUI");
auto* source = Component(name, tmp);
auto* font = Get(source, "get_font");
if (!parent || !font)
return false;

Expand Down Expand Up @@ -337,10 +377,14 @@ void Update()
Clear();
return;
}
if (!Alive(navigation.get())) {
if (!InSystemNavigation()) {
Clear();
return;
}
bool active = false;
if (!Alive(navigation.get()) || !Value(navigation.get(), "get_isActiveAndEnabled", active) || !active) {
Clear();
static auto* cls = Class("Assembly-CSharp", "Digit.Prime.Navigation.UI", "HudNavigationViewController");
navigation.reset(Find(cls));
navigation.reset(NavigationHud());
}
auto* nav = navigation.get();
bool show = false;
Expand All @@ -353,12 +397,13 @@ void Update()
// Cache the Unity object, not its timer data. Unity's liveness check detects
// destruction even while the managed wrapper is retained by our GC handle.
if (!Alive(anomalyManager.get()))
anomalyManager.reset(Find(managerClass));
anomalyManager.reset(ExistingAnomalyManager(managerClass));
auto* manager = anomalyManager.get();
Il2CppObject* anomaly = nullptr;
void* args[] = {&system};
show = manager && Value(address, "get_System", system) && system > 0
&& TryInvoke(IL2CppClassHelper(managerClass).GetMethodInfo("GetSystemGalacticAnomalies", 1), manager, args, &anomaly)
&& TryInvoke(IL2CppClassHelper(managerClass).GetMethodInfo("GetSystemGalacticAnomalies", 1), manager, args,
&anomaly)
&& Value(anomaly, "get_IsActive", show) && show
&& Value(Get(anomaly, "get_EndTimeTimerDataContext"), "get_RemainingTime", ticks) && ticks > 0;
} else {
Expand Down
Loading