std::vector<mongroup*> overmapbuffer::groups_at(int x, int y, int z) { std::vector<mongroup *> result; const point omp = sm_to_om_remain( x, y ); if( !has( omp.x, omp.y ) ) { return result; } const tripoint dpos( x, y, z ); overmap &om = get( omp.x, omp.y ); for( auto it = om.zg.lower_bound( dpos ), end = om.zg.upper_bound( dpos ); it != end; ++it ) { auto &mg = it->second; if( mg.population <= 0 ) { continue; } result.push_back( &mg ); } return result; }
void overmapbuffer::spawn_monster(const int x, const int y, const int z) { // Create a copy, so we can reuse x and y later point sm( x, y ); const point omp = sm_to_om_remain( sm ); overmap &om = get( omp.x, omp.y ); for( auto it = om.monsters.begin(); it != om.monsters.end(); ) { auto &mdata = *it; if( sm.x == mdata.x && sm.y == mdata.y && z == mdata.z ) { monster &critter = mdata.mon; // The absolute position in map squares, (x,y) is already global, but it's a // submap coordinate, so translate it and add the exact monster position on // the submap. modulo because the zombies position might be negative, as it // is stored *after* it has gone out of bounds during shifting. When reloading // we only need the part that tells where on the sumap to put it. point ms( modulo( critter.posx(), SEEX ), modulo( critter.posy(), SEEY ) ); if( ms.x < 0 ) { ms.x += SEEX; } if( ms.y < 0 ) { ms.y += SEEY; } assert( ms.x >= 0 && ms.x < SEEX ); assert( ms.y >= 0 && ms.y < SEEX ); ms.x += x * SEEX; ms.y += y * SEEY; // The monster position must be local to the main map when added via game::add_zombie const point local = g->m.getlocal( ms.x, ms.y ); assert( g->m.inbounds( local.x, local.y ) ); critter.spawn( local.x, local.y ); g->add_zombie( critter ); it = om.monsters.erase( it ); } else { ++it; } } }
/* * Save to opened character.sav */ void game::serialize(std::ofstream & fout) { /* * Format version 12: Fully json, save the header. Weather and memorial exist elsewhere. * To prevent (or encourage) confusion, there is no version 8. (cata 0.8 uses v7) */ // Header fout << "# version " << savegame_version << std::endl; JsonOut json(fout, true); // pretty-print json.start_object(); // basic game state information. json.member("turn", (int)calendar::turn); json.member("calendar_start", (int)calendar::start); json.member("initial_season", (int)calendar::initial_season); json.member("eternal_season", calendar::eternal_season); json.member( "last_target", (int)last_target ); json.member( "run_mode", (int)safe_mode ); json.member( "mostseen", mostseen ); json.member( "nextspawn", (int)nextspawn ); // current map coordinates tripoint pos_sm = m.get_abs_sub(); const point pos_om = sm_to_om_remain( pos_sm.x, pos_sm.y ); json.member( "levx", pos_sm.x ); json.member( "levy", pos_sm.y ); json.member( "levz", pos_sm.z ); json.member( "om_x", pos_om.x ); json.member( "om_y", pos_om.y ); // Next, the scent map. std::stringstream rle_out; int rle_lastval = -1; int rle_count = 0; for( auto &elem : grscent ) { for( auto val : elem ) { if (val == rle_lastval) { rle_count++; } else { if ( rle_count ) { rle_out << rle_count << " "; } rle_out << val << " "; rle_lastval = val; rle_count = 1; } } } rle_out << rle_count; json.member( "grscent", rle_out.str() ); // Then each monster json.member( "active_monsters", critter_tracker->list() ); json.member( "stair_monsters", coming_to_stairs ); // save killcounts. json.member( "kills" ); json.start_object(); for( auto &elem : kills ) { json.member( elem.first.str(), elem.second ); } json.end_object(); json.member( "player", u ); Messages::serialize( json ); json.end_object(); }