diff --git a/src/Lobby.hh b/src/Lobby.hh index fb723355..4388665b 100644 --- a/src/Lobby.hh +++ b/src/Lobby.hh @@ -10,12 +10,10 @@ #include "RareItemSet.hh" enum LobbyFlag { - // games and lobbies are actually the same thing - games have negative IDs, - // lobbies have IDs >= 0 IsGame = 0x01, CheatsEnabled = 0x02, // game only Public = 0x04, // lobby only - Episode3 = 0x08, // lobby only + Episode3 = 0x08, // lobby & game QuestInProgress = 0x10, // game only JoinableQuestInProgress = 0x20, // game only Default = 0x40, // lobby only; not set for games and private lobbies diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index 9c775269..c5a1eed9 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -1523,6 +1523,8 @@ shared_ptr create_game_generic(shared_ptr s, if (((episode != 0xFF) && (episode > 3)) || (episode == 0)) { throw invalid_argument("incorrect episode number"); } + bool is_ep3 = (episode == 0xFF); + if (difficulty > 3) { throw invalid_argument("incorrect difficulty level"); } @@ -1556,15 +1558,17 @@ shared_ptr create_game_generic(shared_ptr s, game->event = Lobby::game_event_for_lobby_event(current_lobby->event); game->block = 0xFF; game->max_clients = 4; - game->flags = ((game->episode != 0xFF) ? 0 : LobbyFlag::Episode3) | LobbyFlag::IsGame; + game->flags = (is_ep3 ? LobbyFlag::Episode3 : 0) | LobbyFlag::IsGame; game->min_level = min_level; game->max_level = 0xFFFFFFFF; - // TODO: cache these somewhere so we don't read the file every time, lolz - game->rare_item_set.reset(new RareItemSet("system/blueburst/ItemRT.rel", - game->episode - 1, game->difficulty, game->section_id)); + log(INFO, "[Debug] create game: %p->flags = %08" PRIX32, game.get(), game->flags); if (game->version == GameVersion::BB) { + // TODO: cache these somewhere so we don't read the file every time, lolz + game->rare_item_set.reset(new RareItemSet("system/blueburst/ItemRT.rel", + game->episode - 1, game->difficulty, game->section_id)); + for (size_t x = 0; x < 4; x++) { game->next_item_id[x] = (0x00200000 * x) + 0x00010000; } diff --git a/src/ReceiveSubcommands.cc b/src/ReceiveSubcommands.cc index e6dff8e4..b32cc9bc 100644 --- a/src/ReceiveSubcommands.cc +++ b/src/ReceiveSubcommands.cc @@ -359,32 +359,37 @@ static void process_subcommand_use_item(shared_ptr, forward_subcommand(l, c, command, flag, p, count); } -static void process_subcommand_open_shop(shared_ptr s, - shared_ptr l, shared_ptr c, uint8_t, uint8_t, +static void process_subcommand_open_shop_or_ep3_unknown(shared_ptr s, + shared_ptr l, shared_ptr c, uint8_t command, uint8_t flag, const PSOSubcommand* p, size_t count) { - check_size(count, 2); - uint32_t shop_type = p[1].dword; + if (l->flags & LobbyFlag::Episode3) { + check_size(count, 2, 0xFFFF); + forward_subcommand(l, c, command, flag, p, count); - if ((l->version == GameVersion::BB) && l->is_game()) { - size_t num_items = (rand() % 4) + 9; - c->player.current_shop_contents.clear(); - while (c->player.current_shop_contents.size() < num_items) { - ItemData item_data; - if (shop_type == 0) { // tool shop - item_data = s->common_item_creator->create_shop_item(l->difficulty, 3); - } else if (shop_type == 1) { // weapon shop - item_data = s->common_item_creator->create_shop_item(l->difficulty, 0); - } else if (shop_type == 2) { // guards shop - item_data = s->common_item_creator->create_shop_item(l->difficulty, 1); - } else { // unknown shop... just leave it blank I guess - break; + } else { + uint32_t shop_type = p[1].dword; + + if ((l->version == GameVersion::BB) && l->is_game()) { + size_t num_items = (rand() % 4) + 9; + c->player.current_shop_contents.clear(); + while (c->player.current_shop_contents.size() < num_items) { + ItemData item_data; + if (shop_type == 0) { // tool shop + item_data = s->common_item_creator->create_shop_item(l->difficulty, 3); + } else if (shop_type == 1) { // weapon shop + item_data = s->common_item_creator->create_shop_item(l->difficulty, 0); + } else if (shop_type == 2) { // guards shop + item_data = s->common_item_creator->create_shop_item(l->difficulty, 1); + } else { // unknown shop... just leave it blank I guess + break; + } + + item_data.item_id = l->generate_item_id(c->lobby_client_id); + c->player.current_shop_contents.emplace_back(item_data); } - item_data.item_id = l->generate_item_id(c->lobby_client_id); - c->player.current_shop_contents.emplace_back(item_data); + send_shop(c, shop_type); } - - send_shop(c, shop_type); } } @@ -1105,7 +1110,7 @@ subcommand_handler_t subcommand_handlers[0x100] = { process_subcommand_unimplemented, process_subcommand_unimplemented, process_subcommand_unimplemented, - process_subcommand_open_shop, + process_subcommand_open_shop_or_ep3_unknown, process_subcommand_unimplemented, process_subcommand_unimplemented, process_subcommand_identify_item, diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 82f37014..abeb98b4 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -1424,8 +1424,10 @@ static void send_join_game_gc(shared_ptr c, shared_ptr l) { cmd.rare_seed = l->rare_seed; cmd.episode = l->episode; - // player is only sent in ep3 games - size_t data_size = (l->flags & LobbyFlag::Episode3) ? 0x1184 : 0x0110; + // player data is only sent in Episode III games; in other versions, the + // players send each other their data using 62/6D commands during loading + size_t data_size = (l->flags & LobbyFlag::Episode3) + ? sizeof(cmd) : (sizeof(cmd) - sizeof(cmd.player)); send_command(c, 0x64, player_count, &cmd, data_size); }