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;
        }
    }
}
Esempio n. 3
0
/*
 * 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();
}