From 4fdf720c58c470c604ab53437c7951f2c8531b88 Mon Sep 17 00:00:00 2001 From: 0O0o0oOoO00 <11174151+0O0o0oOoO00@users.noreply.github.com> Date: Sun, 16 Nov 2025 20:30:15 +0800 Subject: [PATCH] add: chapter auto ambush --- blcrack/cracker/cracker.cpp | 56 ++++++++++++++++++++++++++ blcrack/cracker/cracker.hpp | 8 ++++ blcrack/cracker/server.cpp | 22 ++++++++++ blcrack/cracker/ui/ui.cpp | 1 + blcrack/http/cracker.http | 6 +++ config/template.json | 3 +- module/config/argument/args.json | 4 ++ module/config/argument/argument.yaml | 1 + module/config/config_generated.py | 1 + module/config/full_config_generated.py | 1 + module/config/i18n/en-US.json | 4 ++ module/config/i18n/ja-JP.json | 4 ++ module/config/i18n/zh-CN.json | 4 ++ module/config/i18n/zh-TW.json | 4 ++ module/luahook/api.py | 6 +++ module/luahook/crack.py | 7 ++++ module/luahook/op.py | 6 +++ 17 files changed, 137 insertions(+), 1 deletion(-) diff --git a/blcrack/cracker/cracker.cpp b/blcrack/cracker/cracker.cpp index 5821a9a60..1756e752f 100644 --- a/blcrack/cracker/cracker.cpp +++ b/blcrack/cracker/cracker.cpp @@ -249,6 +249,7 @@ void Cracker::disable_all() { disable_chapter_force_enable_auto_fight(); disable_chapter_skip_precombat(); disable_chapter_auto_next_battle(); + disable_chapter_auto_ambush(); } void Cracker::enable_hooked_lua_function_trace() { @@ -283,6 +284,14 @@ void Cracker::disable_chapter_force_enable_auto_fight() { DISABLE(CHAPTER_FORCE_ENABLE_AUTO_FIGHT); } +void Cracker::enable_chapter_auto_ambush() { + ENABLE(CHAPTER_AUTO_AMBUSH); +} + +void Cracker::disable_chapter_auto_ambush() { + DISABLE(CHAPTER_AUTO_AMBUSH); +} + void Cracker::enable_skip_ship_gain_show() { ENABLE(SKIP_SHIP_GAIN_SHOW); } @@ -564,6 +573,8 @@ void Cracker::load_lua_resources() { m_lua_res.ChapterProxy = m_state["ChapterProxy"]; m_lua_res.ChapterProxy_GetChapterAutoFlag = m_state["ChapterProxy"]["GetChapterAutoFlag"]; m_lua_res.ChapterProxy_SetChapterAutoFlag = m_state["ChapterProxy"]["SetChapterAutoFlag"]; + m_lua_res.Chapter_getChapterCell = m_state["Chapter"]["getChapterCell"]; + m_lua_res.LevelStageView_emit = m_state["LevelStageView"]["emit"]; SPDLOG_INFO("Load lua functions"); m_original.GetBattleCheckResult = m_state["GetBattleCheckResult"]; @@ -599,11 +610,49 @@ void Cracker::load_lua_resources() { m_original.Chapter_IsAutoFight = m_state["Chapter"]["IsAutoFight"]; m_original.Chapter_IsSkipPrecombat = m_state["Chapter"]["IsSkipPrecombat"]; m_original.Chapter_writeBack = m_state["Chapter"]["writeBack"]; + m_original.LevelStageView_tryAutoTrigger = m_state["LevelStageView"]["tryAutoTrigger"]; } void Cracker::hook_all_lua_functions() { SPDLOG_INFO("Hook lua functions"); + // chapter_auto_ambush + m_state["LevelStageView"]["tryAutoTrigger"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object { + CALLED(LevelStageView.tryAutoTrigger); + if (!IS_ENABLED(CHAPTER_AUTO_AMBUSH)) { + return m_original.LevelStageView_tryAutoTrigger(L, args); + } + + Lua::Table self = args[0]; + std::optional chapterVO = self["contextData"]["chapterVO"]; + + if (chapterVO.has_value()) { + auto& vo = chapterVO.value(); + Lua::Object row = vo["fleet"]["line"]["row"]; + Lua::Object column = vo["fleet"]["line"]["column"]; + + std::optional cell = m_lua_res.Chapter_getChapterCell(L, vo, row, column); + if (cell.has_value()) { + auto& cell_v = cell.value(); + int attachment = cell_v["attachment"]; + int flag = cell_v["flag"]; + + if (attachment == 5 && flag == 2) { + Lua::Table trigger_arg = m_state.create_table(); + + int fleet_id = vo["fleet"]["id"]; + trigger_arg["type"] = 4; + trigger_arg["id"] = fleet_id; + trigger_arg["arg1"] = 1; + + m_lua_res.LevelStageView_emit(L, self, sol::make_object(L, "LevelMediator2:ON_OP"), trigger_arg); + return sol::make_object(L, true); + } + } + } + return m_original.LevelStageView_tryAutoTrigger(L, args); + }; + // chapter_auto_next_battle m_state["Chapter"]["writeBack"] = [this](sol::this_state L, Lua::VariadicArgs args) { CALLED(Chapter.writeBack); @@ -1289,6 +1338,7 @@ Cracker::Config Cracker::get_config() { SET_CONFIG_FLAG(CHAPTER_FORCE_ENABLE_AUTO_FIGHT), SET_CONFIG_FLAG(CHAPTER_SKIP_PRECOMBAT), SET_CONFIG_FLAG(CHAPTER_AUTO_NEXT_BATTLE), + SET_CONFIG_FLAG(CHAPTER_AUTO_AMBUSH), }, .globle_ship_properties = m_globle_ship_properties, .global_speedup_rate = static_cast(m_global_speedup_rate), @@ -1308,6 +1358,12 @@ void Cracker::apply_config(Config& config) { disable_hooked_lua_function_trace(); } + if(IS_CONFIG_ENABLED(CHAPTER_AUTO_AMBUSH)) { + enable_chapter_auto_ambush(); + } else { + disable_chapter_auto_ambush(); + } + if(IS_CONFIG_ENABLED(CHAPTER_SKIP_PRECOMBAT)) { enable_chapter_skip_precombat(); } else { diff --git a/blcrack/cracker/cracker.hpp b/blcrack/cracker/cracker.hpp index 2451814b5..1e3c6f224 100644 --- a/blcrack/cracker/cracker.hpp +++ b/blcrack/cracker/cracker.hpp @@ -94,6 +94,7 @@ public: bool CHAPTER_FORCE_ENABLE_AUTO_FIGHT = false; bool CHAPTER_SKIP_PRECOMBAT = false; bool CHAPTER_AUTO_NEXT_BATTLE = false; + bool CHAPTER_AUTO_AMBUSH = false; } flag; ShipProperties globle_ship_properties; int global_speedup_rate = 1; @@ -141,6 +142,9 @@ public: void enable_chapter_force_enable_auto_fight(); void disable_chapter_force_enable_auto_fight(); + void enable_chapter_auto_ambush(); + void disable_chapter_auto_ambush(); + void enable_skip_ship_gain_show(); void disable_skip_ship_gain_show(); @@ -251,6 +255,7 @@ private: std::atomic CHAPTER_FORCE_ENABLE_AUTO_FIGHT = false; std::atomic CHAPTER_SKIP_PRECOMBAT = false; std::atomic CHAPTER_AUTO_NEXT_BATTLE = false; + std::atomic CHAPTER_AUTO_AMBUSH = false; } m_flag; struct { @@ -295,6 +300,7 @@ private: Lua::Function Chapter_IsAutoFight; Lua::Function Chapter_IsSkipPrecombat; Lua::Function Chapter_writeBack; + Lua::Function LevelStageView_tryAutoTrigger; } m_original; struct { Lua::Function Clone; @@ -317,6 +323,8 @@ private: Lua::Table ChapterProxy; Lua::Function ChapterProxy_GetChapterAutoFlag; Lua::Function ChapterProxy_SetChapterAutoFlag; + Lua::Function Chapter_getChapterCell; + Lua::Function LevelStageView_emit; } m_lua_res; std::atomic m_exercise_more_power_rate = 0.03; FakePlayerInfo m_fake_player_info; diff --git a/blcrack/cracker/server.cpp b/blcrack/cracker/server.cpp index f303f7baa..4a93a0b5f 100644 --- a/blcrack/cracker/server.cpp +++ b/blcrack/cracker/server.cpp @@ -982,6 +982,28 @@ CrackerServer::CrackerServer() { CRACK_OK(); }); + Post("/enable_chapter_auto_ambush", [](const httplib::Request& req, httplib::Response& res) { + try { + Cracker::Instance().enable_chapter_auto_ambush(); + } catch (std::exception& e) { + SPDLOG_ERROR("Enable chapter auto ambush failed: {}", e.what()); + res.status = 500; + return; + } + CRACK_OK(); + }); + + Post("/disable_chapter_auto_ambush", [](const httplib::Request& req, httplib::Response& res) { + try { + Cracker::Instance().disable_chapter_auto_ambush(); + } catch (std::exception& e) { + SPDLOG_ERROR("Disable chapter auto ambush failed: {}", e.what()); + res.status = 500; + return; + } + CRACK_OK(); + }); + Post("/init", [](const httplib::Request& req, httplib::Response& res) { try { Cracker::Instance(); diff --git a/blcrack/cracker/ui/ui.cpp b/blcrack/cracker/ui/ui.cpp index 58a4bdb21..9d9e80e82 100644 --- a/blcrack/cracker/ui/ui.cpp +++ b/blcrack/cracker/ui/ui.cpp @@ -105,6 +105,7 @@ void CrackerUI::draw_menu() { ImGui::Checkbox("章节图强制开启自动战斗", &CONFIG_FLAG(CHAPTER_FORCE_ENABLE_AUTO_FIGHT)); ImGui::Checkbox("章节图跳过战前准备", &CONFIG_FLAG(CHAPTER_SKIP_PRECOMBAT)); ImGui::Checkbox("演习锁血", &CONFIG_FLAG(EXERCISE_GOD_MOD)); + ImGui::Checkbox("自动规避伏击", &CONFIG_FLAG(CHAPTER_AUTO_AMBUSH)); ImGui::TableNextColumn(); ImGui::Checkbox("移除困难图属性限制", &CONFIG_FLAG(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)); diff --git a/blcrack/http/cracker.http b/blcrack/http/cracker.http index 4918dbf73..ca824362a 100644 --- a/blcrack/http/cracker.http +++ b/blcrack/http/cracker.http @@ -203,6 +203,12 @@ POST http://{{Host}}:{{Port}}/enable_chapter_auto_next_battle ### POST http://{{Host}}:{{Port}}/disable_chapter_auto_next_battle +### +POST http://{{Host}}:{{Port}}/enable_chapter_auto_ambush + +### +POST http://{{Host}}:{{Port}}/disable_chapter_auto_ambush + ### POST http://{{Host}}:{{Port}}/is_alive diff --git a/config/template.json b/config/template.json index 16cd0b57e..997edd295 100644 --- a/config/template.json +++ b/config/template.json @@ -225,7 +225,8 @@ "SkipShipGainShow": false, "ChapterForceEnableAutoFight": false, "ChapterSkipPrecombat": false, - "ChapterAutoNextBattle": false + "ChapterAutoNextBattle": false, + "ChapterAutoAmbush": false }, "ShipProperty": { "Method": "disable", diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 17cc0aed5..c16cfe99d 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -897,6 +897,10 @@ "ChapterAutoNextBattle": { "type": "checkbox", "value": false + }, + "ChapterAutoAmbush": { + "type": "checkbox", + "value": false } }, "ShipProperty": { diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 83612f229..0b7fd72e0 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -890,6 +890,7 @@ Misc: ChapterForceEnableAutoFight: false ChapterSkipPrecombat: false ChapterAutoNextBattle: false + ChapterAutoAmbush: false # ==================== Cheat ==================== PowerLimit: diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 9105e89b6..c51175c1a 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -545,6 +545,7 @@ class GeneratedConfig: Misc_ChapterForceEnableAutoFight = False Misc_ChapterSkipPrecombat = False Misc_ChapterAutoNextBattle = False + Misc_ChapterAutoAmbush = False # Group `PowerLimit` PowerLimit_Enable = True diff --git a/module/config/full_config_generated.py b/module/config/full_config_generated.py index c109f20c8..fc8b091b8 100644 --- a/module/config/full_config_generated.py +++ b/module/config/full_config_generated.py @@ -159,6 +159,7 @@ class FullGeneratedConfig: Hook_Misc_ChapterForceEnableAutoFight = None Hook_Misc_ChapterSkipPrecombat = None Hook_Misc_ChapterAutoNextBattle = None + Hook_Misc_ChapterAutoAmbush = None Hook_ShipProperty_Method = None Hook_ShipProperty_Factor = None Hook_ShipProperty_Armor = None diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 4ce8fd454..c0f9fca25 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -3140,6 +3140,10 @@ "ChapterAutoNextBattle": { "name": "Misc.ChapterAutoNextBattle.name", "help": "Misc.ChapterAutoNextBattle.help" + }, + "ChapterAutoAmbush": { + "name": "Misc.ChapterAutoAmbush.name", + "help": "Misc.ChapterAutoAmbush.help" } }, "PowerLimit": { diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index 092e70d3f..e5a9d5a6b 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -3140,6 +3140,10 @@ "ChapterAutoNextBattle": { "name": "Misc.ChapterAutoNextBattle.name", "help": "Misc.ChapterAutoNextBattle.help" + }, + "ChapterAutoAmbush": { + "name": "Misc.ChapterAutoAmbush.name", + "help": "Misc.ChapterAutoAmbush.help" } }, "PowerLimit": { diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index c10129fac..2f8480495 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -3140,6 +3140,10 @@ "ChapterAutoNextBattle": { "name": "章节图自动下一战", "help": "" + }, + "ChapterAutoAmbush": { + "name": "自动规避伏击", + "help": "" } }, "PowerLimit": { diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 63d2f7cc9..335c49ac3 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -3140,6 +3140,10 @@ "ChapterAutoNextBattle": { "name": "Misc.ChapterAutoNextBattle.name", "help": "Misc.ChapterAutoNextBattle.help" + }, + "ChapterAutoAmbush": { + "name": "Misc.ChapterAutoAmbush.name", + "help": "Misc.ChapterAutoAmbush.help" } }, "PowerLimit": { diff --git a/module/luahook/api.py b/module/luahook/api.py index 70bba6071..4e61d39bd 100644 --- a/module/luahook/api.py +++ b/module/luahook/api.py @@ -349,3 +349,9 @@ class CrackApi: def disable_chapter_auto_next_battle(self): self.post("disable_chapter_auto_next_battle") + + def enable_chapter_auto_ambush(self): + self.post("enable_chapter_auto_ambush") + + def disable_chapter_auto_ambush(self): + self.post("disable_chapter_auto_ambush") diff --git a/module/luahook/crack.py b/module/luahook/crack.py index 2179cc0b0..eb696667e 100644 --- a/module/luahook/crack.py +++ b/module/luahook/crack.py @@ -42,6 +42,7 @@ ALL_ENABLE_OPS = [ CrackOp.EnableChapterForceEnableAutoFight, CrackOp.EnableChapterSkipPrecombat, CrackOp.EnableChapterAutoNextBattle, + CrackOp.EnableChapterAutoAmbush, ] REMOTE_PORT = 23897 @@ -276,6 +277,11 @@ def do_crack_op(config: AzurLaneConfig, device: Device, ops: Union[Type[CrackOp. api.enable_chapter_auto_next_battle() elif op == CrackOp.DisableChapterAutoNextBattle: api.disable_chapter_auto_next_battle() + elif op == CrackOp.EnableChapterAutoAmbush: + if full_config.Hook_Misc_ChapterAutoAmbush: + api.enable_chapter_auto_ambush() + elif op == CrackOp.DisableChapterAutoAmbush: + api.disable_chapter_auto_ambush() else: logger.error(f"Unsupported op: {op}") @@ -331,6 +337,7 @@ CHAPTER_CRACK_OPS = [ CrackOp.EnableChapterForceEnableAutoFight, CrackOp.EnableChapterSkipPrecombat, CrackOp.EnableChapterAutoNextBattle, + CrackOp.EnableChapterAutoAmbush, ] diff --git a/module/luahook/op.py b/module/luahook/op.py index 92605e58d..71582bacd 100644 --- a/module/luahook/op.py +++ b/module/luahook/op.py @@ -160,3 +160,9 @@ class CrackOp: class DisableChapterAutoNextBattle(Op): ... + + class EnableChapterAutoAmbush(Op): + ... + + class DisableChapterAutoAmbush(Op): + ...