1
0
mirror of https://github.com/0O0o0oOoO00/Alas.git synced 2026-05-15 01:09:26 +08:00
Files
Alas/blcrack/cracker/cracker.cpp

1039 lines
37 KiB
C++

#include "cracker.hpp"
#include <lua/lua.hpp>
#include <spdlog/spdlog.h>
#include <sol/as_args.hpp>
#include <sol/sol.hpp>
#include "utils.hpp"
#include "il2cpp.hpp"
using fnset_TimeScaleT = void(*)(float);
static fnset_TimeScaleT get_Time_set_timeScale() {
static fnset_TimeScaleT fn = []() {
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<fnset_TimeScaleT>(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");
}();
return fn;
}
#define IS_ENABLED(f) m_flag.f.load()
#define ENABLE(n) \
SPDLOG_INFO("Enable {}", #n); \
m_flag.n.store(true)
#define DISABLE(n) \
SPDLOG_INFO("Disable {}", #n); \
m_flag.n.store(false)
#ifdef DEBUG_MODE
#define CALLED(f) SPDLOG_INFO("{} called", #f)
#else
#define CALLED(f)
#endif
Cracker::Cracker()
: m_state(lua_newthread(Utils::get_lua_state())) {
try {
load_lua_resources();
hook_all_lua_functions();
} catch(std::exception& e) {
SPDLOG_ERROR("Cracker load error: {}", e.what());
exit(-1);
}
}
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<int>(coin);
}
int Cracker::get_oil() {
double oil = m_data_proxy.player["data"]["oil"];
return static_cast<int>(oil);
}
int Cracker::get_gems() {
double gems = m_data_proxy.player["data"]["awardGem"];
return static_cast<int>(gems);
}
int Cracker::get_level() {
double level = m_data_proxy.player["data"]["level"];
return static_cast<int>(level);
}
int Cracker::get_exp() {
double exp = m_data_proxy.player["data"]["exp"];
return static_cast<int>(exp);
}
int Cracker::get_merit() {
double merit = m_data_proxy.player["data"]["exploit"];
return static_cast<int>(merit);
}
int Cracker::get_guild_coin() {
double guild_coin = m_data_proxy.player["data"]["guildCoin"];
return static_cast<int>(guild_coin);
}
int Cracker::get_design_prt() {
double design_prt = m_data_proxy.player["data"]["design_prt"];
return static_cast<int>(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<Lua::Table>(CORE_DATA_ITEM_ID)["count"];
return static_cast<int>(core_data);
}
#define MEDAL_ITEM_ID 15001
int Cracker::get_medal() {
Lua::Table storage = m_data_proxy.storage["data"];
double medal = storage.get<Lua::Table>(MEDAL_ITEM_ID)["count"];
return static_cast<int>(medal);
}
int Cracker::get_pt() {
double pt = m_data_proxy.player["data"]["pt"];
return static_cast<int>(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<Lua::Table>(SPECIALIZED_CORE_ITEM_ID)["count"];
return static_cast<int>(specialized_core);
}
int Cracker::get_curr_action_point() {
double curr_action_point = m_data_proxy.world["world"]["fields"]["staminaMgr"]["fields"]["stamina"];
return static_cast<int>(curr_action_point);
}
std::map<Cracker::ShipId, Cracker::ShipInfo> Cracker::scan_dock() {
std::map<ShipId, ShipInfo> ships;
Lua::Table dock = m_data_proxy.dock["data"];
for (auto& [ship_id, ship_info] : dock) {
Lua::Table ship_data = ship_info.as<Lua::Table>();
double id = ship_data["id"];
ships[static_cast<ShipId>(id)] = {
.config_id = static_cast<int>(ship_data.get<double>("configId")),
.emotion = static_cast<int>(ship_data.get<double>("energy")),
.rarity = static_cast<int>(ship_data.get<double>("star")),
.level = static_cast<int>(ship_data.get<double>("level")),
.exp = static_cast<int>(ship_data.get<double>("exp")),
.curr_star = static_cast<int>(ship_data.get<double>("state")),
};
}
return ships;
}
std::map<Cracker::StorageItemId, Cracker::StorageItemCount> Cracker::scan_storage() {
std::map<StorageItemId, StorageItemCount> items;
Lua::Table storage = m_data_proxy.storage["data"];
for (auto& [item_id, item_info] : storage) {
Lua::Table item_data = item_info.as<Lua::Table>();
double config_id = item_data["configId"];
double count = item_data["count"];
items[static_cast<StorageItemId>(config_id)] = static_cast<StorageItemCount>(count);
}
return items;
}
std::optional<Cracker::ShipInfo> Cracker::get_ship_info(ShipId ship_id) {
double id = static_cast<double>(ship_id);
Lua::Table dock = m_data_proxy.dock["data"];
try {
Lua::Table ship_data = dock.get<Lua::Table>(id);
return ShipInfo{
.config_id = static_cast<int>(ship_data.get<double>("configId")),
.emotion = static_cast<int>(ship_data.get<double>("energy")),
.rarity = static_cast<int>(ship_data.get<double>("star")),
.level = static_cast<int>(ship_data.get<double>("level")),
.exp = static_cast<int>(ship_data.get<double>("exp")),
.curr_star = static_cast<int>(ship_data.get<double>("state")),
};
}
catch (const std::exception& e) {
return std::nullopt;
}
return std::nullopt;
}
std::optional<Cracker::StorageItemCount> Cracker::get_storage_item_count(StorageItemId item_id) {
double id = static_cast<double>(item_id);
Lua::Table storage = m_data_proxy.storage["data"];
try {
Lua::Table item_data = storage.get<Lua::Table>(id);
return static_cast<StorageItemCount>(item_data.get<double>("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();
disable_global_speedup();
disable_better_global_speedup();
disable_exercise_god_mode();
disable_exercise_more_power();
disable_fast_wave();
disable_monster_kill_self();
disable_skip_battle_celebrate();
disable_better_global_speedup();
}
void Cracker::enable_better_global_speedup() {
ENABLE(BETTER_GLOBAL_SPEEDUP);
better_global_speedup_set_rate(m_better_global_speedup_rate.load());
}
void Cracker::update_better_global_speedup_rate(double rate) {
m_better_global_speedup_rate.store(rate);
if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP)) {
better_global_speedup_set_rate(rate);
}
}
void Cracker::disable_better_global_speedup() {
DISABLE(BETTER_GLOBAL_SPEEDUP);
better_global_speedup_set_rate(1.0);
}
void Cracker::enable_skip_battle_celebrate() {
ENABLE(SKIP_BATTLE_CELEBRATE);
m_state["ys"]["Battle"]["BattleConfig"]["CelebrateDuration"] = 0.01;
}
void Cracker::disable_skip_battle_celebrate() {
DISABLE(SKIP_BATTLE_CELEBRATE);
m_state["ys"]["Battle"]["BattleConfig"]["CelebrateDuration"] = 3;
}
void Cracker::enable_monster_kill_self() {
ENABLE(MONSTER_KILL_SELF);
}
void Cracker::disable_monster_kill_self() {
DISABLE(MONSTER_KILL_SELF);
}
void Cracker::enable_fast_wave() {
ENABLE(FAST_WAVE);
}
void Cracker::disable_fast_wave() {
DISABLE(FAST_WAVE);
}
void Cracker::enable_exercise_more_power() {
ENABLE(EXERCISE_MORE_POWER);
}
void Cracker::update_exercise_more_power_rate(double rate) {
m_exercise_more_power_rate.store(rate);
}
void Cracker::disable_exercise_more_power() {
DISABLE(EXERCISE_MORE_POWER);
}
void Cracker::enable_exercise_god_mode() {
ENABLE(EXERCISE_GOD_MOD);
}
void Cracker::disable_exercise_god_mode() {
DISABLE(EXERCISE_GOD_MOD);
}
void Cracker::enable_global_speedup() {
m_global_speedup_timer.stop();
m_global_speedup_timer.setInterval([this]() {
get_Time_set_timeScale()(m_global_speedup_rate.load());
}, 500);
ENABLE(GLOBAL_SPEEDUP);
}
void Cracker::update_global_speedup_rate(float rate) {
m_global_speedup_rate.store(rate);
}
void Cracker::disable_global_speedup() {
m_global_speedup_timer.stop();
get_Time_set_timeScale()(1.0);
DISABLE(GLOBAL_SPEEDUP);
}
void Cracker::enable_gg_factor() {
ENABLE(GG_FACTOR);
}
void Cracker::disable_gg_factor() {
DISABLE(GG_FACTOR);
}
void Cracker::update_gg_factor(double factor) {
m_gg_factor = factor;
}
void Cracker::enable_opsi_fast_move() {
ENABLE(OPSI_FAST_MOVE);
}
void Cracker::disable_opsi_fast_move() {
DISABLE(OPSI_FAST_MOVE);
}
void Cracker::enable_no_emotion_warning() {
ENABLE(NO_EMOTION_WARNING);
}
void Cracker::disable_no_emotion_warning() {
DISABLE(NO_EMOTION_WARNING);
}
void Cracker::enable_no_bb_animation() {
ENABLE(NO_BB_ANIMATION);
}
void Cracker::disable_no_bb_animation() {
DISABLE(NO_BB_ANIMATION);
}
void Cracker::enable_fake_player() {
ENABLE(FAKE_PLAYER_INFO);
}
void Cracker::disable_fake_player() {
DISABLE(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() {
ENABLE(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT);
}
void Cracker::disable_remove_hard_mode_ship_type_limit() {
DISABLE(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT);
}
void Cracker::enable_remove_hard_mode_ship_properties_limit() {
ENABLE(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT);
}
void Cracker::disable_remove_hard_mode_ship_properties_limit() {
DISABLE(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT);
}
void Cracker::enable_fast_stage_move() {
m_state["ChapterConst"]["ShipStepDuration"] = 0.0;
m_state["ChapterConst"]["ShipStepQuickPlayScale"] = 0.0;
ENABLE(FAST_STAGE_MOVE_CRACK);
}
void Cracker::disable_fast_stage_move() {
m_state["ChapterConst"]["ShipStepDuration"] = 0.5;
m_state["ChapterConst"]["ShipStepQuickPlayScale"] = 0.5;
DISABLE(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() {
ENABLE(GLOBAL_SHIP_PROPERTIES_CRACK);
}
void Cracker::disable_global_ship_properties_crack() {
DISABLE(GLOBAL_SHIP_PROPERTIES_CRACK);
}
void Cracker::print_table_field(std::vector<std::string>& 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<std::string>& 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<double>());
} else if (type == sol::type::string) {
SPDLOG_INFO("value: {}", value.as<std::string>());
} else if (type == sol::type::boolean) {
SPDLOG_INFO("value: {}", value.as<bool>());
} else if (type == sol::type::nil) {
SPDLOG_INFO("value: nil");
} else if (type == sol::type::table) {
Lua::Table table = value.as<Lua::Table>();
Utils::Lua::print_table_fields_type(table);
}
}
void Cracker::load_lua_resources() {
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.Clone = m_state["Clone"];
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<std::string>("Durability"),
.Cannon = AttributeType.get<std::string>("Cannon"),
.Torpedo = AttributeType.get<std::string>("Torpedo"),
.AntiAircraft = AttributeType.get<std::string>("AntiAircraft"),
.AntiSub = AttributeType.get<std::string>("AntiSub"),
.Air = AttributeType.get<std::string>("Air"),
.Reload = AttributeType.get<std::string>("Reload"),
.Hit = AttributeType.get<std::string>("Hit"),
.Dodge = AttributeType.get<std::string>("Dodge"),
};
m_original.GetBattleCheckResult = m_state["GetBattleCheckResult"];
m_original.FinishStageCommand_GeneralPackage = m_state["FinishStageCommand"]["GeneralPackage"];
m_original.Ship_intimacyAdditions = m_state["Ship"]["intimacyAdditions"];
m_original.Ship_cosumeEnergy = m_state["Ship"]["cosumeEnergy"];
m_original.Ship_getEnergy = m_state["Ship"]["getEnergy"];
m_original.ys_Battle_BattleManualWeaponAutoBot_SetActive = m_state["ys"]["Battle"]["BattleManualWeaponAutoBot"]["SetActive"];
m_original.PlayerVitaeDetailPage_UpdateInfo = m_state["PlayerVitaeDetailPage"]["UpdateInfo"];
m_original.Chapter_getConfig = m_state["Chapter"]["getConfig"];
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_original.Ship_getShipProperties = m_state["Ship"]["getShipProperties"];
m_original.ys_Battle_BattleGateGuild_GeneralPackage = m_state["ys"]["Battle"]["BattleGateGuild"]["GeneralPackage"];
m_original.ys_Battle_BattleDataFunction_GetBuffTemplate = m_state["ys"]["Battle"]["BattleDataFunction"]["GetBuffTemplate"];
m_original.WorldConst_GetTerrainMoveStepDuration = m_state["WorldConst"]["GetTerrainMoveStepDuration"];
m_original.ys_Battle_BattleDataFunction_GetDungeonTmpDataByID = m_state["ys"]["Battle"]["BattleDataFunction"]["GetDungeonTmpDataByID"];
m_original.ys_Battle_BattleEnemyUnit_GetTemplate = m_state["ys"]["Battle"]["BattleEnemyUnit"]["GetTemplate"];
m_original.ys_Battle_BattleState_ExitBattle = m_state["ys"]["Battle"]["BattleState"]["ExitBattle"];
m_original.ys_Battle_BattleState_ScaleTimer = m_state["ys"]["Battle"]["BattleState"]["ScaleTimer"];
}
void Cracker::hook_all_lua_functions() {
// better_global_speedup
m_state["ys"]["Battle"]["BattleState"]["ExitBattle"] = [this](sol::this_state L, Lua::VariadicArgs args) {
m_original.ys_Battle_BattleState_ExitBattle(L, args);
if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP)) {
better_global_speedup_set_rate(m_better_global_speedup_rate.load());
}
};
m_state["ys"]["Battle"]["BattleState"]["ScaleTimer"] = [this](sol::this_state L, Lua::VariadicArgs args) {
m_original.ys_Battle_BattleState_ScaleTimer(L, args);
if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP)) {
better_global_speedup_set_rate(m_better_global_speedup_rate.load());
}
};
// monster_kill_self
m_state["ys"]["Battle"]["BattleEnemyUnit"]["GetTemplate"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(ys.Battle.BattleEnemyUnit.GetTemplate);
if (!IS_ENABLED(MONSTER_KILL_SELF)) {
return m_original.ys_Battle_BattleEnemyUnit_GetTemplate(L, args);
}
Lua::Table result_original = m_original.ys_Battle_BattleEnemyUnit_GetTemplate(L, args);
Lua::Table result = m_lua_res.Clone(result_original);
Lua::Table buff_list = m_state.create_table();
Lua::Table buff1 = m_state.create_table();
buff1["ID"] = 201229;
buff1["LV"] = 1;
buff_list.add(buff1);
Lua::Table buff2 = m_state.create_table();
buff2["ID"] = 800382;
buff2["LV"] = 1;
buff_list.add(buff2);
result["buff_list"] = buff_list;
return result;
};
// fast_wave
m_state["ys"]["Battle"]["BattleDataFunction"]["GetDungeonTmpDataByID"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Table {
CALLED(ys.Battle.BattleDataFunction.GetDungeonTmpDataByID);
if (!IS_ENABLED(FAST_WAVE)) {
return m_original.ys_Battle_BattleDataFunction_GetDungeonTmpDataByID(L, args);
}
Lua::Table result_original = m_original.ys_Battle_BattleDataFunction_GetDungeonTmpDataByID(L, args);
Lua::Table result = m_lua_res.Clone(result_original);
Lua::Table stages = result["stages"];
for (int i = 1; i <= stages.size(); ++i) {
Lua::Table stage = stages[i];
Lua::Table waves = stage["waves"];
for(int j = 1; j <= waves.size(); ++j) {
Lua::Table wave = waves[j];
sol::optional<Lua::Table> preWaves = wave["preWaves"];
if (preWaves.has_value()) {
preWaves.value().clear();
}
sol::optional<Lua::Table> triggerParams = wave["triggerParams"];
if (triggerParams.has_value()) {
triggerParams.value()["timeout"] = 0.1;
}
sol::optional<Lua::Table> airFighterTable = wave["airFighter"];
if (airFighterTable.has_value()) {
auto& airFighters = airFighterTable.value();
for (int k = 1; k <= airFighters.size(); ++k) {
Lua::Table airFighter = airFighters[k];
airFighter["interval"] = 0;
airFighter["onceNumber"] = 0;
airFighter["totalNumber"] = 0;
airFighter["delay"] = 0;
}
}
}
}
return result;
};
// enable_global_speedup
m_state["GetBattleCheckResult"] = [this](sol::this_state L, Lua::VariadicArgs args) {
CALLED(GetBattleCheckResult);
if (!IS_ENABLED(GLOBAL_SPEEDUP)) {
if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP) && IS_ENABLED(MONSTER_KILL_SELF)) {
return m_original.GetBattleCheckResult(L, args);
}
}
double speedup_rate;
if (IS_ENABLED(GLOBAL_SPEEDUP)) {
speedup_rate = m_global_speedup_rate.load();
} else if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP)) {
speedup_rate = m_better_global_speedup_rate.load();
} else {
speedup_rate = 1.0;
}
double total_time = args[2];
std::vector<Lua::Object> new_args(args.begin(), args.end());
new_args[2] = sol::make_object(L, total_time / speedup_rate);
return m_original.GetBattleCheckResult(L, sol::as_args(new_args));
};
m_state["ys"]["Battle"]["BattleGateGuild"]["GeneralPackage"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Table {
CALLED(BattleGateGuild.GeneralPackage);
if (!IS_ENABLED(GLOBAL_SPEEDUP)) {
if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP) && IS_ENABLED(MONSTER_KILL_SELF)) {
return m_original.ys_Battle_BattleGateGuild_GeneralPackage(L, args);
}
}
Lua::Table ret = m_original.ys_Battle_BattleGateGuild_GeneralPackage(args);
double speedup_rate;
if (IS_ENABLED(GLOBAL_SPEEDUP)) {
speedup_rate = m_global_speedup_rate.load();
} else if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP)) {
speedup_rate = m_better_global_speedup_rate.load();
} else {
speedup_rate = 1.0;
}
double total_time = ret["total_time"];
ret["total_time"] = total_time / speedup_rate;
return ret;
};
m_state["FinishStageCommand"]["GeneralPackage"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Table {
CALLED(FinishStageCommand.GeneralPackage);
if (!IS_ENABLED(GLOBAL_SPEEDUP)) {
if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP) && IS_ENABLED(MONSTER_KILL_SELF)) {
return m_original.FinishStageCommand_GeneralPackage(L, args);
}
}
Lua::Table ret = m_original.FinishStageCommand_GeneralPackage(args);
double speedup_rate;
if (IS_ENABLED(GLOBAL_SPEEDUP)) {
speedup_rate = m_global_speedup_rate.load();
} else if (IS_ENABLED(BETTER_GLOBAL_SPEEDUP)) {
speedup_rate = m_better_global_speedup_rate.load();
} else {
speedup_rate = 1.0;
}
double total_time = ret["total_time"];
SPDLOG_INFO("Total time: {}", total_time);
ret["total_time"] = total_time / speedup_rate;
return ret;
};
// enable_gg_factor
m_state["Ship"]["intimacyAdditions"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(Ship.intimacyAdditions);
if (!IS_ENABLED(GG_FACTOR)) {
return m_original.Ship_intimacyAdditions(L, args);
}
if (args.size() < 2) {
return m_original.Ship_intimacyAdditions(L, args);
}
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<Lua::Table>(intimacy_level);
double attr_bonus = attr_bonus_table.get<double>("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<std::string>();
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_no_emotion_warning
m_state["Ship"]["cosumeEnergy"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(Ship.cosumeEnergy);
if (!IS_ENABLED(NO_EMOTION_WARNING)) {
return m_original.Ship_cosumeEnergy(L, args);
}
return sol::nil;
};
m_state["Ship"]["getEnergy"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(Ship.getEnergy);
if (!IS_ENABLED(NO_EMOTION_WARNING)) {
return m_original.Ship_getEnergy(L, args);
}
return sol::make_object(L, 150);
};
// enable_no_bb_animation
m_state["ys"]["Battle"]["BattleManualWeaponAutoBot"]["SetActive"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(ys.Battle.BattleManualWeaponAutoBot.SetActive);
if (!IS_ENABLED(NO_BB_ANIMATION)) {
return m_original.ys_Battle_BattleManualWeaponAutoBot_SetActive(L, args);
}
if (args.size() < 3) {
return m_original.ys_Battle_BattleManualWeaponAutoBot_SetActive(L, args);
}
std::vector<Lua::Object> 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_fake_player
m_state["PlayerVitaeDetailPage"]["UpdateInfo"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(PlayerVitaeDetailPage.UpdateInfo);
if (!IS_ENABLED(FAKE_PLAYER_INFO)) {
return m_original.PlayerVitaeDetailPage_UpdateInfo(L, args);
}
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_remove_hard_mode_ship_type_limit
m_state["Chapter"]["getConfig"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(Chapter.getConfig);
if (!IS_ENABLED(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT)) {
return m_original.Chapter_getConfig(L, args);
}
bool limitation = false;
if (args.size() == 2) {
Lua::Object first_arg = args[1];
if (first_arg.get_type() == sol::type::string && first_arg.as<std::string>() == "limitation") {
limitation = true;
}
}
Lua::Object res = m_original.Chapter_getConfig(L, args);
if (limitation) {
sol::table table = res;
clear_hard_mode_ship_properties_limit(table);
}
return res;
};
// enable_remove_hard_mode_ship_properties_limit
m_state["WorldFleetSelectLayer"]["CheckValid"] = [this](sol::this_state L, Lua::VariadicArgs args) -> bool {
CALLED(WorldFleetSelectLayer.CheckValid);
if (!IS_ENABLED(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)) {
return m_original.WorldFleetSelectLayer_CheckValid(L, args);
}
return true;
};
m_state["BossSingleBattleFleetSelectSubPanel"]["CheckValid"] = [this](sol::this_state L, Lua::VariadicArgs args) -> bool {
CALLED(BossSingleBattleFleetSelectSubPanel.CheckValid);
if (!IS_ENABLED(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)) {
return m_original.BossSingleBattleFleetSelectSubPanel_CheckValid(L, args);
}
return true;
};
m_state["Chapter"]["IsEliteFleetLegal"] = [this](sol::this_state L, Lua::VariadicArgs args) -> bool {
CALLED(Chapter.IsEliteFleetLegal);
if (!IS_ENABLED(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)) {
return m_original.Chapter_IsEliteFleetLegal(L, args);
}
return true;
};
// enable_global_ship_properties_crack
m_state["Ship"]["getShipProperties"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(Ship.getShipProperties);
if (!IS_ENABLED(GLOBAL_SHIP_PROPERTIES_CRACK)) {
return m_original.Ship_getShipProperties(L, args);
}
Lua::Table properties = m_original.Ship_getShipProperties(L, args);
modify_ship_properties(properties, m_globle_ship_properties);
return properties;
};
// exercise
m_state["ys"]["Battle"]["BattleDataFunction"]["GetBuffTemplate"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Table {
CALLED(ys.Battle.BattleDataFunction.GetBuffTemplate);
auto is_enabled_EXERCISE_GOD_MOD = IS_ENABLED(EXERCISE_GOD_MOD);
auto is_enabled_EXERCISE_MORE_POWER = IS_ENABLED(EXERCISE_MORE_POWER);
auto is_enabled_MONSTER_KILL_SELF = IS_ENABLED(MONSTER_KILL_SELF);
if (!is_enabled_EXERCISE_GOD_MOD && !is_enabled_EXERCISE_MORE_POWER && !is_enabled_MONSTER_KILL_SELF) {
return m_original.ys_Battle_BattleDataFunction_GetBuffTemplate(L, args);
}
double buff_id = args[0];
if (buff_id == 19) { // buff_19
Lua::Table buff = m_original.ys_Battle_BattleDataFunction_GetBuffTemplate(L, args);
sol::table effect_list = m_state.create_table();
if (is_enabled_EXERCISE_GOD_MOD) {
sol::table entry1 = m_state.create_table();
entry1["type"] = "BattleBuffCastSkill";
sol::table trigger1 = m_state.create_table();
trigger1.add("onBeforeFatalDamage");
entry1["trigger"] = trigger1;
sol::table arg_list1 = m_state.create_table();
arg_list1["skill_id"] = 11011;
arg_list1["target"] = "TargetSelf";
entry1["arg_list"] = arg_list1;
sol::table entry2 = m_state.create_table();
entry2["type"] = "BattleBuffCancelBuff";
sol::table trigger2 = m_state.create_table();
trigger2.add("onBeforeFatalDamage");
entry2["trigger"] = trigger2;
sol::table arg_list2 = m_state.create_table();
arg_list2["count"] = INT_MAX;
entry2["arg_list"] = arg_list2;
sol::table entry3 = m_state.create_table();
entry3["type"] = "BattleBuffAddBuff";
sol::table trigger3 = m_state.create_table();
trigger3.add("onRemove");
entry3["trigger"] = trigger3;
sol::table arg_list3 = m_state.create_table();
arg_list3["buff_id"] = 11016;
entry3["arg_list"] = arg_list3;
sol::table entry4 = m_state.create_table();
entry4["type"] = "BattleBuffAddAttr";
sol::table trigger4 = m_state.create_table();
trigger4.add("onAttach");
entry4["trigger"] = trigger4;
sol::table arg_list4 = m_state.create_table();
arg_list4["number"] = 1;
arg_list4["target"] = "TargetSelf";
arg_list4["attr"] = "isInvincible";
entry4["arg_list"] = arg_list4;
effect_list.add(entry1);
effect_list.add(entry2);
effect_list.add(entry3);
effect_list.add(entry4);
}
if (is_enabled_EXERCISE_MORE_POWER) {
sol::table entry = m_state.create_table();
entry["type"] = "BattleBuffAddBulletAttr";
sol::table trigger = m_state.create_table();
trigger.add("onBulletCreate");
entry["trigger"] = trigger;
sol::table arg_list = m_state.create_table();
arg_list["number"] = m_exercise_more_power_rate.load();
arg_list["attr"] = "damageRatioBullet";
entry["arg_list"] = arg_list;
effect_list.add(entry);
}
if (is_enabled_EXERCISE_GOD_MOD || is_enabled_EXERCISE_MORE_POWER) {
buff["effect_list"] = effect_list;
}
return buff;
} else if (buff_id == 800382) {
Lua::Table buff = m_original.ys_Battle_BattleDataFunction_GetBuffTemplate(L, args);
buff["effect_list"][1]["arg_list"]["number"] = -9999999;
return buff;
}
return m_original.ys_Battle_BattleDataFunction_GetBuffTemplate(L, args);
};
m_state["WorldConst"]["GetTerrainMoveStepDuration"] = [this](sol::this_state L, Lua::VariadicArgs args) -> Lua::Object {
CALLED(WorldConst.GetTerrainMoveStepDuration);
if (!IS_ENABLED(OPSI_FAST_MOVE)) {
return m_original.WorldConst_GetTerrainMoveStepDuration(L, args);
}
return sol::make_object(L, 0);
};
}
void Cracker::better_global_speedup_set_rate(double rate) {
m_state["ys"]["Battle"]["BattleConfig"]["BASIC_TIME_SCALE"] = rate;
m_state["Time"]["timeScale"] = rate;
}
#define SET_SHIP_PROPERTIES_VALUE(f) v[#f]["value"] = m_globle_ship_properties.f
Json::Value Cracker::get_config_json() {
Json::Value j;
j["globalSpeedup"]["enabled"] = m_flag.GLOBAL_SPEEDUP.load();
j["globalSpeedup"]["value"] = m_global_speedup_rate.load();
j["chapterFastMove"]["enabled"] = m_flag.FAST_STAGE_MOVE_CRACK.load();
j["opsiFastMove"]["enabled"] = m_flag.OPSI_FAST_MOVE.load();
j["noBBAnimation"]["enabled"] = m_flag.NO_BB_ANIMATION.load();
j["noEmotionWarning"]["enabled"] = m_flag.NO_EMOTION_WARNING.load();
j["removeHardModeShipPropertiesLimit"]["enabled"] = m_flag.REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT.load();
j["removeHardModeShipTypeLimit"]["enabled"] = m_flag.REMOVE_HARD_MODE_SHIP_TYPE_LIMIT.load();
j["globalShipProperties"]["enabled"] = m_flag.GLOBAL_SHIP_PROPERTIES_CRACK.load();
j["globalShipProperties"]["value"] = [this] -> Json::Value {
Json::Value v;
SET_SHIP_PROPERTIES_VALUE(armor);
SET_SHIP_PROPERTIES_VALUE(speed);
SET_SHIP_PROPERTIES_VALUE(antiaircraft);
SET_SHIP_PROPERTIES_VALUE(oxy_recovery_bench);
SET_SHIP_PROPERTIES_VALUE(torpedo);
SET_SHIP_PROPERTIES_VALUE(hit);
SET_SHIP_PROPERTIES_VALUE(sonarRange);
SET_SHIP_PROPERTIES_VALUE(attack_duration);
SET_SHIP_PROPERTIES_VALUE(raid_distance);
SET_SHIP_PROPERTIES_VALUE(oxy_recovery_surface);
SET_SHIP_PROPERTIES_VALUE(oxy_recovery);
SET_SHIP_PROPERTIES_VALUE(dodge);
SET_SHIP_PROPERTIES_VALUE(luck);
SET_SHIP_PROPERTIES_VALUE(reload);
SET_SHIP_PROPERTIES_VALUE(oxy_cost);
SET_SHIP_PROPERTIES_VALUE(durability);
SET_SHIP_PROPERTIES_VALUE(air);
SET_SHIP_PROPERTIES_VALUE(oxy_max);
SET_SHIP_PROPERTIES_VALUE(cannon);
SET_SHIP_PROPERTIES_VALUE(antisub);
return v;
}();
j["ggFactor"]["enabled"] = m_flag.GG_FACTOR.load();
j["ggFactor"]["value"] = m_gg_factor;
j["exerciseGodMode"]["enabled"] = m_flag.EXERCISE_GOD_MOD.load();
j["exerciseMorePower"]["enabled"] = m_flag.EXERCISE_MORE_POWER.load();
j["exerciseMorePower"]["value"] = m_exercise_more_power_rate.load();
return j;
}
#define APPLY_CONFIG(f) m_##f = config.f
#define APPLY_ATOMIC_CONFIG(f) m_##f.store(config.f)
void Cracker::apply_config(Config& config) {
APPLY_ATOMIC_CONFIG(flag.GLOBAL_SHIP_PROPERTIES_CRACK);
APPLY_ATOMIC_CONFIG(flag.FAST_STAGE_MOVE_CRACK);
APPLY_ATOMIC_CONFIG(flag.REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT);
APPLY_ATOMIC_CONFIG(flag.REMOVE_HARD_MODE_SHIP_TYPE_LIMIT);
APPLY_ATOMIC_CONFIG(flag.NO_BB_ANIMATION);
APPLY_ATOMIC_CONFIG(flag.NO_EMOTION_WARNING);
APPLY_ATOMIC_CONFIG(flag.OPSI_FAST_MOVE);
APPLY_ATOMIC_CONFIG(flag.GG_FACTOR);
APPLY_ATOMIC_CONFIG(flag.GLOBAL_SPEEDUP);
APPLY_ATOMIC_CONFIG(flag.EXERCISE_GOD_MOD);
APPLY_ATOMIC_CONFIG(flag.EXERCISE_MORE_POWER);
APPLY_ATOMIC_CONFIG(flag.OPSI_FAST_MOVE);
APPLY_CONFIG(globle_ship_properties);
APPLY_ATOMIC_CONFIG(global_speedup_rate);
APPLY_CONFIG(gg_factor);
APPLY_ATOMIC_CONFIG(exercise_more_power_rate);
if (config.flag.FAST_STAGE_MOVE_CRACK) {
enable_fast_stage_move();
} else {
disable_fast_stage_move();
}
if (config.flag.GLOBAL_SPEEDUP) {
update_global_speedup_rate(config.global_speedup_rate);
enable_global_speedup();
} else {
disable_global_speedup();
}
}
#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;
}
}
}
}