mirror of
https://github.com/SunsetMkt/Akebi-GC.git
synced 2025-09-19 12:06:04 +08:00
158 lines
6.3 KiB
C++
158 lines
6.3 KiB
C++
#include "pch-il2cpp.h"
|
|
#include "DialogSkip.h"
|
|
|
|
#include <helpers.h>
|
|
#include <cheat/game/EntityManager.h>
|
|
|
|
namespace cheat::feature
|
|
{
|
|
static void InLevelCutScenePageContext_UpdateView_Hook(app::InLevelCutScenePageContext* __this, MethodInfo* method);
|
|
static void InLevelCutScenePageContext_ClearView_Hook(app::InLevelCutScenePageContext* __this, MethodInfo* method);
|
|
static void CriwareMediaPlayer_Update(app::CriwareMediaPlayer* __this, MethodInfo* method);
|
|
|
|
DialogSkip::DialogSkip() : Feature(),
|
|
NF(f_Enabled, "Auto talk", "AutoTalk", false),
|
|
NF(f_AutoSelectDialog, "Auto select dialog", "AutoTalk", true),
|
|
NF(f_ExcludeImportant, "Exclude Katheryne/Tubby/Wagner", "AutoTalk", true),
|
|
NF(f_FastDialog, "Fast dialog", "AutoTalk", false),
|
|
NF(f_CutsceneUSM, "Skip Cutscenes", "AutoTalk", false),
|
|
NF(f_TimeSpeedup, "Time Speed", "AutoTalk", 5.0f)
|
|
{
|
|
HookManager::install(app::MoleMole_InLevelCutScenePageContext_UpdateView, InLevelCutScenePageContext_UpdateView_Hook);
|
|
HookManager::install(app::MoleMole_InLevelCutScenePageContext_ClearView, InLevelCutScenePageContext_ClearView_Hook);
|
|
HookManager::install(app::CriwareMediaPlayer_Update, CriwareMediaPlayer_Update);
|
|
}
|
|
|
|
const FeatureGUIInfo& DialogSkip::GetGUIInfo() const
|
|
{
|
|
static const FeatureGUIInfo info{ "Auto Talk", "World", true };
|
|
return info;
|
|
}
|
|
|
|
void DialogSkip::DrawMain()
|
|
{
|
|
ConfigWidget("Enabled", f_Enabled, "Automatically continue the dialog.");
|
|
ConfigWidget("Auto-select Dialog", f_AutoSelectDialog, "Automatically select dialog choices.");
|
|
if (f_AutoSelectDialog)
|
|
{
|
|
ImGui::Indent();
|
|
ConfigWidget("Exclude Katheryne/Tubby/Wagner", f_ExcludeImportant, "Exclude Kath/Tubby/Wagner from auto-select.");
|
|
ImGui::Unindent();
|
|
}
|
|
ConfigWidget("Fast Dialog", f_FastDialog, "Speeds up Time");
|
|
if (f_FastDialog)
|
|
{
|
|
ConfigWidget(f_TimeSpeedup, 0.1f, 2.0f, 50.0f, "Time Speedup Multipler \nHigher Values will lead to sync issues with servers \nand is not recommended for Laggy Internet connections.");
|
|
}
|
|
ConfigWidget("Skip Cutscenes", f_CutsceneUSM, "Automatically skips game movies.");
|
|
}
|
|
|
|
bool DialogSkip::NeedStatusDraw() const
|
|
{
|
|
return f_Enabled || f_CutsceneUSM;
|
|
}
|
|
|
|
void DialogSkip::DrawStatus()
|
|
{
|
|
if (f_Enabled)
|
|
ImGui::Text("Dialog [%s%s%s%s%s]",
|
|
f_AutoSelectDialog ? "Auto" : "Manual",
|
|
f_AutoSelectDialog && (f_ExcludeImportant || f_FastDialog) ? "|" : "",
|
|
f_ExcludeImportant ? "Exc" : "",
|
|
f_ExcludeImportant && f_FastDialog ? "|" : "",
|
|
f_FastDialog ? "Fast" : "Normal");
|
|
|
|
ImGui::Text(f_CutsceneUSM ? "Skip Cutscenes" : "");
|
|
}
|
|
|
|
DialogSkip& DialogSkip::GetInstance()
|
|
{
|
|
static DialogSkip instance;
|
|
return instance;
|
|
}
|
|
|
|
// Raised when dialog view updating
|
|
// We call free click, if auto talk enabled, that means we just emulate user click
|
|
// When appear dialog choose we create notify with dialog select first item.
|
|
void DialogSkip::OnCutScenePageUpdate(app::InLevelCutScenePageContext* context)
|
|
{
|
|
if (!f_Enabled)
|
|
return;
|
|
|
|
auto talkDialog = context->fields._talkDialog;
|
|
if (talkDialog == nullptr)
|
|
return;
|
|
|
|
if (f_FastDialog)
|
|
app::Time_set_timeScale(f_TimeSpeedup, nullptr);
|
|
else
|
|
app::Time_set_timeScale(1.0f, nullptr);
|
|
|
|
bool isImportant = false;
|
|
if (f_ExcludeImportant)
|
|
{
|
|
// TODO: Add a custom filter in the future where users can
|
|
// add their own name substrings of entities to avoid
|
|
// speeding up dialog on.
|
|
std::vector<std::string> impEntitiesNames = {
|
|
"Djinn",
|
|
"Katheryne",
|
|
"Wagner",
|
|
"Ahangar"
|
|
};
|
|
auto dialogPartnerID = context->fields._inteeID;
|
|
auto& manager = game::EntityManager::instance();
|
|
auto dialogPartner = manager.entity(dialogPartnerID);
|
|
auto dialogPartnerName = dialogPartner->name();
|
|
for (auto impEntityName : impEntitiesNames)
|
|
{
|
|
if (dialogPartnerName.find(impEntityName) != -1) {
|
|
LOG_DEBUG("%s %s %d", dialogPartnerName.c_str(), impEntityName, dialogPartnerName.find(impEntityName));
|
|
isImportant = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (talkDialog->fields._inSelect && f_AutoSelectDialog && !isImportant)
|
|
{
|
|
int32_t value = 0;
|
|
auto object = il2cpp_value_box((Il2CppClass*)*app::Int32__TypeInfo, &value);
|
|
app::Notify notify{};
|
|
notify.type = app::MoleMole_NotifyTypes__Enum::DialogSelectNotify;
|
|
notify.body = (app::Object*)object;
|
|
app::MoleMole_TalkDialogContext_OnDialogSelectItem(talkDialog, ¬ify, nullptr);
|
|
}
|
|
else if (!talkDialog->fields._inSelect)
|
|
app::MoleMole_InLevelCutScenePageContext_OnFreeClick(context, nullptr);
|
|
}
|
|
|
|
static void InLevelCutScenePageContext_UpdateView_Hook(app::InLevelCutScenePageContext* __this, MethodInfo* method)
|
|
{
|
|
CALL_ORIGIN(InLevelCutScenePageContext_UpdateView_Hook, __this, method);
|
|
|
|
DialogSkip& dialogSkip = DialogSkip::GetInstance();
|
|
dialogSkip.OnCutScenePageUpdate(__this);
|
|
}
|
|
|
|
// Raised when exiting a dialog. We try to hackishly return to normal value.
|
|
// Should be a better way to store the pre-dialog speed using Time_get_timeScale.
|
|
static void InLevelCutScenePageContext_ClearView_Hook(app::InLevelCutScenePageContext* __this, MethodInfo* method)
|
|
{
|
|
float gameSpeed = app::Time_get_timeScale(nullptr);
|
|
if (gameSpeed > 1.0f)
|
|
app::Time_set_timeScale(1.0f, nullptr);
|
|
CALL_ORIGIN(InLevelCutScenePageContext_ClearView_Hook, __this, method);
|
|
}
|
|
|
|
static void CriwareMediaPlayer_Update(app::CriwareMediaPlayer* __this, MethodInfo* method)
|
|
{
|
|
DialogSkip& dialogSkip = DialogSkip::GetInstance();
|
|
if (dialogSkip.f_CutsceneUSM)
|
|
app::CriwareMediaPlayer_Skip(__this, nullptr);
|
|
|
|
return CALL_ORIGIN(CriwareMediaPlayer_Update, __this, method);
|
|
}
|
|
}
|
|
|