From b6d35fd5b358b3a63e6c491e9adbc68873ded7a6 Mon Sep 17 00:00:00 2001
From: chinosk <2248589280@qq.com>
Date: Sun, 5 May 2024 10:38:41 +0800
Subject: [PATCH] Add: Unlock Idol Event and Support Event #20
---
README.md | 31 +++++++++++-----------
readme_EN.md | 1 +
resources/scsp-config.json | 3 ++-
src/hook.cpp | 53 ++++++++++++++++++++++++++++++++++++++
src/main.cpp | 4 +++
src/scgui/scGUILoop.cpp | 4 +++
src/stdinclude.hpp | 1 +
7 files changed, 81 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index d291a55..2e91fd0 100644
--- a/README.md
+++ b/README.md
@@ -40,21 +40,22 @@
- 配置项位于 `scsp-config.json` 文件中
-| 配置项 | 类型 | 默认值 | 说明 |
-| --------------------- | ---------------------------------------- | -------------------------------------- | ---------------------------------------------------- |
-| enableConsole | Bool | `true` | 是否开启控制台 |
-| enableVSync | Bool | `false` | 是否启用垂直同步 |
-| maxFps | Int | `60` | 最大帧数
当启用 `enableVSync` 时,此项配置失效 |
-| 3DResolutionScale | Float | `1.0` | 3D 渲染分辨率倍率 |
-| localifyBasePath | String | `scsp_localify` | 本地化文件目录 |
-| hotKey | String (Char) | `u` | 按下 `Ctrl` + 此项配置的热键,**打开插件 GUI** |
-| dumpUntransLyrics | Bool | `false` | dump 未翻译的歌词 |
-| dumpUntransLocal2 | Bool | `false` | dump 未翻译的文本 |
-| autoDumpAllJson | Bool | `false` | dump 所有游戏加载的 JSON |
-| extraAssetBundlePaths | String[] | `["scsp_localify/scsp-bundle"]` | 自定义数据包路径 |
-| customFontPath | String | `assets/font/sbtphumminge-regular.ttf` | 自定义数据包中字体路径
用于替换游戏内置字体 |
-| blockOutOfFocus | Bool | `true` | 拦截窗口失焦事件
切换到其它窗口后不会触发游戏暂停 |
-| baseFreeCamera | [BaseFreeCamera](#BaseFreeCamera) Object | [BaseFreeCamera](#BaseFreeCamera) | 自由视角配置 |
+| 配置项 | 类型 | 默认值 | 说明 |
+| -------------------------- | ---------------------------------------- | -------------------------------------- | ---------------------------------------------------- |
+| enableConsole | Bool | `true` | 是否开启控制台 |
+| enableVSync | Bool | `false` | 是否启用垂直同步 |
+| maxFps | Int | `60` | 最大帧数
当启用 `enableVSync` 时,此项配置失效 |
+| 3DResolutionScale | Float | `1.0` | 3D 渲染分辨率倍率 |
+| localifyBasePath | String | `scsp_localify` | 本地化文件目录 |
+| hotKey | String (Char) | `u` | 按下 `Ctrl` + 此项配置的热键,**打开插件 GUI** |
+| dumpUntransLyrics | Bool | `false` | dump 未翻译的歌词 |
+| dumpUntransLocal2 | Bool | `false` | dump 未翻译的文本 |
+| autoDumpAllJson | Bool | `false` | dump 所有游戏加载的 JSON |
+| extraAssetBundlePaths | String[] | `["scsp_localify/scsp-bundle"]` | 自定义数据包路径 |
+| customFontPath | String | `assets/font/sbtphumminge-regular.ttf` | 自定义数据包中字体路径
用于替换游戏内置字体 |
+| blockOutOfFocus | Bool | `true` | 拦截窗口失焦事件
切换到其它窗口后不会触发游戏暂停 |
+| baseFreeCamera | [BaseFreeCamera](#BaseFreeCamera) Object | [BaseFreeCamera](#BaseFreeCamera) | 自由视角配置 |
+| unlockPIdolAndSCharaEvents | Bool | `false` | 解锁 `角色` - `一览` 中的P卡和S卡事件 |
diff --git a/readme_EN.md b/readme_EN.md
index d4812f8..cbaeb13 100644
--- a/readme_EN.md
+++ b/readme_EN.md
@@ -54,6 +54,7 @@ iM@S SCSP localify plugin.
| customFontPath | String | `assets/font/sbtphumminge-regular.ttf` | Custom font path in asset bundles
Used for replacing built-in fonts in the game |
| blockOutOfFocus | Bool | `true` | Intercept window out-of-focus events
Game won't pause when switching to other windows |
| baseFreeCamera | [BaseFreeCamera](#BaseFreeCamera) Object | [BaseFreeCamera](#BaseFreeCamera) | Free camera configuration |
+| unlockPIdolAndSCharaEvents | Bool | `false` | Unlock Idol Event (アイドルイベント) and Support Event (サポートイベント) in `Characters` - `Overview` |
diff --git a/resources/scsp-config.json b/resources/scsp-config.json
index 93f9711..9b2a693 100644
--- a/resources/scsp-config.json
+++ b/resources/scsp-config.json
@@ -18,5 +18,6 @@
"enable": false,
"moveStep": 50,
"mouseSpeed": 35
- }
+ },
+ "unlockPIdolAndSCharaEvents": false
}
\ No newline at end of file
diff --git a/src/hook.cpp b/src/hook.cpp
index c7be9fd..8a774b5 100644
--- a/src/hook.cpp
+++ b/src/hook.cpp
@@ -593,6 +593,48 @@ namespace
}
+ // NOT HOOK
+ void* PIdolDetailPopupViewModel_Create_orig;
+ void* PIdolDetailPopupViewModel_Create_hook(void* produceIdol, void* costumeSetInfoList, void* idolBase, void* idolParameter, bool isChangeableIdolSkill, bool isChangeableFavorite, void* produceAdvStatusList, bool isPlayableAdv, bool inLive, bool upgradingButtonActive) {
+ auto ret = reinterpret_cast(PIdolDetailPopupViewModel_Create_orig)(
+ produceIdol, costumeSetInfoList, idolBase, idolParameter, isChangeableIdolSkill, isChangeableFavorite, produceAdvStatusList, isPlayableAdv, inLive, upgradingButtonActive
+ );
+ return ret;
+ /* // 功能被 EventModel_ctor_hook 替代
+ static auto get_EventList = reinterpret_cast(
+ il2cpp_symbols::get_method_pointer("PRISM.Adapters.dll", "PRISM.Adapters",
+ "PIdolDetailPopupViewModel", "get_EventList", 0)
+ );
+ static auto EventModel_klass = il2cpp_symbols::get_class("PRISM.Adapters.dll", "PRISM.Adapters", "EventModel");
+ static auto Read_field = il2cpp_class_get_field_from_name(EventModel_klass, "k__BackingField");
+ static auto IsAdvPlayable_field = il2cpp_class_get_field_from_name(EventModel_klass, "k__BackingField");
+
+ printf("PIdolDetailPopupViewModel_Create\n");
+
+ auto events = get_EventList(ret);
+
+ il2cpp_symbols::iterate_IEnumerable(events, [](void* event) {
+ const auto read = il2cpp_symbols::read_field(event, Read_field);
+ const auto isAdvPlayable = il2cpp_symbols::read_field(event, IsAdvPlayable_field);
+ printf("read: %d, isAdvPlayable: %d\n", read, isAdvPlayable);
+
+ il2cpp_symbols::write_field(event, Read_field, true);
+ });
+
+ return ret;*/
+ }
+
+ void* EventModel_ctor_orig;
+ void EventModel_ctor_hook(void* _this, void* scenarioID, Il2CppString* title, Il2CppString* summary, bool read, bool isAdvPlayable) {
+ if (g_unlock_PIdol_and_SChara_events) {
+ if (!read) {
+ wprintf(L"Force Unlock Event: %ls\n", title->start_char);
+ read = true;
+ }
+ }
+ return reinterpret_cast(EventModel_ctor_orig)(_this, scenarioID, title, summary, read, isAdvPlayable);
+ }
+
void* LocalizationManager_GetTextOrNull_orig;
Il2CppString* LocalizationManager_GetTextOrNull_hook(void* _this, Il2CppString* category, int id) {
if (g_max_fps != -1) set_fps_hook(g_max_fps);
@@ -2025,6 +2067,15 @@ namespace
"TextLog", "AddLog", 4
);
+ auto PIdolDetailPopupViewModel_Create_addr = il2cpp_symbols::get_method_pointer(
+ "PRISM.Adapters.dll", "PRISM.Adapters",
+ "PIdolDetailPopupViewModel", "Create", 10
+ );
+ auto EventModel_ctor_addr = il2cpp_symbols::get_method_pointer(
+ "PRISM.Adapters.dll", "PRISM.Adapters",
+ "EventModel", ".ctor", 5
+ );
+
auto LocalizationManager_GetTextOrNull_addr = il2cpp_symbols::get_method_pointer(
"ENTERPRISE.Localization.dll", "ENTERPRISE.Localization",
"LocalizationManager", "GetTextOrNull", 2
@@ -2215,6 +2266,8 @@ namespace
);
#pragma endregion
+ // ADD_HOOK(PIdolDetailPopupViewModel_Create, "PIdolDetailPopupViewModel_Create at %p");
+ ADD_HOOK(EventModel_ctor, "EventModel_ctor at %p");
ADD_HOOK(LocalizationManager_GetTextOrNull, "LocalizationManager_GetTextOrNull at %p");
ADD_HOOK(get_NeedsLocalization, "get_NeedsLocalization at %p");
ADD_HOOK(GetResolutionSize, "GetResolutionSize at %p");
diff --git a/src/main.cpp b/src/main.cpp
index c9279f7..e9358cf 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -43,6 +43,7 @@ bool g_allow_same_idol = false;
bool g_unlock_all_dress = false;
bool g_unlock_all_headwear = false;
bool g_enable_chara_param_edit = false;
+bool g_unlock_PIdol_and_SChara_events = false;
std::filesystem::path g_localify_base("scsp_localify");
constexpr const char ConfigJson[] = "scsp-config.json";
@@ -180,6 +181,9 @@ namespace
if (document.HasMember("unlockAllHeadwear")) {
g_unlock_all_headwear = document["unlockAllHeadwear"].GetBool() && g_unlock_all_dress;
}
+ if (document.HasMember("unlockPIdolAndSCharaEvents")) {
+ g_unlock_PIdol_and_SChara_events = document["unlockPIdolAndSCharaEvents"].GetBool();
+ }
}
diff --git a/src/scgui/scGUILoop.cpp b/src/scgui/scGUILoop.cpp
index 8ffa1d7..77107df 100644
--- a/src/scgui/scGUILoop.cpp
+++ b/src/scgui/scGUILoop.cpp
@@ -172,6 +172,10 @@ namespace SCGUILoop {
ImGui::SameLine();
HELP_TOOLTIP("(?)", "启用角色身体参数编辑器")
+ ImGui::Checkbox("Unlock PIdol And SChara Events", &g_unlock_PIdol_and_SChara_events);
+ ImGui::SameLine();
+ HELP_TOOLTIP("(?)", "解锁 角色 - 一览 中的P卡和S卡事件\nUnlock Idol Event (アイドルイベント) and Support Event (サポートイベント)")
+
if (ImGui::CollapsingHeader("Resolution Settings", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::Text("Window Resolution Settings");
diff --git a/src/stdinclude.hpp b/src/stdinclude.hpp
index 3ed7566..9ebbdfb 100644
--- a/src/stdinclude.hpp
+++ b/src/stdinclude.hpp
@@ -175,3 +175,4 @@ extern bool g_unlock_all_headwear;
extern bool g_enable_chara_param_edit;
extern float g_font_size_offset;
extern float g_3d_resolution_scale;
+extern bool g_unlock_PIdol_and_SChara_events;