From 249317305289b08a5f69c5462aa92ae3bad62af3 Mon Sep 17 00:00:00 2001 From: James Osborne Date: Fri, 5 Jun 2026 19:23:49 -0400 Subject: [PATCH] Gate Brutal Peeps tiers by character level --- src/Client.hh | 2 +- src/Lobby.hh | 4 +- src/Menu.hh | 2 +- src/ReceiveCommands.cc | 85 +++++++++++++++++++++--------------------- 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/Client.hh b/src/Client.hh index 467f625f..d05c605a 100644 --- a/src/Client.hh +++ b/src/Client.hh @@ -152,7 +152,7 @@ public: uint8_t override_lobby_event = 0xFF; // FF = no override uint8_t override_lobby_number = 0x80; // 80 = no override int64_t override_random_seed = -1; - int8_t selected_brutal_peeps_tier = -1; // -1 = normal lobby/game; 0..10 = requested Brutal Peeps tier + int8_t selected_brutal_peeps_tier = -1; // -1 = normal lobby/game; 1..11 = requested Brutal Peeps tier std::unique_ptr override_variations; VectorXYZF pos; uint32_t floor = 0x0F; diff --git a/src/Lobby.hh b/src/Lobby.hh index 7c80f356..78550360 100644 --- a/src/Lobby.hh +++ b/src/Lobby.hh @@ -81,7 +81,7 @@ struct Lobby : public std::enable_shared_from_this { START_BATTLE_PLAYER_IMMEDIATELY = 0x00010000, CANNOT_CHANGE_CHEAT_MODE = 0x00020000, USE_CREATOR_SECTION_ID = 0x00040000, - BRUTAL_PEEPS_PLUS0 = 0x00080000, + BRUTAL_PEEPS_MODE = 0x00080000, // Flags used only for lobbies PUBLIC = 0x01000000, DEFAULT = 0x02000000, @@ -119,7 +119,7 @@ struct Lobby : public std::enable_shared_from_this { Episode episode = Episode::NONE; GameMode mode = GameMode::NORMAL; Difficulty difficulty = Difficulty::NORMAL; - int8_t brutal_peeps_tier = -1; // -1 = disabled; 0..10 = Brutal Peeps +0..+10 + int8_t brutal_peeps_tier = -1; // -1 = disabled; 1..11 = Brutal Peeps +1..+11 float base_exp_multiplier = 1.0f; float exp_share_multiplier = 0.5f; float challenge_exp_multiplier = 1.0f; diff --git a/src/Menu.hh b/src/Menu.hh index dd18fdb0..851157dc 100644 --- a/src/Menu.hh +++ b/src/Menu.hh @@ -47,7 +47,7 @@ constexpr uint32_t BB_TEST_SHIP = 0x11BBBB11; constexpr uint32_t BB_VANILLA_SHIP = 0x11CCCC11; constexpr uint32_t BB_HARDCORE_SHIP = 0x11F00D11; constexpr uint32_t BB_DEV_SHIP = 0x11EEEE11; -constexpr uint32_t BRUTAL_PEEPS_PLUS0 = 0x11DDDD11; +constexpr uint32_t BRUTAL_PEEPS_PLUS1 = 0x11DDDD11; } // namespace MainMenuItemID namespace ClearLicenseConfirmationMenuItemID { diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index bbc126ac..a432ddef 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -26,6 +26,7 @@ #include "SendCommands.hh" #include "StaticGameData.hh" #include "Text.hh" +#include "BrutalPeeps.hh" const char* BATTLE_TABLE_DISCONNECT_HOOK_NAME = "battle_table_state"; const char* QUEST_BARRIER_DISCONNECT_HOOK_NAME = "quest_barrier"; @@ -306,19 +307,22 @@ static void send_main_menu(std::shared_ptr c) { num_players, num_games, num_compatible_games); }, go_to_lobby_menu_item_flags); + uint32_t character_level = c->character_file() + ? (c->character_file()->disp.stats.level + 1) + : 0; + int8_t max_brutal_peeps_menu_tier = s->enable_brutal_peeps_mode + ? max_brutal_peeps_tier_for_level(character_level) + : -1; + bool show_brutal_peeps_menu_items = bb_destination_transport_menu && s->enable_brutal_peeps_mode && - (s->brutal_peeps_unlocked_tier_v4 >= 0); + (max_brutal_peeps_menu_tier >= 1); if (show_brutal_peeps_menu_items) { - int64_t max_brutal_peeps_menu_tier = std::min( - s->brutal_peeps_max_tier, - s->brutal_peeps_unlocked_tier_v4); - - for (int64_t tier = 0; tier <= max_brutal_peeps_menu_tier; tier++) { + for (int64_t tier = 1; tier <= max_brutal_peeps_menu_tier; tier++) { main_menu->items.emplace_back( - MainMenuItemID::BRUTAL_PEEPS_PLUS0 + static_cast(tier), + MainMenuItemID::BRUTAL_PEEPS_PLUS1 + static_cast(tier - 1), std::format("Brutal Peeps +{}", tier), std::format("Enter Brutal Peeps\n+{}", tier), MenuItem::Flag::BB_ONLY); @@ -2735,21 +2739,27 @@ void set_lobby_quest(std::shared_ptr l, std::shared_ptr q, b static asio::awaitable on_10_main_menu(std::shared_ptr c, uint32_t item_id) { auto s = c->require_server_state(); - if ((item_id >= MainMenuItemID::BRUTAL_PEEPS_PLUS0) && - (item_id <= (MainMenuItemID::BRUTAL_PEEPS_PLUS0 + 10))) { - int64_t tier = item_id - MainMenuItemID::BRUTAL_PEEPS_PLUS0; + if ((item_id >= MainMenuItemID::BRUTAL_PEEPS_PLUS1) && + (item_id <= (MainMenuItemID::BRUTAL_PEEPS_PLUS1 + 10))) { + int64_t tier = (item_id - MainMenuItemID::BRUTAL_PEEPS_PLUS1) + 1; + const auto* brutal_peeps_def = brutal_peeps_tier_definition(tier); + uint32_t character_level = c->character_file() + ? (c->character_file()->disp.stats.level + 1) + : 0; if (!s->enable_brutal_peeps_mode || !is_v4(c->version()) || - (tier < 0) || - (tier > s->brutal_peeps_max_tier) || - (tier > s->brutal_peeps_unlocked_tier_v4)) { - send_message_box(c, std::format("$C6Brutal Peeps +{} is not available.", tier)); + !brutal_peeps_def || + (character_level < brutal_peeps_def->required_level)) { + send_message_box(c, std::format( + "$C6Brutal Peeps +{} is not available.\n\n$C7Required level: {}", + tier, + brutal_peeps_def ? brutal_peeps_def->required_level : 100)); co_return; } c->selected_brutal_peeps_tier = tier; - c->log.info_f("Brutal Peeps +{} selected from BB menu", tier); + c->log.info_f("Brutal Peeps +{} selected from BB menu at level {}", tier, character_level); co_await send_auto_patches_if_needed(c); co_await enable_save_if_needed(c); @@ -2775,21 +2785,6 @@ static asio::awaitable on_10_main_menu(std::shared_ptr c, uint32_t break; } - case MainMenuItemID::BRUTAL_PEEPS_PLUS0: { - if (!s->enable_brutal_peeps_mode || (c->version() != Version::DC_V2) || (s->brutal_peeps_unlocked_tier_v2 < 0)) { - send_message_box(c, "$C6Brutal Peeps +0 is not available."); - break; - } - c->selected_brutal_peeps_tier = 0; - co_await send_auto_patches_if_needed(c); - co_await enable_save_if_needed(c); - send_lobby_list(c); - if (!c->lobby.lock()) { - s->add_client_to_available_lobby(c, false); - } - break; - } - case MainMenuItemID::INFORMATION: { send_menu(c, s->information_menu(c->version())); c->set_flag(Client::Flag::IN_INFORMATION_MENU); @@ -5081,13 +5076,15 @@ std::shared_ptr create_game_generic( if (creator_c->check_flag(Client::Flag::IS_CLIENT_CUSTOMIZATION)) { game->set_flag(Lobby::Flag::IS_CLIENT_CUSTOMIZATION); } - game->log.info_f("PSO Peeps Brutal Peeps debug: created game name=[{}] version={} difficulty={} enable_brutal_peeps_mode={} unlocked_v4={} max_tier={}", + uint32_t creator_character_level = creator_c->character_file() + ? (creator_c->character_file()->disp.stats.level + 1) + : 0; + game->log.info_f("PSO Peeps Brutal Peeps debug: created game name=[{}] version={} difficulty={} enable_brutal_peeps_mode={} creator_level={}", name, static_cast(creator_c->version()), name_for_difficulty(difficulty), s->enable_brutal_peeps_mode, - s->brutal_peeps_unlocked_tier_v4, - s->brutal_peeps_max_tier); + creator_character_level); int8_t requested_brutal_peeps_tier = -1; bool requested_brutal_peeps = false; std::string requested_brutal_peeps_source = "none"; @@ -5098,7 +5095,7 @@ std::shared_ptr create_game_generic( requested_brutal_peeps_source = "BB menu selection"; } else { - size_t bb_prefix_offset = name.find("[BB+"); + size_t bb_prefix_offset = name.find("[BP+"); if (bb_prefix_offset != std::string::npos) { requested_brutal_peeps = true; requested_brutal_peeps_source = "room prefix"; @@ -5115,7 +5112,7 @@ std::shared_ptr create_game_generic( } if (tier_str_valid) { int64_t parsed_tier = std::stoll(tier_str); - if ((parsed_tier >= 0) && (parsed_tier <= s->brutal_peeps_max_tier)) { + if (brutal_peeps_tier_definition(parsed_tier)) { requested_brutal_peeps_tier = parsed_tier; } } @@ -5124,23 +5121,27 @@ std::shared_ptr create_game_generic( } if (requested_brutal_peeps_tier >= 0) { + const auto* brutal_peeps_def = brutal_peeps_tier_definition(requested_brutal_peeps_tier); if (s->enable_brutal_peeps_mode && is_v4(creator_c->version()) && (difficulty == Difficulty::ULTIMATE) && - (requested_brutal_peeps_tier <= s->brutal_peeps_unlocked_tier_v4)) { + brutal_peeps_def && + (creator_character_level >= brutal_peeps_def->required_level)) { game->brutal_peeps_tier = requested_brutal_peeps_tier; - game->set_flag(Lobby::Flag::BRUTAL_PEEPS_PLUS0); - game->log.info_f("Brutal Peeps +{} enabled for BB Ultimate game via {}", + game->set_flag(Lobby::Flag::BRUTAL_PEEPS_MODE); + creator_c->selected_brutal_peeps_tier = requested_brutal_peeps_tier; + game->log.info_f("Brutal Peeps +{} enabled for BB Ultimate game via {} at creator level {}", static_cast(game->brutal_peeps_tier), - requested_brutal_peeps_source); + requested_brutal_peeps_source, + creator_character_level); } else { - game->log.info_f("Brutal Peeps +{} room prefix ignored; enable={}, version={}, difficulty={}, unlocked_v4={}, max_tier={}", + game->log.info_f("Brutal Peeps +{} room/menu request ignored; enable={}, version={}, difficulty={}, creator_level={}, required_level={}", static_cast(requested_brutal_peeps_tier), s->enable_brutal_peeps_mode, static_cast(creator_c->version()), name_for_difficulty(difficulty), - s->brutal_peeps_unlocked_tier_v4, - s->brutal_peeps_max_tier); + creator_character_level, + brutal_peeps_def ? brutal_peeps_def->required_level : 0); } } else if (requested_brutal_peeps) { game->log.info_f("Brutal Peeps room prefix ignored; invalid prefix in room name: {}", name);