#include "cracker.hpp" #include #include #include #include #include "utils.hpp" Cracker::Cracker() : m_state(lua_newthread(Utils::get_lua_state())) { Lua::Table proxies = m_state["pg"]["proxyRegister"]["data"]; for (int i = 1; i <= proxies.size(); ++i) { Lua::Table proxy = proxies[i]; std::string proxy_name = proxy["proxyName"]; if (proxy_name == "PlayerProxy") { Lua::Table proxy_map = proxy["facade"]["model"]["proxyMap"]; m_data_proxy.player = proxy_map["PlayerProxy"]; m_data_proxy.dock = proxy_map["BayProxy"]; m_data_proxy.storage = proxy_map["BagProxy"]; } else if (proxy_name == "WorldProxy") { m_data_proxy.world = proxy["facade"]["model"]["proxyMap"]["WorldProxy"]; } } m_lua_res.Ship_getIntimacyLevel = m_state["Ship"]["getIntimacyLevel"]; m_lua_res.pg_intimacy_template = m_state["pg"]["intimacy_template"]; Lua::Table AttributeType = m_state["AttributeType"]; m_lua_res.AttributeType = { .Durability = AttributeType.get("Durability"), .Cannon = AttributeType.get("Cannon"), .Torpedo = AttributeType.get("Torpedo"), .AntiAircraft = AttributeType.get("AntiAircraft"), .AntiSub = AttributeType.get("AntiSub"), .Air = AttributeType.get("Air"), .Reload = AttributeType.get("Reload"), .Hit = AttributeType.get("Hit"), .Dodge = AttributeType.get("Dodge"), }; } Cracker& Cracker::Instance() { static auto* instance = new Cracker; return *instance; } int Cracker::get_coin() { double coin = m_data_proxy.player["data"]["gold"]; return static_cast(coin); } int Cracker::get_oil() { double oil = m_data_proxy.player["data"]["oil"]; return static_cast(oil); } int Cracker::get_gems() { double gems = m_data_proxy.player["data"]["awardGem"]; return static_cast(gems); } int Cracker::get_level() { double level = m_data_proxy.player["data"]["level"]; return static_cast(level); } int Cracker::get_exp() { double exp = m_data_proxy.player["data"]["exp"]; return static_cast(exp); } int Cracker::get_merit() { double merit = m_data_proxy.player["data"]["exploit"]; return static_cast(merit); } int Cracker::get_guild_coin() { double guild_coin = m_data_proxy.player["data"]["guildCoin"]; return static_cast(guild_coin); } int Cracker::get_design_prt() { double design_prt = m_data_proxy.player["data"]["design_prt"]; return static_cast(design_prt); } #define CORE_DATA_ITEM_ID 59900 int Cracker::get_core_data() { Lua::Table storage = m_data_proxy.storage["data"]; double core_data = storage.get(CORE_DATA_ITEM_ID)["count"]; return static_cast(core_data); } #define MEDAL_ITEM_ID 15001 int Cracker::get_medal() { Lua::Table storage = m_data_proxy.storage["data"]; double medal = storage.get(MEDAL_ITEM_ID)["count"]; return static_cast(medal); } int Cracker::get_pt() { double pt = m_data_proxy.player["data"]["pt"]; return static_cast(pt); } #define SPECIALIZED_CORE_ITEM_ID 59010 int Cracker::get_specialized_core() { Lua::Table storage = m_data_proxy.storage["data"]; double specialized_core = storage.get(SPECIALIZED_CORE_ITEM_ID)["count"]; return static_cast(specialized_core); } int Cracker::get_curr_action_point() { double curr_action_point = m_data_proxy.world["world"]["fields"]["staminaMgr"]["fields"]["stamina"]; return static_cast(curr_action_point); } std::map Cracker::scan_dock() { std::map ships; Lua::Table dock = m_data_proxy.dock["data"]; for (auto& [ship_id, ship_info] : dock) { Lua::Table ship_data = ship_info.as(); double id = ship_data["id"]; ships[static_cast(id)] = { .config_id = static_cast(ship_data.get("configId")), .emotion = static_cast(ship_data.get("energy")), .rarity = static_cast(ship_data.get("star")), .level = static_cast(ship_data.get("level")), .exp = static_cast(ship_data.get("exp")), .curr_star = static_cast(ship_data.get("state")), }; } return ships; } std::map Cracker::scan_storage() { std::map items; Lua::Table storage = m_data_proxy.storage["data"]; for (auto& [item_id, item_info] : storage) { Lua::Table item_data = item_info.as(); double config_id = item_data["configId"]; double count = item_data["count"]; items[static_cast(config_id)] = static_cast(count); } return items; } std::optional Cracker::get_ship_info(ShipId ship_id) { double id = static_cast(ship_id); Lua::Table dock = m_data_proxy.dock["data"]; try { Lua::Table ship_data = dock.get(id); return ShipInfo{ .config_id = static_cast(ship_data.get("configId")), .emotion = static_cast(ship_data.get("energy")), .rarity = static_cast(ship_data.get("star")), .level = static_cast(ship_data.get("level")), .exp = static_cast(ship_data.get("exp")), .curr_star = static_cast(ship_data.get("state")), }; } catch (const std::exception& e) { return std::nullopt; } return std::nullopt; } std::optional Cracker::get_storage_item_count(StorageItemId item_id) { double id = static_cast(item_id); Lua::Table storage = m_data_proxy.storage["data"]; try { Lua::Table item_data = storage.get(id); return static_cast(item_data.get("count")); } catch (const std::exception& e) { return std::nullopt; } return std::nullopt; } void Cracker::disable_all() { disable_global_ship_properties_crack(); disable_fast_stage_move(); disable_remove_hard_mode_ship_properties_limit(); disable_remove_hard_mode_ship_type_limit(); disable_fake_player(); disable_no_bb_animation(); disable_no_emotion_warning(); disable_opsi_fast_move(); disable_gg_factor(); } void Cracker::enable_gg_factor() { if (is_enabled(GG_FACTOR)) { return; } m_original.Ship_intimacyAdditions = m_state["Ship"]["intimacyAdditions"]; m_state["Ship"]["intimacyAdditions"] = [this](Lua::VariadicArgs args) -> Lua::Object { Lua::Table self = args[0]; int intimacy_level = m_lua_res.Ship_getIntimacyLevel(self); Lua::Table attr_bonus_table = m_lua_res.pg_intimacy_template.get(intimacy_level); double attr_bonus = attr_bonus_table.get("attr_bonus"); double calculated_attr_bonus = attr_bonus * 0.0001; Lua::Table attributes = args[1]; for (auto& [attr_name, attr_value] : attributes) { if (attr_name.get_type() == sol::type::string) { std::string attr_name_str = attr_name.as(); const auto& attr = m_lua_res.AttributeType; if ( attr_name_str == attr.Durability || attr_name_str == attr.Cannon || attr_name_str == attr.Torpedo || attr_name_str == attr.AntiAircraft || attr_name_str == attr.AntiSub || attr_name_str == attr.Air || attr_name_str == attr.Reload || attr_name_str == attr.Hit || attr_name_str == attr.Dodge ) { double old_value = attributes[attr_name_str]; attributes[attr_name_str] = old_value * (calculated_attr_bonus + m_gg_factor); } } } return sol::nil; }; enable_flag(GG_FACTOR); } void Cracker::disable_gg_factor() { if (is_disabled(GG_FACTOR)) { return; } m_state["Ship"]["intimacyAdditions"] = m_original.Ship_intimacyAdditions; disable_flag(GG_FACTOR); } void Cracker::update_gg_factor(double factor) { m_gg_factor = factor; } void Cracker::enable_opsi_fast_move() { if (is_enabled(OPSI_FAST_MOVE)) { return; } m_original.WorldConst_BaseMoveDuration = m_state["WorldConst"]["BaseMoveDuration"]; m_state["WorldConst"]["BaseMoveDuration"] = 0.0; enable_flag(OPSI_FAST_MOVE); } void Cracker::disable_opsi_fast_move() { if (is_disabled(OPSI_FAST_MOVE)) { return; } m_state["WorldConst"]["BaseMoveDuration"] = m_original.WorldConst_BaseMoveDuration; disable_flag(OPSI_FAST_MOVE); } void Cracker::enable_no_emotion_warning() { if (is_enabled(NO_EMOTION_WARNING)) { return; } m_original.Ship_cosumeEnergy = m_state["Ship"]["cosumeEnergy"]; m_original.Ship_getEnergy = m_state["Ship"]["getEnergy"]; m_state["Ship"]["cosumeEnergy"] = [](Lua::VariadicArgs args) -> Lua::Object { return sol::nil; }; m_state["Ship"]["getEnergy"] = [](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object { return sol::make_object(L, 150); }; enable_flag(NO_EMOTION_WARNING); } void Cracker::disable_no_emotion_warning() { if (is_disabled(NO_EMOTION_WARNING)) { return; } m_state["Ship"]["cosumeEnergy"] = m_original.Ship_cosumeEnergy; m_state["Ship"]["getEnergy"] = m_original.Ship_getEnergy; disable_flag(NO_EMOTION_WARNING); } void Cracker::enable_no_bb_animation() { if (is_enabled(NO_BB_ANIMATION)) { return; } m_original.ys_Battle_BattleManualWeaponAutoBot_SetActive = m_state["ys"]["Battle"]["BattleManualWeaponAutoBot"]["SetActive"]; m_state["ys"]["Battle"]["BattleManualWeaponAutoBot"]["SetActive"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object { std::vector new_args(args.begin(), args.end()); new_args[2] = sol::make_object(L, false); Lua::Object res = m_original.ys_Battle_BattleManualWeaponAutoBot_SetActive(sol::as_args(new_args)); return res; }; enable_flag(NO_BB_ANIMATION); } void Cracker::disable_no_bb_animation() { if (is_disabled(NO_BB_ANIMATION)) { return; } m_state["ys"]["Battle"]["BattleManualWeaponAutoBot"]["SetActive"] = m_original.ys_Battle_BattleManualWeaponAutoBot_SetActive; disable_flag(NO_BB_ANIMATION); } void Cracker::enable_fake_player() { if (is_enabled(FAKE_PLAYER_INFO)) { return; } m_original.PlayerVitaeDetailPage_UpdateInfo = m_state["PlayerVitaeDetailPage"]["UpdateInfo"]; m_state["PlayerVitaeDetailPage"]["UpdateInfo"] = [this](Lua::VariadicArgs args) -> Lua::Object { Lua::Object res = m_original.PlayerVitaeDetailPage_UpdateInfo(args); Lua::Table t = args[0]; if (!m_fake_player_info.name.empty()) { t["nameTxt"]["text"] = m_fake_player_info.name; } if (!m_fake_player_info.level.empty()) { t["levelTxt"]["text"] = "LV." + m_fake_player_info.level; } if (!m_fake_player_info.id.empty()) { t["idTxt"]["text"] = m_fake_player_info.id; } return res; }; enable_flag(FAKE_PLAYER_INFO); } void Cracker::disable_fake_player() { if (is_disabled(FAKE_PLAYER_INFO)) { return; } m_state["PlayerVitaeDetailPage"]["UpdateInfo"] = m_original.PlayerVitaeDetailPage_UpdateInfo; disable_flag(FAKE_PLAYER_INFO); } void Cracker::update_fake_player_info(const FakePlayerInfo& fake_info) { m_fake_player_info = fake_info; } void Cracker::enable_remove_hard_mode_ship_type_limit() { if (is_enabled(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT)) { return; } m_original.Chapter_getConfig = m_state["Chapter"]["getConfig"]; m_state["Chapter"]["getConfig"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object { Lua::Object first_arg = args[1]; bool limitation = false; if (first_arg.get_type() == sol::type::string && first_arg.as() == "limitation") { limitation = true; } Lua::Object res = m_original.Chapter_getConfig(args); if (limitation) { sol::table table = res; clear_hard_mode_ship_properties_limit(table); } return res; }; enable_flag(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT); } void Cracker::disable_remove_hard_mode_ship_type_limit() { if (is_disabled(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT)) { return; } m_state["Chapter"]["getConfig"] = m_original.Chapter_getConfig; disable_flag(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT); } void Cracker::enable_remove_hard_mode_ship_properties_limit() { if (is_enabled(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)) { return; } m_original.WorldFleetSelectLayer_CheckValid = m_state["WorldFleetSelectLayer"]["CheckValid"]; m_original.BossSingleBattleFleetSelectSubPanel_CheckValid = m_state["BossSingleBattleFleetSelectSubPanel"]["CheckValid"]; m_original.Chapter_IsEliteFleetLegal = m_state["Chapter"]["IsEliteFleetLegal"]; m_state["WorldFleetSelectLayer"]["CheckValid"] = [](Lua::VariadicArgs args) -> bool { return true; }; m_state["BossSingleBattleFleetSelectSubPanel"]["CheckValid"] = [](Lua::VariadicArgs args) -> bool { return true; }; m_state["Chapter"]["IsEliteFleetLegal"] = [](Lua::VariadicArgs args) -> bool { return true; }; enable_flag(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT); } void Cracker::disable_remove_hard_mode_ship_properties_limit() { if (is_disabled(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)) { return; } m_state["WorldFleetSelectLayer"]["CheckValid"] = m_original.WorldFleetSelectLayer_CheckValid; m_state["BossSingleBattleFleetSelectSubPanel"]["CheckValid"] = m_original.BossSingleBattleFleetSelectSubPanel_CheckValid; m_state["Chapter"]["IsEliteFleetLegal"] = m_original.Chapter_IsEliteFleetLegal; disable_flag(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT); } void Cracker::enable_fast_stage_move() { if (is_enabled(FAST_STAGE_MOVE_CRACK)) { return; } m_original.ChapterConst_ShipStepDuration = m_state["ChapterConst"]["ShipStepDuration"]; m_original.ChapterConst_ShipStepQuickPlayScale = m_state["ChapterConst"]["ShipStepQuickPlayScale"]; m_state["ChapterConst"]["ShipStepDuration"] = 0.0; m_state["ChapterConst"]["ShipStepQuickPlayScale"] = 0.0; enable_flag(FAST_STAGE_MOVE_CRACK); } void Cracker::disable_fast_stage_move() { if (is_disabled(FAST_STAGE_MOVE_CRACK)) { return; } m_state["ChapterConst"]["ShipStepDuration"] = m_original.ChapterConst_ShipStepDuration; m_state["ChapterConst"]["ShipStepQuickPlayScale"] = m_original.ChapterConst_ShipStepQuickPlayScale; disable_flag(FAST_STAGE_MOVE_CRACK); } void Cracker::update_global_ship_properties(const ShipProperties& properties) { m_globle_ship_properties = properties; } void Cracker::enable_global_ship_properties_crack() { if (is_enabled(GLOBAL_SHIP_PROPERTIES_CRACK)) { return; } m_original.Ship_getShipProperties = m_state["Ship"]["getShipProperties"]; m_state["Ship"]["getShipProperties"] = [this](Lua::VariadicArgs args) -> Lua::Object { Lua::Table properties = m_original.Ship_getShipProperties(args); modify_ship_properties(properties, m_globle_ship_properties); return properties; }; enable_flag(GLOBAL_SHIP_PROPERTIES_CRACK); } void Cracker::disable_global_ship_properties_crack() { if (is_disabled(GLOBAL_SHIP_PROPERTIES_CRACK)) { return; } m_state["Ship"]["getShipProperties"] = m_original.Ship_getShipProperties; disable_flag(GLOBAL_SHIP_PROPERTIES_CRACK); } bool Cracker::is_enabled(FunctionId id) { return m_functions.contains(id) ? m_functions[id] : false; } bool Cracker::is_disabled(FunctionId id) { return !is_enabled(id); } void Cracker::print_table_field(std::vector& path) { Lua::Table t = m_state.globals(); for (const auto& p : path) { t = t[p]; } Utils::Lua::print_table_fields_type(t); } void Cracker::print_value(std::vector& path) { Lua::Table t = m_state.globals(); for (auto it = path.begin(); it != path.end() - 1; ++it) { t = t[*it]; } std::string key = path.back(); Lua::Object value = t[key]; auto type = value.get_type(); if (type == sol::type::number) { SPDLOG_INFO("value: {}", value.as()); } else if (type == sol::type::string) { SPDLOG_INFO("value: {}", value.as()); } else if (type == sol::type::boolean) { SPDLOG_INFO("value: {}", value.as()); } else if (type == sol::type::nil) { SPDLOG_INFO("value: nil"); } else if (type == sol::type::table) { Lua::Table table = value.as(); Utils::Lua::print_table_fields_type(table); } } void Cracker::enable_flag(FunctionId id) { m_functions[id] = true; } void Cracker::disable_flag(FunctionId id) { m_functions[id] = false; } #define MODIFY_PROPERTY(name) \ if (new_properties.name != -1) { \ properties[#name] = new_properties.name; \ } void Cracker::modify_ship_properties(Lua::Table& properties, const ShipProperties& new_properties) { MODIFY_PROPERTY(armor) MODIFY_PROPERTY(speed) MODIFY_PROPERTY(antiaircraft) MODIFY_PROPERTY(oxy_recovery_bench) MODIFY_PROPERTY(torpedo) MODIFY_PROPERTY(hit) MODIFY_PROPERTY(sonarRange) MODIFY_PROPERTY(attack_duration) MODIFY_PROPERTY(raid_distance) MODIFY_PROPERTY(oxy_recovery_surface) MODIFY_PROPERTY(oxy_recovery) MODIFY_PROPERTY(dodge) MODIFY_PROPERTY(luck) MODIFY_PROPERTY(reload) MODIFY_PROPERTY(oxy_cost) MODIFY_PROPERTY(durability) MODIFY_PROPERTY(air) MODIFY_PROPERTY(oxy_max) MODIFY_PROPERTY(cannon) MODIFY_PROPERTY(antisub) } void Cracker::clear_hard_mode_ship_properties_limit(Lua::Table& t) { for (int i = 1, n = t.size(); i <= n; ++i) { sol::table fleet = t[i]; for (int j = 1, m = fleet.size(); j <= m; ++j) { sol::table team = fleet[j]; for (int k = 1, l = team.size(); k <= l; ++k) { team[k] = 0.0; } } } }