mirror of
https://github.com/0O0o0oOoO00/Alas.git
synced 2026-05-15 02:49:26 +08:00
570 lines
20 KiB
C++
570 lines
20 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() {
|
|
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");
|
|
}
|
|
|
|
#define IS_ENABLED(n) \
|
|
if (is_enabled(n)) { \
|
|
SPDLOG_INFO("{} is enabled", #n); \
|
|
return; \
|
|
} \
|
|
|
|
#define ENABLE(n) \
|
|
SPDLOG_INFO("Enable {}", #n); \
|
|
enable_flag(n);
|
|
|
|
#define IS_DISABLED(n) \
|
|
if (is_disabled(n)) { \
|
|
SPDLOG_INFO("{} is disabled", #n); \
|
|
return; \
|
|
} \
|
|
|
|
#define DISABLE(n) \
|
|
SPDLOG_INFO("Disable {}", #n); \
|
|
disable_flag(n);
|
|
|
|
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<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"),
|
|
};
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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() {
|
|
IS_ENABLED(GG_FACTOR)
|
|
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<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(GG_FACTOR)
|
|
}
|
|
|
|
void Cracker::disable_gg_factor() {
|
|
IS_DISABLED(GG_FACTOR)
|
|
m_state["Ship"]["intimacyAdditions"] = m_original.Ship_intimacyAdditions;
|
|
DISABLE(GG_FACTOR)
|
|
}
|
|
|
|
void Cracker::update_gg_factor(double factor) {
|
|
m_gg_factor = factor;
|
|
}
|
|
|
|
void Cracker::enable_opsi_fast_move() {
|
|
IS_ENABLED(OPSI_FAST_MOVE)
|
|
m_state["WorldConst"]["BaseMoveDuration"] = 0.0;
|
|
ENABLE(OPSI_FAST_MOVE)
|
|
}
|
|
|
|
void Cracker::disable_opsi_fast_move() {
|
|
IS_DISABLED(OPSI_FAST_MOVE)
|
|
m_state["WorldConst"]["BaseMoveDuration"] = 0.35;
|
|
ENABLE(OPSI_FAST_MOVE)
|
|
}
|
|
|
|
void Cracker::enable_no_emotion_warning() {
|
|
IS_ENABLED(NO_EMOTION_WARNING)
|
|
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(NO_EMOTION_WARNING)
|
|
}
|
|
|
|
void Cracker::disable_no_emotion_warning() {
|
|
IS_DISABLED(NO_EMOTION_WARNING)
|
|
m_state["Ship"]["cosumeEnergy"] = m_original.Ship_cosumeEnergy;
|
|
m_state["Ship"]["getEnergy"] = m_original.Ship_getEnergy;
|
|
DISABLE(NO_EMOTION_WARNING)
|
|
}
|
|
|
|
void Cracker::enable_no_bb_animation() {
|
|
IS_ENABLED(NO_BB_ANIMATION)
|
|
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<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(NO_BB_ANIMATION)
|
|
}
|
|
|
|
void Cracker::disable_no_bb_animation() {
|
|
IS_DISABLED(NO_BB_ANIMATION)
|
|
m_state["ys"]["Battle"]["BattleManualWeaponAutoBot"]["SetActive"] = m_original.ys_Battle_BattleManualWeaponAutoBot_SetActive;
|
|
DISABLE(NO_BB_ANIMATION)
|
|
}
|
|
|
|
void Cracker::enable_fake_player() {
|
|
IS_ENABLED(FAKE_PLAYER_INFO)
|
|
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(FAKE_PLAYER_INFO)
|
|
}
|
|
|
|
void Cracker::disable_fake_player() {
|
|
IS_DISABLED(FAKE_PLAYER_INFO)
|
|
m_state["PlayerVitaeDetailPage"]["UpdateInfo"] = m_original.PlayerVitaeDetailPage_UpdateInfo;
|
|
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() {
|
|
IS_ENABLED(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT)
|
|
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<std::string>() == "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(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT)
|
|
}
|
|
|
|
void Cracker::disable_remove_hard_mode_ship_type_limit() {
|
|
IS_DISABLED(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT)
|
|
m_state["Chapter"]["getConfig"] = m_original.Chapter_getConfig;
|
|
DISABLE(REMOVE_HARD_MODE_SHIP_TYPE_LIMIT)
|
|
}
|
|
|
|
void Cracker::enable_remove_hard_mode_ship_properties_limit() {
|
|
IS_ENABLED(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)
|
|
|
|
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(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)
|
|
}
|
|
|
|
void Cracker::disable_remove_hard_mode_ship_properties_limit() {
|
|
IS_DISABLED(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)
|
|
|
|
m_state["WorldFleetSelectLayer"]["CheckValid"] = m_original.WorldFleetSelectLayer_CheckValid;
|
|
m_state["BossSingleBattleFleetSelectSubPanel"]["CheckValid"] = m_original.BossSingleBattleFleetSelectSubPanel_CheckValid;
|
|
m_state["Chapter"]["IsEliteFleetLegal"] = m_original.Chapter_IsEliteFleetLegal;
|
|
|
|
ENABLE(REMOVE_HARD_MODE_SHIP_PROPERTIES_LIMIT)
|
|
}
|
|
|
|
void Cracker::enable_fast_stage_move() {
|
|
IS_ENABLED(FAST_STAGE_MOVE_CRACK)
|
|
|
|
m_state["ChapterConst"]["ShipStepDuration"] = 0.0;
|
|
m_state["ChapterConst"]["ShipStepQuickPlayScale"] = 0.0;
|
|
|
|
ENABLE(FAST_STAGE_MOVE_CRACK)
|
|
}
|
|
|
|
void Cracker::disable_fast_stage_move() {
|
|
IS_DISABLED(FAST_STAGE_MOVE_CRACK)
|
|
|
|
m_state["ChapterConst"]["ShipStepDuration"] = 0.5;
|
|
m_state["ChapterConst"]["ShipStepQuickPlayScale"] = 0.5;
|
|
|
|
ENABLE(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() {
|
|
IS_ENABLED(GLOBAL_SHIP_PROPERTIES_CRACK)
|
|
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(GLOBAL_SHIP_PROPERTIES_CRACK)
|
|
}
|
|
|
|
void Cracker::disable_global_ship_properties_crack() {
|
|
IS_DISABLED(GLOBAL_SHIP_PROPERTIES_CRACK)
|
|
m_state["Ship"]["getShipProperties"] = m_original.Ship_getShipProperties;
|
|
DISABLE(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<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::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;
|
|
}
|
|
}
|
|
}
|
|
}
|