diff --git a/blcrack/cracker/cracker.cpp b/blcrack/cracker/cracker.cpp index 3a7dee8ae..8ab04da6b 100644 --- a/blcrack/cracker/cracker.cpp +++ b/blcrack/cracker/cracker.cpp @@ -6,6 +6,35 @@ #include #include "utils.hpp" +#include "il2cpp.hpp" + +using fnset_TimeScaleT = void(*)(float); + +static fnset_TimeScaleT get_Time_set_timeScale() { + Il2CppDomain* domain = il2cpp_domain_get(); + size_t assembly_count = 0; + Il2CppAssembly** assemblies = il2cpp_domain_get_assemblies(domain, &assembly_count); + + Il2CppClass* cls = nullptr; + for (size_t i = 0; i < assembly_count; ++i) { + Il2CppImage* image = il2cpp_assembly_get_image(assemblies[i]); + Il2CppClass* klass = il2cpp_class_from_name(image, "UnityEngine", "Time"); + if (klass != nullptr) { + cls = klass; + break; + } + } + if (cls != nullptr) { + MethodInfo* method_info = il2cpp_class_get_method_from_name(cls, "set_timeScale", 1); + if (method_info != nullptr) { + auto method = reinterpret_cast(method_info->methodPointer); + SPDLOG_INFO("Found Time.set_timeScale at {}", (void*)method_info->methodPointer); + return method; + } + } + SPDLOG_ERROR("Failed to get Time.set_timeScale"); + throw std::runtime_error("Failed to get Time.set_timeScale"); +} #define IS_ENABLED(n) \ if (is_enabled(n)) { \ @@ -211,6 +240,19 @@ void Cracker::disable_all() { disable_no_emotion_warning(); disable_opsi_fast_move(); disable_gg_factor(); + disable_global_speedup(); +} + +void Cracker::enable_global_speedup(float rate) { + // IS_ENABLED(GLOBAL_SPEEDUP) + get_Time_set_timeScale()(rate); + ENABLE(GLOBAL_SPEEDUP) +} + +void Cracker::disable_global_speedup() { + // IS_DISABLED(GLOBAL_SPEEDUP) + get_Time_set_timeScale()(1.0); + DISABLE(GLOBAL_SPEEDUP) } void Cracker::enable_gg_factor() { diff --git a/blcrack/cracker/cracker.hpp b/blcrack/cracker/cracker.hpp index 9c33c25e8..fe8f8eba8 100644 --- a/blcrack/cracker/cracker.hpp +++ b/blcrack/cracker/cracker.hpp @@ -28,6 +28,7 @@ enum { NO_EMOTION_WARNING, OPSI_FAST_MOVE, GG_FACTOR, + GLOBAL_SPEEDUP, }; class Cracker { @@ -103,6 +104,9 @@ public: void disable_all(); + void enable_global_speedup(float rate); + void disable_global_speedup(); + void enable_gg_factor(); void disable_gg_factor(); void update_gg_factor(double factor); diff --git a/blcrack/cracker/server.cpp b/blcrack/cracker/server.cpp index 431f6bf51..9f32d28d5 100644 --- a/blcrack/cracker/server.cpp +++ b/blcrack/cracker/server.cpp @@ -603,6 +603,34 @@ CrackerServer::CrackerServer() { res.status = 200; }); + Post("/enable_global_speedup", [](const httplib::Request& req, httplib::Response& res) { + try { + Json::Reader reader; + Json::Value j; + reader.parse(req.body, j); + Cracker::Instance().enable_global_speedup(j["rate"].asFloat()); + } catch (std::exception& e) { + SPDLOG_ERROR("Enable global speedup failed: {}", e.what()); + res.status = 500; + return; + } + res.status = 200; + }); + + Post("/disable_global_speedup", [](const httplib::Request& req, httplib::Response& res) { + try { + Json::Reader reader; + Json::Value j; + reader.parse(req.body, j); + Cracker::Instance().disable_global_speedup(); + } catch (std::exception& e) { + SPDLOG_ERROR("Disable global speedup failed: {}", e.what()); + res.status = 500; + return; + } + res.status = 200; + }); + std::thread([this] { SPDLOG_INFO("Start server on port 23897"); listen("0.0.0.0", 23897); diff --git a/blcrack/http/cracker.http b/blcrack/http/cracker.http index fa2484780..03b1993dd 100644 --- a/blcrack/http/cracker.http +++ b/blcrack/http/cracker.http @@ -89,5 +89,15 @@ POST http://127.0.0.1:23897/enable_opsi_fast_move ### POST http://127.0.0.1:23897/disable_opsi_fast_move +### +POST http://127.0.0.1:23897/enable_global_speedup + +{ + "rate": 10.0 +} + +### +POST http://127.0.0.1:23897/disable_global_speedup + ### POST http://127.0.0.1:23897/is_alive \ No newline at end of file diff --git a/config/template.json b/config/template.json index a6dfa867f..84a19f336 100644 --- a/config/template.json +++ b/config/template.json @@ -1,4 +1,89 @@ { + "Dashboard": { + "Oil": { + "Value": 0, + "Limit": 0, + "Color": "^000000", + "Record": "2020-01-01 00:00:00" + }, + "Coin": { + "Value": 0, + "Limit": 0, + "Color": "^FFAA33", + "Record": "2020-01-01 00:00:00" + }, + "Gem": { + "Value": 0, + "Color": "^FF3333", + "Record": "2020-01-01 00:00:00" + }, + "Pt": { + "Value": 0, + "Color": "^00BFFF", + "Record": "2020-01-01 00:00:00" + }, + "Cube": { + "Value": 0, + "Color": "^33FFFF", + "Record": "2020-01-01 00:00:00" + }, + "ActionPoint": { + "Value": 0, + "Total": 0, + "Color": "^0000FF", + "Record": "2020-01-01 00:00:00" + }, + "YellowCoin": { + "Value": 0, + "Color": "^FF8800", + "Record": "2020-01-01 00:00:00" + }, + "PurpleCoin": { + "Value": 0, + "Color": "^7700BB", + "Record": "2020-01-01 00:00:00" + }, + "Core": { + "Value": 0, + "Color": "^AAAAAA", + "Record": "2020-01-01 00:00:00" + }, + "Medal": { + "Value": 0, + "Color": "^FFDD00", + "Record": "2020-01-01 00:00:00" + }, + "Merit": { + "Value": 0, + "Color": "^FFFF00", + "Record": "2020-01-01 00:00:00" + }, + "GuildCoin": { + "Value": 0, + "Color": "^AAAAAA", + "Record": "2020-01-01 00:00:00" + }, + "ResearchPercent": { + "Value": 0, + "Limit": 100, + "Color": "^00AA00", + "Record": "2020-01-01 00:00:00" + }, + "PlayerLevel": { + "Value": 0, + "Color": "^FFAA33", + "Record": "2020-01-01 00:00:00" + }, + "PlayerExp": { + "Value": 0, + "Limit": 0, + "Color": "^FFAA33", + "Record": "2020-01-01 00:00:00" + }, + "Storage": { + "Storage": {} + } + }, "Alas": { "Emulator": { "Serial": "auto", @@ -104,6 +189,7 @@ "GameLibDir": null }, "Misc": { + "GlobalSpeedup": 1.0, "ChapterMove": false, "OpsiMove": false, "RemoveHardMapLimit": "disable", @@ -2702,90 +2788,5 @@ "Storage": { "Storage": {} } - }, - "Dashboard": { - "Oil": { - "Value": 0, - "Limit": 0, - "Color": "^000000", - "Record": "2020-01-01 00:00:00" - }, - "Coin": { - "Value": 0, - "Limit": 0, - "Color": "^FFAA33", - "Record": "2020-01-01 00:00:00" - }, - "Gem": { - "Value": 0, - "Color": "^FF3333", - "Record": "2020-01-01 00:00:00" - }, - "Pt": { - "Value": 0, - "Color": "^00BFFF", - "Record": "2020-01-01 00:00:00" - }, - "Cube": { - "Value": 0, - "Color": "^33FFFF", - "Record": "2020-01-01 00:00:00" - }, - "ActionPoint": { - "Value": 0, - "Total": 0, - "Color": "^0000FF", - "Record": "2020-01-01 00:00:00" - }, - "YellowCoin": { - "Value": 0, - "Color": "^FF8800", - "Record": "2020-01-01 00:00:00" - }, - "PurpleCoin": { - "Value": 0, - "Color": "^7700BB", - "Record": "2020-01-01 00:00:00" - }, - "Core": { - "Value": 0, - "Color": "^AAAAAA", - "Record": "2020-01-01 00:00:00" - }, - "Medal": { - "Value": 0, - "Color": "^FFDD00", - "Record": "2020-01-01 00:00:00" - }, - "Merit": { - "Value": 0, - "Color": "^FFFF00", - "Record": "2020-01-01 00:00:00" - }, - "GuildCoin": { - "Value": 0, - "Color": "^AAAAAA", - "Record": "2020-01-01 00:00:00" - }, - "ResearchPercent": { - "Value": 0, - "Limit": 100, - "Color": "^00AA00", - "Record": "2020-01-01 00:00:00" - }, - "PlayerLevel": { - "Value": 0, - "Color": "^FFAA33", - "Record": "2020-01-01 00:00:00" - }, - "PlayerExp": { - "Value": 0, - "Limit": 0, - "Color": "^FFAA33", - "Record": "2020-01-01 00:00:00" - }, - "Storage": { - "Storage": {} - } } } \ No newline at end of file diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 68e302fde..5d8ac4d39 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -1,4 +1,274 @@ { + "Dashboard": { + "Oil": { + "Value": { + "type": "input", + "value": 0 + }, + "Limit": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^000000", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Coin": { + "Value": { + "type": "input", + "value": 0 + }, + "Limit": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^FFAA33", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Gem": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^FF3333", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Pt": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^00BFFF", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Cube": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^33FFFF", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "ActionPoint": { + "Value": { + "type": "input", + "value": 0 + }, + "Total": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^0000FF", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "YellowCoin": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^FF8800", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "PurpleCoin": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^7700BB", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Core": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^AAAAAA", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Medal": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^FFDD00", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Merit": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^FFFF00", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "GuildCoin": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^AAAAAA", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "ResearchPercent": { + "Value": { + "type": "input", + "value": 0 + }, + "Limit": { + "type": "input", + "value": 100 + }, + "Color": { + "type": "input", + "value": "^00AA00", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "PlayerLevel": { + "Value": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^FFAA33", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "PlayerExp": { + "Value": { + "type": "input", + "value": 0 + }, + "Limit": { + "type": "input", + "value": 0 + }, + "Color": { + "type": "input", + "value": "^FFAA33", + "display": "hide" + }, + "Record": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + } + }, + "Storage": { + "Storage": { + "type": "storage", + "value": {}, + "valuetype": "ignore", + "display": "disabled" + } + } + }, "Alas": { "Emulator": { "Serial": { @@ -520,6 +790,10 @@ } }, "Misc": { + "GlobalSpeedup": { + "type": "input", + "value": 1.0 + }, "ChapterMove": { "type": "checkbox", "value": false @@ -13586,275 +13860,5 @@ "display": "disabled" } } - }, - "Dashboard": { - "Oil": { - "Value": { - "type": "input", - "value": 0 - }, - "Limit": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^000000", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Coin": { - "Value": { - "type": "input", - "value": 0 - }, - "Limit": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^FFAA33", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Gem": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^FF3333", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Pt": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^00BFFF", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Cube": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^33FFFF", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "ActionPoint": { - "Value": { - "type": "input", - "value": 0 - }, - "Total": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^0000FF", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "YellowCoin": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^FF8800", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "PurpleCoin": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^7700BB", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Core": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^AAAAAA", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Medal": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^FFDD00", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Merit": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^FFFF00", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "GuildCoin": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^AAAAAA", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "ResearchPercent": { - "Value": { - "type": "input", - "value": 0 - }, - "Limit": { - "type": "input", - "value": 100 - }, - "Color": { - "type": "input", - "value": "^00AA00", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "PlayerLevel": { - "Value": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^FFAA33", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "PlayerExp": { - "Value": { - "type": "input", - "value": 0 - }, - "Limit": { - "type": "input", - "value": 0 - }, - "Color": { - "type": "input", - "value": "^FFAA33", - "display": "hide" - }, - "Record": { - "type": "datetime", - "value": "2020-01-01 00:00:00", - "validate": "datetime" - } - }, - "Storage": { - "Storage": { - "type": "storage", - "value": {}, - "valuetype": "ignore", - "display": "disabled" - } - } } } \ No newline at end of file diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index d14ecb96f..c348e7e2e 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -196,6 +196,7 @@ FakePlayer: Level: "" Id: "" Misc: + GlobalSpeedup: 1.0 ChapterMove: false OpsiMove: false RemoveHardMapLimit: diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 64c26fa47..e4590c3d9 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -117,6 +117,7 @@ class GeneratedConfig: FakePlayer_Id = None # Group `Misc` + Misc_GlobalSpeedup = 1.0 Misc_ChapterMove = False Misc_OpsiMove = False Misc_RemoveHardMapLimit = 'disable' # disable, remove_ship_properties_limit, remove_ship_type_limit, remove_both diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 473c7660c..36a1c4dda 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -892,6 +892,10 @@ "name": "Misc._info.name", "help": "Misc._info.help" }, + "GlobalSpeedup": { + "name": "Misc.GlobalSpeedup.name", + "help": "Misc.GlobalSpeedup.help" + }, "ChapterMove": { "name": "Misc.ChapterMove.name", "help": "Misc.ChapterMove.help" diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index 406c1754d..7555ffc7c 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -892,6 +892,10 @@ "name": "Misc._info.name", "help": "Misc._info.help" }, + "GlobalSpeedup": { + "name": "Misc.GlobalSpeedup.name", + "help": "Misc.GlobalSpeedup.help" + }, "ChapterMove": { "name": "Misc.ChapterMove.name", "help": "Misc.ChapterMove.help" diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 88cbc382c..86b834f91 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -892,6 +892,10 @@ "name": "杂项", "help": "" }, + "GlobalSpeedup": { + "name": "全局加速", + "help": "1表示不使用,不要开太高!" + }, "ChapterMove": { "name": "章节图移动加速", "help": "" diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 911031935..e8e3a8468 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -892,6 +892,10 @@ "name": "Misc._info.name", "help": "Misc._info.help" }, + "GlobalSpeedup": { + "name": "Misc.GlobalSpeedup.name", + "help": "Misc.GlobalSpeedup.help" + }, "ChapterMove": { "name": "Misc.ChapterMove.name", "help": "Misc.ChapterMove.help" diff --git a/module/luahook/api.py b/module/luahook/api.py index c6758898c..1941fad69 100644 --- a/module/luahook/api.py +++ b/module/luahook/api.py @@ -44,6 +44,9 @@ class CrackApi: exp: int curr_star: int + class GlobalSpeedupRate(BaseModel): + rate: float + def __init__(self, base_url): self.api_url = base_url @@ -231,5 +234,11 @@ class CrackApi: def disable_opsi_fast_move(self): self.post("disable_opsi_fast_move") + def enable_global_speedup(self, rate: GlobalSpeedupRate): + self.post("enable_global_speedup", data=rate.json()) + + def disable_global_speedup(self): + self.post("disable_global_speedup") + def is_alive(self): self.post("is_alive") diff --git a/module/luahook/crack.py b/module/luahook/crack.py index 8653d055f..092906cfc 100644 --- a/module/luahook/crack.py +++ b/module/luahook/crack.py @@ -27,6 +27,7 @@ ALL_ENABLE_OPS = [ CrackOp.EnableRemoveHardModeShipTypeLimit, CrackOp.EnableRemoveHardModeShipPropertiesLimit, CrackOp.EnableGGFactor, + CrackOp.EnableGlobalSpeedup, ] REMOTE_PORT = 23897 @@ -156,6 +157,13 @@ def do_crack_op(config: AzurLaneConfig, device: Device, ops: Union[Type[CrackOp. api.enable_gg_factor() elif op == CrackOp.DisableGGFactor: api.disable_gg_factor() + elif op == CrackOp.EnableGlobalSpeedup: + rate = float(deep_get(config.data, "Hook.Misc.GlobalSpeedup", 1.0)) + if rate == 1.0: + continue + api.enable_global_speedup(CrackApi.GlobalSpeedupRate(rate=rate)) + elif op == CrackOp.DisableGlobalSpeedup: + api.disable_global_speedup() else: logger.error(f"Unsupported op: {op}") @@ -204,6 +212,7 @@ CHAPTER_CRACK_OPS = [ CrackOp.EnableRemoveHardModeLimit, CrackOp.EnableFakePlayer, CrackOp.EnableGGFactor, + CrackOp.EnableGlobalSpeedup, ] @@ -222,6 +231,7 @@ OPSI_CRACK_OPS = [ CrackOp.EnableGlobalShipProperties, CrackOp.EnableFakePlayer, CrackOp.EnableGGFactor, + CrackOp.EnableGlobalSpeedup, ] diff --git a/module/luahook/op.py b/module/luahook/op.py index 03aa14f6d..37a6c9b13 100644 --- a/module/luahook/op.py +++ b/module/luahook/op.py @@ -50,6 +50,12 @@ class CrackOp: class DisableFakePlayer(Op): ... + class EnableGlobalSpeedup(Op): + ... + + class DisableGlobalSpeedup(Op): + ... + class EnableNoBBAnimation(Op): ...