allow specifying what counts as cheating; closes #572

This commit is contained in:
Martin Michelsen
2024-10-17 21:19:25 -07:00
parent f8e479b4f9
commit 21f1c40408
5 changed files with 134 additions and 39 deletions
+49 -39
View File
@@ -71,22 +71,25 @@ static void check_debug_enabled(shared_ptr<Client> c) {
}
}
static void check_cheats_enabled(shared_ptr<Lobby> l, shared_ptr<Client> c) {
if (!l->check_flag(Lobby::Flag::CHEATS_ENABLED) &&
static void check_cheats_enabled(shared_ptr<Lobby> l, shared_ptr<Client> c, bool behavior_is_cheating) {
if (behavior_is_cheating &&
!l->check_flag(Lobby::Flag::CHEATS_ENABLED) &&
!c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE)) {
throw precondition_failed("$C6This command can\nonly be used in\ncheat mode.");
}
}
static void check_cheats_allowed(shared_ptr<ServerState> s, shared_ptr<Client> c) {
if ((s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) &&
static void check_cheats_allowed(shared_ptr<ServerState> s, shared_ptr<Client> c, bool behavior_is_cheating) {
if (behavior_is_cheating &&
(s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) &&
!c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE)) {
throw precondition_failed("$C6Cheats are disabled\non this server.");
}
}
static void check_cheats_allowed(shared_ptr<ServerState> s, shared_ptr<ProxyServer::LinkedSession> ses) {
if ((s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) &&
static void check_cheats_allowed(shared_ptr<ServerState> s, shared_ptr<ProxyServer::LinkedSession> ses, bool behavior_is_cheating) {
if (behavior_is_cheating &&
(s->cheat_mode_behavior == ServerState::BehaviorSwitch::OFF) &&
(!ses->login || !ses->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE))) {
throw precondition_failed("$C6Cheats are disabled\non this proxy.");
}
@@ -972,7 +975,9 @@ static void server_command_cheat(shared_ptr<Client> c, const std::string&) {
l->toggle_flag(Lobby::Flag::CHEATS_ENABLED);
send_text_message_printf(l, "Cheat mode %s", l->check_flag(Lobby::Flag::CHEATS_ENABLED) ? "enabled" : "disabled");
if (!l->check_flag(Lobby::Flag::CHEATS_ENABLED) && !c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE)) {
if (!l->check_flag(Lobby::Flag::CHEATS_ENABLED) &&
!c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE) &&
s->cheat_flags.insufficient_minimum_level) {
size_t default_min_level = s->default_min_level_for_game(l->base_version, l->episode, l->difficulty);
if (l->min_level < default_min_level) {
l->min_level = default_min_level;
@@ -1147,7 +1152,8 @@ static void server_command_meseta(shared_ptr<Client> c, const std::string& args)
static void server_command_secid(shared_ptr<Client> c, const std::string& args) {
auto l = c->require_lobby();
check_cheats_allowed(c->require_server_state(), c);
auto s = c->require_server_state();
check_cheats_allowed(s, c, s->cheat_flags.override_section_id);
uint8_t new_override_section_id;
@@ -1172,7 +1178,9 @@ static void server_command_secid(shared_ptr<Client> c, const std::string& args)
}
static void proxy_command_secid(shared_ptr<ProxyServer::LinkedSession> ses, const std::string& args) {
check_cheats_allowed(ses->require_server_state(), ses);
auto s = ses->require_server_state();
check_cheats_allowed(s, ses, s->cheat_flags.override_section_id);
if (!args[0]) {
ses->config.override_section_id = 0xFF;
send_text_message(ses->client_channel, "$C6Override section ID\nremoved");
@@ -1194,7 +1202,7 @@ static void server_command_variations(shared_ptr<Client> c, const std::string& a
auto s = c->require_server_state();
auto l = c->require_lobby();
check_is_game(l, false);
check_cheats_allowed(s, c);
check_cheats_allowed(s, c, s->cheat_flags.override_variations);
c->override_variations = make_unique<parray<le_uint32_t, 0x20>>();
c->override_variations->clear(0);
@@ -1207,7 +1215,7 @@ static void server_command_rand(shared_ptr<Client> c, const std::string& args) {
auto s = c->require_server_state();
auto l = c->require_lobby();
check_is_game(l, false);
check_cheats_allowed(s, c);
check_cheats_allowed(s, c, s->cheat_flags.override_random_seed);
if (!args[0]) {
c->config.clear_flag(Client::Flag::USE_OVERRIDE_RANDOM_SEED);
@@ -1221,7 +1229,8 @@ static void server_command_rand(shared_ptr<Client> c, const std::string& args) {
}
static void proxy_command_rand(shared_ptr<ProxyServer::LinkedSession> ses, const std::string& args) {
check_cheats_allowed(ses->require_server_state(), ses);
auto s = ses->require_server_state();
check_cheats_allowed(s, ses, s->cheat_flags.override_random_seed);
if (!args[0]) {
ses->config.clear_flag(Client::Flag::USE_OVERRIDE_RANDOM_SEED);
ses->config.override_random_seed = 0;
@@ -1292,7 +1301,7 @@ static void server_command_min_level(shared_ptr<Client> c, const std::string& ar
auto s = c->require_server_state();
bool cheats_allowed = (l->check_flag(Lobby::Flag::CHEATS_ENABLED) ||
c->login->account->check_flag(Account::Flag::CHEAT_ANYWHERE));
if (!cheats_allowed) {
if (!cheats_allowed && s->cheat_flags.insufficient_minimum_level) {
size_t default_min_level = s->default_min_level_for_game(l->base_version, l->episode, l->difficulty);
if (new_min_level < default_min_level) {
send_text_message_printf(c, "$C6Cannot set minimum\nlevel below %zu", default_min_level + 1);
@@ -1342,28 +1351,28 @@ static void server_command_edit(shared_ptr<Client> c, const std::string& args) {
try {
auto p = c->character();
if (tokens.at(0) == "atp" && cheats_allowed) {
if (tokens.at(0) == "atp" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.char_stats.atp = stoul(tokens.at(1));
} else if (tokens.at(0) == "mst" && cheats_allowed) {
} else if (tokens.at(0) == "mst" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.char_stats.mst = stoul(tokens.at(1));
} else if (tokens.at(0) == "evp" && cheats_allowed) {
} else if (tokens.at(0) == "evp" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.char_stats.evp = stoul(tokens.at(1));
} else if (tokens.at(0) == "hp" && cheats_allowed) {
} else if (tokens.at(0) == "hp" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.char_stats.hp = stoul(tokens.at(1));
} else if (tokens.at(0) == "dfp" && cheats_allowed) {
} else if (tokens.at(0) == "dfp" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.char_stats.dfp = stoul(tokens.at(1));
} else if (tokens.at(0) == "ata" && cheats_allowed) {
} else if (tokens.at(0) == "ata" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.char_stats.ata = stoul(tokens.at(1));
} else if (tokens.at(0) == "lck" && cheats_allowed) {
} else if (tokens.at(0) == "lck" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.char_stats.lck = stoul(tokens.at(1));
} else if (tokens.at(0) == "meseta" && cheats_allowed) {
} else if (tokens.at(0) == "meseta" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.meseta = stoul(tokens.at(1));
} else if (tokens.at(0) == "exp" && cheats_allowed) {
} else if (tokens.at(0) == "exp" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.experience = stoul(tokens.at(1));
} else if (tokens.at(0) == "level" && cheats_allowed) {
} else if (tokens.at(0) == "level" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
p->disp.stats.level = stoul(tokens.at(1)) - 1;
p->recompute_stats(s->level_table(c->version()));
} else if (((tokens.at(0) == "material") || (tokens.at(0) == "mat")) && !is_v1_or_v2(c->version())) {
} else if (((tokens.at(0) == "material") || (tokens.at(0) == "mat")) && !is_v1_or_v2(c->version()) && (cheats_allowed || !s->cheat_flags.reset_materials)) {
if (tokens.at(1) == "reset") {
const auto& which = tokens.at(2);
if (which == "power") {
@@ -1420,7 +1429,7 @@ static void server_command_edit(shared_ptr<Client> c, const std::string& args) {
sys->language = new_language;
}
} else if (tokens.at(0) == "secid") {
if (!cheats_allowed && (p->disp.stats.level > 0)) {
if (!cheats_allowed && (p->disp.stats.level > 0) && s->cheat_flags.edit_section_id) {
send_text_message(c, "$C6You cannot change\nyour Section ID\nafter level 1");
return;
}
@@ -1482,7 +1491,7 @@ static void server_command_edit(shared_ptr<Client> c, const std::string& args) {
p->disp.visual.extra_model = npc;
p->disp.visual.validation_flags |= 0x02;
}
} else if (tokens.at(0) == "tech" && cheats_allowed) {
} else if (tokens.at(0) == "tech" && (cheats_allowed || !s->cheat_flags.edit_stats)) {
uint8_t level = stoul(tokens.at(2)) - 1;
if (tokens.at(1) == "all") {
for (size_t x = 0; x < 0x14; x++) {
@@ -1853,7 +1862,7 @@ static void server_command_warp(shared_ptr<Client> c, const std::string& args, b
auto s = c->require_server_state();
auto l = c->require_lobby();
check_is_game(l, true);
check_cheats_enabled(l, c);
check_cheats_enabled(l, c, s->cheat_flags.warp);
uint32_t floor = stoul(args, nullptr, 0);
if (!is_warpall && (c->floor == floor)) {
@@ -1885,7 +1894,7 @@ static void server_command_warpall(shared_ptr<Client> c, const std::string& args
static void proxy_command_warp(shared_ptr<ProxyServer::LinkedSession> ses, const std::string& args, bool is_warpall) {
auto s = ses->require_server_state();
check_cheats_allowed(s, ses);
check_cheats_allowed(s, ses, s->cheat_flags.warp);
if (!ses->is_in_game) {
send_text_message(ses->client_channel, "$C6You must be in a\ngame to use this\ncommand");
return;
@@ -1910,7 +1919,7 @@ static void server_command_next(shared_ptr<Client> c, const std::string&) {
auto s = c->require_server_state();
auto l = c->require_lobby();
check_is_game(l, true);
check_cheats_enabled(l, c);
check_cheats_enabled(l, c, s->cheat_flags.warp);
size_t limit = floor_limit_for_episode(l->episode);
if (limit == 0) {
@@ -1921,7 +1930,7 @@ static void server_command_next(shared_ptr<Client> c, const std::string&) {
static void proxy_command_next(shared_ptr<ProxyServer::LinkedSession> ses, const std::string&) {
auto s = ses->require_server_state();
check_cheats_allowed(s, ses);
check_cheats_allowed(s, ses, s->cheat_flags.warp);
if (!ses->is_in_game) {
send_text_message(ses->client_channel, "$C6You must be in a\ngame to use this\ncommand");
return;
@@ -2022,7 +2031,7 @@ static void server_command_infinite_hp(shared_ptr<Client> c, const std::string&)
auto s = c->require_server_state();
auto l = c->require_lobby();
check_is_game(l, true);
check_cheats_enabled(l, c);
check_cheats_enabled(l, c, s->cheat_flags.infinite_hp_tp);
c->config.toggle_flag(Client::Flag::INFINITE_HP_ENABLED);
bool enabled = c->config.check_flag(Client::Flag::INFINITE_HP_ENABLED);
@@ -2034,7 +2043,7 @@ static void server_command_infinite_hp(shared_ptr<Client> c, const std::string&)
static void proxy_command_infinite_hp(shared_ptr<ProxyServer::LinkedSession> ses, const std::string&) {
auto s = ses->require_server_state();
check_cheats_allowed(s, ses);
check_cheats_allowed(s, ses, s->cheat_flags.infinite_hp_tp);
ses->config.toggle_flag(Client::Flag::INFINITE_HP_ENABLED);
bool enabled = ses->config.check_flag(Client::Flag::INFINITE_HP_ENABLED);
send_text_message_printf(ses->client_channel, "$C6Infinite HP %s", enabled ? "enabled" : "disabled");
@@ -2048,7 +2057,7 @@ static void server_command_infinite_tp(shared_ptr<Client> c, const std::string&)
auto s = c->require_server_state();
auto l = c->require_lobby();
check_is_game(l, true);
check_cheats_enabled(l, c);
check_cheats_enabled(l, c, s->cheat_flags.infinite_hp_tp);
c->config.toggle_flag(Client::Flag::INFINITE_TP_ENABLED);
send_text_message_printf(c, "$C6Infinite TP %s", c->config.check_flag(Client::Flag::INFINITE_TP_ENABLED) ? "enabled" : "disabled");
@@ -2056,7 +2065,7 @@ static void server_command_infinite_tp(shared_ptr<Client> c, const std::string&)
static void proxy_command_infinite_tp(shared_ptr<ProxyServer::LinkedSession> ses, const std::string&) {
auto s = ses->require_server_state();
check_cheats_allowed(s, ses);
check_cheats_allowed(s, ses, s->cheat_flags.infinite_hp_tp);
ses->config.toggle_flag(Client::Flag::INFINITE_TP_ENABLED);
send_text_message_printf(ses->client_channel, "$C6Infinite TP %s",
ses->config.check_flag(Client::Flag::INFINITE_TP_ENABLED) ? "enabled" : "disabled");
@@ -2146,7 +2155,8 @@ static void server_command_dropmode(shared_ptr<Client> c, const std::string& arg
}
static void proxy_command_dropmode(shared_ptr<ProxyServer::LinkedSession> ses, const std::string& args) {
check_cheats_allowed(ses->require_server_state(), ses);
auto s = ses->require_server_state();
check_cheats_allowed(ses->require_server_state(), ses, s->cheat_flags.proxy_override_drops);
using DropMode = ProxyServer::LinkedSession::DropMode;
if (args.empty()) {
@@ -2194,7 +2204,7 @@ static void server_command_item(shared_ptr<Client> c, const std::string& args) {
auto s = c->require_server_state();
auto l = c->require_lobby();
check_is_game(l, true);
check_cheats_enabled(l, c);
check_cheats_enabled(l, c, s->cheat_flags.create_items);
ItemData item = s->parse_item_description(c->version(), args);
item.id = l->generate_item_id(c->lobby_client_id);
@@ -2213,7 +2223,7 @@ static void server_command_item(shared_ptr<Client> c, const std::string& args) {
static void proxy_command_item(shared_ptr<ProxyServer::LinkedSession> ses, const std::string& args) {
auto s = ses->require_server_state();
check_cheats_allowed(s, ses);
check_cheats_allowed(s, ses, s->cheat_flags.create_items);
if (ses->version() == Version::BB_V4) {
send_text_message(ses->client_channel, "$C6This command cannot\nbe used on the proxy\nserver in BB games");
return;
@@ -2379,7 +2389,7 @@ static void server_command_ep3_replace_assist_card(shared_ptr<Client> c, const s
auto l = c->require_lobby();
check_is_game(l, true);
check_is_ep3(c, true);
check_cheats_enabled(l, c);
check_cheats_enabled(l, c, s->cheat_flags.ep3_replace_assist);
if (l->episode != Episode::EP3) {
throw logic_error("non-Ep3 client in Ep3 game");
@@ -2431,7 +2441,7 @@ static void server_command_ep3_unset_field_character(shared_ptr<Client> c, const
auto l = c->require_lobby();
check_is_game(l, true);
check_is_ep3(c, true);
check_cheats_enabled(l, c);
check_cheats_enabled(l, c, s->cheat_flags.ep3_unset_field_character);
if (l->episode != Episode::EP3) {
throw logic_error("non-Ep3 client in Ep3 game");