static void Command_Sync(uint8_t *data) { if (!IsReplay()) { uint8_t *sync_data = &*bw::sync_data + 0x10c * (data[1] >> 4); if (sync_data[8] != data[5] || !Command_Sync_Main(data)) { if (*bw::desync_happened == 0) { LogSyncData(); // Saving is kind of pointless as the game cannot be reloaded with all players // but it might give some info if (Debug) { char buf[260]; char timestr[50]; auto now = std::chrono::system_clock::now(); auto timet = std::chrono::system_clock::to_time_t(now); std::strftime(timestr, sizeof timestr, "%m-%d %H-%M", std::localtime(&timet)); snprintf(buf, sizeof buf, "%s.%s", bw::net_players[*bw::self_net_player].name, timestr); auto time = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count(); SaveGame(buf, time); } } *bw::desync_happened = 1; bw::net_player_flags[*bw::lobby_command_user] = 0x10000; // Jep, ei or } }
void Command_GameData(uint8_t *data, int net_player) { if (*bw::in_lobby || net_player != 0) return; *bw::tileset = *(uint16_t *)(data + 0x1); *bw::map_width_tiles = *(uint16_t *)(data + 0x3); *bw::map_height_tiles = *(uint16_t *)(data + 0x5); memset(bw::temp_players.v(), 0, sizeof(Player) * Limits::Players); for (int i = 0; i < Limits::Players; i++) { Player *player = &bw::temp_players[i]; player->id = i; player->storm_id = -1; player->type = data[0x7 + i]; player->race = data[0x13 + i]; player->team = data[0x2b + i]; } if (IsTeamGame()) { int player_id = 0; int players_per_team = GetTeamGameTeamSize(); int team_count = 2; if (bw::game_data[0].got.game_type_id != 0xf) // Tvb team_count = *bw::team_game; for (int i = 0; i < team_count; i++) { for (int j = 0; j < players_per_team; j++) { if (!IsActivePlayer(player_id)) break; Player *player = &bw::temp_players[player_id]; player->team = i + 1; player_id += 1; } } } memcpy(bw::player_types_unused.v(), data + 0x1f, 0xc); memcpy(bw::force_layout.v(), data + 0x2b, 0xc); memcpy(bw::user_select_slots.v(), data + 0x37, 0x8); if (!IsReplay()) memcpy(bw::replay_user_select_slots.v(), data + 0x37, 0x8); int save_player_id = *bw::loaded_save ? *bw::loaded_local_player_id : 0; int save_unique_player_id = *bw::loaded_save ? *bw::loaded_local_unique_player_id : 0; int flags = *bw::own_net_player_flags; MakeJoinedGameCommand(flags, 1, save_player_id, save_unique_player_id, *bw::saved_seed, false); *bw::lobby_state = 3; }
void Neutralize(int player) { Assert(player >= 0 && player < Limits::Players); if (IsCheatActive(Cheats::Staying_Alive) && IsHumanPlayer(player)) return; if (bw::game_data->got.victory_conditions == 4 || bw::game_data->got.victory_conditions == 5) { Unit *next = bw::first_player_unit[player]; while (next != nullptr) { Unit *unit = next; next = unit->player_units.next; if (units_dat_flags[unit->unit_id] & UnitFlags::Subunit || unit->sprite == nullptr) continue; if (unit->order == Order::Die) continue; if (units_dat_flags[unit->unit_id] & UnitFlags::SingleEntity && unit->powerup.carrying_unit != nullptr) { Unit *worker = unit->powerup.carrying_unit; if (worker->carried_powerup_flags != 0) { DeletePowerupImages(worker); if (worker->worker.powerup) { worker->worker.powerup->order_flags |= 0x4; worker->worker.powerup->Kill(nullptr); } worker->worker.powerup = nullptr; worker->carried_powerup_flags = 0; } } else { unit->Kill(nullptr); } } } else { Unit *next = bw::first_player_unit[player]; while (next != nullptr) { Unit *unit = next; next = unit->player_units.next; NeutralizeUnit(unit); } RefreshUi(); } if (*bw::team_game) { for (int i = 0; i < Limits::ActivePlayers; i++) { if (bw::players[player].team == bw::players[i].team) MarkPlayerNeutral(i); } } else { MarkPlayerNeutral(player); } if (IsReplay()) { *bw::replay_visions &= ~(1 << player); *bw::player_visions &= ~(1 << player); *bw::player_exploration_visions &= ~(0x100 << player); } }
void GenerateFog() { int screen_x = *bw::screen_pos_x_tiles; if (screen_x != 0) screen_x--; int screen_y = *bw::screen_pos_y_tiles; if (screen_y != 0) screen_y--; uint32_t *flags = (*bw::map_tile_flags) + screen_y * *bw::map_width_tiles + screen_x; uint32_t *orig_flags = flags; uint8_t *pos = *bw::fog_arr1; int shown_value = *bw::fog_variance_amount; int fow_value = shown_value / 2; int y_pos = screen_y; for (int i = 0; i < 0x11; i++) { int x_pos = *bw::screen_pos_x_tiles - 1; flags = orig_flags; for (int i = 0; i < 0x18; i++) { // Obviously people can just remove multiplayer check if they wish // Bw had nice vision-based sync but it does not work with dynamically allocated sprites if (all_visions && !IsMultiplayer()) { if ((0xff00 & flags[0]) == 0xff00) *pos = 0; else if ((0xff & flags[0]) == 0xff) *pos = fow_value; else *pos = shown_value; } else if (IsReplay()) { if (*bw::replay_show_whole_map) *pos = shown_value; else if (!((*bw::replay_visions << 8) & ~flags[0])) *pos = 0; else if (!(*bw::replay_visions & ~flags[0])) *pos = fow_value; else *pos = shown_value; } else { if (*bw::player_exploration_visions & flags[0]) *pos = 0; else if (*bw::player_visions & flags[0]) *pos = fow_value; else *pos = shown_value; } if (x_pos < *bw::map_width_tiles - 1 && x_pos >= 0) flags++; x_pos++; pos++; } if (y_pos < *bw::map_height_tiles - 1 && y_pos >= 0) orig_flags += *bw::map_width_tiles; y_pos++; } // Blend fog // Screen is 0x18 x 0x11 tiles // Well every border has 1 nonvisible tile, it is only used for blending? pos = *bw::fog_arr1 + 0x18 + 0x1; uint8_t *out = *bw::fog_arr2 + 0x18 + 0x1; for (int i = 0; i < 0x11 - 2; i++) { for (int i = 0; i < 0x18 - 2; i++) { int val = pos[0] * 2; val = (val + pos[-1] + pos[1] + pos[-0x18] + pos[0x18]) * 2; val = (val + pos[-0x17] + pos[0x17] + pos[-0x19] + pos[0x19]) / 16; *out = val; pos++; out++; } pos += 2; out += 2; } }