Ejemplo n.º 1
0
void mapbuffer::save( bool delete_after_save )
{
    std::stringstream map_directory;
    map_directory << world_generator->active_world->world_path << "/maps";
    assure_dir_exist( map_directory.str().c_str() );

    int num_saved_submaps = 0;
    int num_total_submaps = submap_list.size();

    point map_origin = overmapbuffer::sm_to_omt_copy( g->levx, g->levy );
    map_origin.x += g->cur_om->pos().x * OMAPX;
    map_origin.y += g->cur_om->pos().y * OMAPY;

    // A set of already-saved submaps, in global overmap coordinates.
    std::set<tripoint, pointcomp> saved_submaps;
    std::list<tripoint> submaps_to_delete;
    for( std::map<tripoint, submap *, pointcomp>::iterator it = submaps.begin();
         it != submaps.end(); ++it ) {
        if (num_total_submaps > 100 && num_saved_submaps % 100 == 0) {
            popup_nowait(_("Please wait as the map saves [%d/%d]"),
                         num_saved_submaps, num_total_submaps);
        }
        // Whatever the coordinates of the current submap are,
        // we're saving a 2x2 quad of submaps at a time.
        // Submaps are generated in quads, so we know if we have one member of a quad,
        // we have the rest of it, if that assumtion is broken we have REAL problems.
        const tripoint om_addr = overmapbuffer::sm_to_omt_copy( it->first );
        if( saved_submaps.count( om_addr ) != 0 ) {
            // Already handled this one.
            continue;
        }
        saved_submaps.insert( om_addr );

        // A segment is a chunk of 32x32 submap quads.
        // We're breaking them into subdirectories so there aren't too many files per directory.
        // Might want to make a set for this one too so it's only checked once per save().
        std::stringstream segment_path;
        tripoint segment_addr = overmapbuffer::omt_to_seg_copy( om_addr );
        segment_path << map_directory.str() << "/" << segment_addr.x << "." <<
            segment_addr.y << "." << segment_addr.z;
        assure_dir_exist( segment_path.str().c_str() );

        std::stringstream quad_path;
        quad_path << segment_path.str() << "/" << om_addr.x << "." <<
            om_addr.y << "." << om_addr.z << ".map";

                   // delete_on_save deletes everything, otherwise delete submaps
                   // outside the current map.
        save_quad( quad_path.str(), om_addr, submaps_to_delete,
                   delete_after_save || om_addr.z != g->levz ||
                   om_addr.x < map_origin.x || om_addr.y < map_origin.y ||
                   om_addr.x > map_origin.x + (MAPSIZE / 2) ||
                   om_addr.y > map_origin.y + (MAPSIZE / 2) );
        num_saved_submaps += 4;
    }
    for( std::list<tripoint>::iterator it = submaps_to_delete.begin();
         it != submaps_to_delete.end(); ++it ) {
        remove_submap( *it );
    }
}
Ejemplo n.º 2
0
void mapbuffer::save( bool delete_after_save )
{
    std::stringstream map_directory;
    map_directory << world_generator->active_world->world_path << "/maps";
    assure_dir_exist( map_directory.str().c_str() );

    int num_saved_submaps = 0;
    int num_total_submaps = submaps.size();

    const tripoint map_origin = overmapbuffer::sm_to_omt_copy( g->m.get_abs_sub() );
    const bool map_has_zlevels = g != nullptr && g->m.has_zlevels();

    // A set of already-saved submaps, in global overmap coordinates.
    std::set<tripoint> saved_submaps;
    std::list<tripoint> submaps_to_delete;
    for( auto &elem : submaps ) {
        if (num_total_submaps > 100 && num_saved_submaps % 100 == 0) {
            popup_nowait(_("Please wait as the map saves [%d/%d]"),
                         num_saved_submaps, num_total_submaps);
        }
        // Whatever the coordinates of the current submap are,
        // we're saving a 2x2 quad of submaps at a time.
        // Submaps are generated in quads, so we know if we have one member of a quad,
        // we have the rest of it, if that assumption is broken we have REAL problems.
        const tripoint om_addr = overmapbuffer::sm_to_omt_copy( elem.first );
        if( saved_submaps.count( om_addr ) != 0 ) {
            // Already handled this one.
            continue;
        }
        saved_submaps.insert( om_addr );

        // A segment is a chunk of 32x32 submap quads.
        // We're breaking them into subdirectories so there aren't too many files per directory.
        // Might want to make a set for this one too so it's only checked once per save().
        std::stringstream dirname;
        tripoint segment_addr = overmapbuffer::omt_to_seg_copy( om_addr );
        dirname << map_directory.str() << "/" << segment_addr.x << "." <<
                     segment_addr.y << "." << segment_addr.z;

        std::stringstream quad_path;
        quad_path << dirname.str() << "/" << om_addr.x << "." <<
                  om_addr.y << "." << om_addr.z << ".map";

        // delete_on_save deletes everything, otherwise delete submaps
        // outside the current map.
        const bool zlev_del = !map_has_zlevels && om_addr.z != g->get_levz();
        save_quad( dirname.str(), quad_path.str(), om_addr, submaps_to_delete,
                   delete_after_save || zlev_del ||
                   om_addr.x < map_origin.x || om_addr.y < map_origin.y ||
                   om_addr.x > map_origin.x + (MAPSIZE / 2) ||
                   om_addr.y > map_origin.y + (MAPSIZE / 2) );
        num_saved_submaps += 4;
    }
    for( auto &elem : submaps_to_delete ) {
        remove_submap( elem );
    }
}
Ejemplo n.º 3
0
bool worldfactory::save_world(WORLDPTR world, bool is_conversion)
{
    // if world is NULL then change it to the active_world
    if (!world) {
        world = active_world;
    }
    // if the active_world is NULL then return w/o saving
    if (!world) {
        return false;
    }

    std::ofstream fout;
    std::stringstream woption;

    woption << world->world_path << "/" << WORLD_OPTION_FILE;

    if (!assure_dir_exist(world->world_path)) {
        DebugLog( D_ERROR, DC_ALL ) << "Unable to create or open world[" << world->world_name <<
                                    "] directory for saving";
        return false;
    }

    if (!is_conversion) {
        fopen_exclusive(fout, woption.str().c_str());
        if (!fout.is_open()) {
            popup( _( "Could not open the world file %s, check file permissions." ), woption.str().c_str() );
            return false;
        }
        fout << world_options_header() << std::endl;

        for( auto &elem : world->world_options ) {
            fout << "#" << elem.second.getTooltip() << std::endl;
            fout << "#" << elem.second.getDefaultText() << std::endl;
            fout << elem.first << " " << elem.second.getValue() << std::endl << std::endl;
        }
        fclose_exclusive(fout, woption.str().c_str());
        if( fout.fail() ) {
            popup( _( "Failed to save the world file to %s." ), woption.str().c_str() );
        }
    }
    mman->save_mods_list(world);
    return true;
}
Ejemplo n.º 4
0
bool save_auto_pickup(bool bCharacter)
{
    std::ofstream fout;
    std::string sFile = FILENAMES["autopickup"];

    if (bCharacter) {
        sFile = world_generator->active_world->world_path + "/" + base64_encode(g->u.name) + ".apu.txt";
        std::ifstream fin;

        fin.open((world_generator->active_world->world_path + "/" +
                  base64_encode(g->u.name) + ".sav").c_str());
        if(!fin.is_open()) {
            return true;
        }
        fin.close();
    }

    fout.exceptions(std::ios::badbit | std::ios::failbit);
    try {
        assure_dir_exist(FILENAMES["config_dir"]);
        fout.open(sFile.c_str());

        fout << auto_pickup_header(bCharacter) << std::endl;
        for (std::vector<cPickupRules>::iterator it =
                 vAutoPickupRules[(bCharacter) ? APU_CHARACTER : APU_GLOBAL].begin();
             it != vAutoPickupRules[(bCharacter) ? APU_CHARACTER : APU_GLOBAL].end(); ++it) {
            fout << it->sRule << ";";
            fout << (it->bActive ? "T" : "F") << ";";
            fout << (it->bExclude ? "T" : "F");
            fout << "\n";
        }

        if (!bCharacter) {
            merge_vector();
            createPickupRules();
        }
        fout.close();
        return true;
    } catch(std::ios::failure &) {
        popup(_("Failed to write autopickup rules to %s"), sFile.c_str());
        return false;
    }
}
Ejemplo n.º 5
0
bool worldfactory::save_world(WORLDPTR world, bool is_conversion)
{
    // if world is NULL then change it to the active_world
    if (!world) {
        world = active_world;
    }
    // if the active_world is NULL then return w/o saving
    if (!world) {
        return false;
    }

    std::ofstream fout;
    std::stringstream woption;

    woption << world->world_path << "/" << WORLD_OPTION_FILE;

    if (!assure_dir_exist(world->world_path)) {
        DebugLog( D_ERROR, DC_ALL ) << "Unable to create or open world[" << world->world_name << "] directory for saving";
        return false;
    }

    if (!is_conversion) {
        fopen_exclusive(fout, woption.str().c_str());
        if (!fout.is_open()) {
            fout.close();
            return false;
        }
        fout << world_options_header() << std::endl;

        for (auto it = world->world_options.begin();
             it != world->world_options.end(); ++it) {
            fout << "#" << it->second.getTooltip() << std::endl;
            fout << "#Default: " << it->second.getDefaultText() << std::endl;
            fout << it->first << " " << it->second.getValue() << std::endl << std::endl;
        }
        fclose_exclusive(fout, woption.str().c_str());
    }
    mman->save_mods_list(world);
    return true;
}
Ejemplo n.º 6
0
//Basic Init, create the font, backbuffer, etc
WINDOW *curses_init(void)
{
   // _windows = new WINDOW[20];         //initialize all of our variables
    lastchar=-1;
    inputdelay=-1;

    int fontsize = 16;
    std::string typeface;
    int map_fontwidth = 8;
    int map_fontheight = 16;
    int map_fontsize = 16;
    std::string map_typeface;
    int overmap_fontwidth = 8;
    int overmap_fontheight = 16;
    int overmap_fontsize = 16;
    std::string overmap_typeface;
    bool fontblending;

    std::ifstream jsonstream(FILENAMES["fontdata"].c_str(), std::ifstream::binary);
    if (jsonstream.good()) {
        JsonIn json(jsonstream);
        JsonObject config = json.get_object();
        // fontsize, fontblending, map_* are ignored in wincurse.
        fontwidth = config.get_int("fontwidth", fontwidth);
        fontheight = config.get_int("fontheight", fontheight);
        typeface = config.get_string("typeface", typeface);
        jsonstream.close();
    } else { // User fontdata is missed. Try to load legacy fontdata.
        // Get and save all values. With unused.
        std::ifstream InStream(FILENAMES["legacy_fontdata"].c_str(), std::ifstream::binary);
        if(InStream.good()) {
            JsonIn jIn(InStream);
            JsonObject config = jIn.get_object();
            fontwidth = config.get_int("fontwidth", fontwidth);
            fontheight = config.get_int("fontheight", fontheight);
            fontsize = config.get_int("fontsize", fontsize);
            typeface = config.get_string("typeface", typeface);
            map_fontwidth = config.get_int("map_fontwidth", fontwidth);
            map_fontheight = config.get_int("map_fontheight", fontheight);
            map_fontsize = config.get_int("map_fontsize", fontsize);
            map_typeface = config.get_string("map_typeface", typeface);
            overmap_fontwidth = config.get_int("overmap_fontwidth", fontwidth);
            overmap_fontheight = config.get_int("overmap_fontheight", fontheight);
            overmap_fontsize = config.get_int("overmap_fontsize", fontsize);
            overmap_typeface = config.get_string("overmap_typeface", typeface);
            InStream.close();
            // Save legacy as user fontdata.
            assure_dir_exist(FILENAMES["config_dir"]);
            std::ofstream OutStream(FILENAMES["fontdata"].c_str(), std::ofstream::binary);
            if(!OutStream.good()) {
                DebugLog( D_ERROR, DC_ALL ) << "Can't save user fontdata file.\n"
                << "Check permissions for: " << FILENAMES["fontdata"].c_str();
                return NULL;
            }
            JsonOut jOut(OutStream, true); // pretty-print
            jOut.start_object();
            jOut.member("fontblending", fontblending);
            jOut.member("fontwidth", fontwidth);
            jOut.member("fontheight", fontheight);
            jOut.member("fontsize", fontsize);
            jOut.member("typeface", typeface);
            jOut.member("map_fontwidth", map_fontwidth);
            jOut.member("map_fontheight", map_fontheight);
            jOut.member("map_fontsize", map_fontsize);
            jOut.member("map_typeface", map_typeface);
            jOut.member("overmap_fontwidth", overmap_fontwidth);
            jOut.member("overmap_fontheight", overmap_fontheight);
            jOut.member("overmap_fontsize", overmap_fontsize);
            jOut.member("overmap_typeface", overmap_typeface);
            jOut.end_object();
            OutStream << "\n";
            OutStream.close();
        } else {
            DebugLog( D_ERROR, DC_ALL ) << "Can't load fontdata files.\n"
            << "Check permissions for:\n" << FILENAMES["legacy_fontdata"].c_str() << "\n"
            << FILENAMES["fontdata"].c_str() << "\n";
            return NULL;
        }
    }

    halfwidth=fontwidth / 2;
    halfheight=fontheight / 2;
    WindowWidth= OPTIONS["TERMINAL_X"] * fontwidth;
    WindowHeight = OPTIONS["TERMINAL_Y"] * fontheight;

    WinCreate();    //Create the actual window, register it, etc
    timeBeginPeriod(1); // Set Sleep resolution to 1ms
    CheckMessages();    //Let the message queue handle setting up the window

    WindowDC   = GetDC(WindowHandle);
    backbuffer = CreateCompatibleDC(WindowDC);

    BITMAPINFO bmi = BITMAPINFO();
    bmi.bmiHeader.biSize         = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth        = WindowWidth;
    bmi.bmiHeader.biHeight       = -WindowHeight;
    bmi.bmiHeader.biPlanes       = 1;
    bmi.bmiHeader.biBitCount     = 8;
    bmi.bmiHeader.biCompression  = BI_RGB; // Raw RGB
    bmi.bmiHeader.biSizeImage    = WindowWidth * WindowHeight * 1;
    bmi.bmiHeader.biClrUsed      = 16; // Colors in the palette
    bmi.bmiHeader.biClrImportant = 16; // Colors in the palette
    backbit = CreateDIBSection(0, &bmi, DIB_RGB_COLORS, (void**)&dcbits, NULL, 0);
    DeleteObject(SelectObject(backbuffer, backbit));//load the buffer into DC

    // Load private fonts
    if (SetCurrentDirectoryW(L"data\\font")){
        WIN32_FIND_DATA findData;
        for (HANDLE findFont = FindFirstFileW(L".\\*", &findData); findFont != INVALID_HANDLE_VALUE; )
        {
            if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){ // Skip folders
                AddFontResourceExW(findData.cFileName, FR_PRIVATE,NULL);
            }
            if (!FindNextFile(findFont, &findData)){
                FindClose(findFont);
                break;
            }
        }
        SetCurrentDirectoryW(L"..\\..");
    }

    // Use desired font, if possible
    font = CreateFontW(fontheight, fontwidth, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
                      DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
                      PROOF_QUALITY, FF_MODERN, widen(typeface).c_str());

    SetBkMode(backbuffer, TRANSPARENT);//Transparent font backgrounds
    SelectObject(backbuffer, font);//Load our font into the DC
//    WindowCount=0;

    init_colors();

    mainwin = newwin(OPTIONS["TERMINAL_Y"],OPTIONS["TERMINAL_X"],0,0);
    return mainwin;   //create the 'stdscr' window and return its ref
}
Ejemplo n.º 7
0
void mapbuffer::save_quad( const std::string &dirname, const std::string &filename, 
                           const tripoint &om_addr, std::list<tripoint> &submaps_to_delete, 
                           bool delete_after_save )
{
    std::vector<point> offsets;
    std::vector<tripoint> submap_addrs;
    offsets.push_back( point(0, 0) );
    offsets.push_back( point(0, 1) );
    offsets.push_back( point(1, 0) );
    offsets.push_back( point(1, 1) );

    bool all_uniform = true;
    for( auto &offsets_offset : offsets ) {
        tripoint submap_addr = overmapbuffer::omt_to_sm_copy( om_addr );
        submap_addr.x += offsets_offset.x;
        submap_addr.y += offsets_offset.y;
        submap_addrs.push_back( submap_addr );
        submap *sm = submaps[submap_addr];
        if( sm != nullptr && !sm->is_uniform ) {
            all_uniform = false;
        }
    }

    if( all_uniform ) {
        // Nothing to save - this quad will be regenerated faster than it would be re-read
        if( delete_after_save ) {
            for( auto &submap_addr : submap_addrs ) {
                if( submaps.count( submap_addr ) > 0 && submaps[submap_addr] != nullptr ) {
                    submaps_to_delete.push_back( submap_addr );
                }
            }
        }

        return;
    }

    // Don't create the directory if it would be empty
    assure_dir_exist( dirname.c_str() );
    std::ofstream fout;
    fopen_exclusive( fout, filename.c_str() );
    if( !fout.is_open() ) {
        return;
    }

    JsonOut jsout( fout );
    jsout.start_array();
    for( auto &submap_addr : submap_addrs ) {
        if( submaps.count( submap_addr ) == 0 ) {
            continue;
        }

        submap *sm = submaps[submap_addr];
        if( sm == nullptr ) {
            continue;
        }

        jsout.start_object();

        jsout.member( "version", savegame_version);

        jsout.member( "coordinates" );
        jsout.start_array();
        jsout.write( submap_addr.x );
        jsout.write( submap_addr.y );
        jsout.write( submap_addr.z );
        jsout.end_array();

        jsout.member( "turn_last_touched", sm->turn_last_touched );
        jsout.member( "temperature", sm->temperature );

        jsout.member( "terrain" );
        jsout.start_array();
        for(int j = 0; j < SEEY; j++) {
            for(int i = 0; i < SEEX; i++) {
                // Save terrains
                jsout.write( sm->ter[i][j].obj().id );
            }
        }
        jsout.end_array();

        // Write out the radiation array in a simple RLE scheme.
        // written in intensity, count pairs
        jsout.member( "radiation" );
        jsout.start_array();
        int lastrad = -1;
        int count = 0;
        for(int j = 0; j < SEEY; j++) {
            for(int i = 0; i < SEEX; i++) {
                // Save radiation, re-examine this because it doesn't look like it works right
                int r = sm->get_radiation(i, j);
                if (r == lastrad) {
                    count++;
                } else {
                    if (count) {
                        jsout.write( count );
                    }
                    jsout.write( r );
                    lastrad = r;
                    count = 1;
                }
            }
        }
        jsout.write( count );
        jsout.end_array();

        jsout.member("furniture");
        jsout.start_array();
        for(int j = 0; j < SEEY; j++) {
            for(int i = 0; i < SEEX; i++) {
                // Save furniture
                if( sm->get_furn( i, j ) != f_null ) {
                    jsout.start_array();
                    jsout.write( i );
                    jsout.write( j );
                    jsout.write( sm->get_furn( i, j ).obj().id );
                    jsout.end_array();
                }
            }
        }
        jsout.end_array();

        jsout.member( "items" );
        jsout.start_array();
        for(int j = 0; j < SEEY; j++) {
            for(int i = 0; i < SEEX; i++) {
                if( sm->itm[i][j].empty() ) {
                    continue;
                }
                jsout.write( i );
                jsout.write( j );
                jsout.write( sm->itm[i][j] );
            }
        }
        jsout.end_array();

        jsout.member( "traps" );
        jsout.start_array();
        for(int j = 0; j < SEEY; j++) {
            for(int i = 0; i < SEEX; i++) {
                // Save traps
                if (sm->get_trap( i, j ) != tr_null) {
                    jsout.start_array();
                    jsout.write( i );
                    jsout.write( j );
                    // TODO: jsout should support writting an id like jsout.write( trap_id )
                    jsout.write( sm->get_trap( i, j ).id().str() );
                    jsout.end_array();
                }
            }
        }
        jsout.end_array();

        jsout.member( "fields" );
        jsout.start_array();
        for(int j = 0; j < SEEY; j++) {
            for(int i = 0; i < SEEX; i++) {
                // Save fields
                if (sm->fld[i][j].fieldCount() > 0) {
                    jsout.write( i );
                    jsout.write( j );
                    jsout.start_array();
                    for( auto &fld : sm->fld[i][j] ) {
                        const field_entry &cur = fld.second;
                            // We don't seem to have a string identifier for fields anywhere.
                            jsout.write( cur.getFieldType() );
                            jsout.write( cur.getFieldDensity() );
                            jsout.write( cur.getFieldAge() );
                    }
                    jsout.end_array();
                }
            }
        }
        jsout.end_array();

        jsout.member("cosmetics");
        jsout.start_array();
        for (int j = 0; j < SEEY; j++) {
            for (int i = 0; i < SEEX; i++) {
                if (sm->cosmetics[i][j].size() > 0) {
                    jsout.start_array();
                    jsout.write(i);
                    jsout.write(j);
                    jsout.write(sm->cosmetics[i][j]);
                    jsout.end_array();
                }
            }
        }
        jsout.end_array();

        // Output the spawn points
        jsout.member( "spawns" );
        jsout.start_array();
        for( auto &elem : sm->spawns ) {
            jsout.start_array();
            jsout.write( elem.type.str() ); // TODO: json should know how to write string_ids
            jsout.write( elem.count );
            jsout.write( elem.posx );
            jsout.write( elem.posy );
            jsout.write( elem.faction_id );
            jsout.write( elem.mission_id );
            jsout.write( elem.friendly );
            jsout.write( elem.name );
            jsout.end_array();
        }
        jsout.end_array();

        jsout.member( "vehicles" );
        jsout.start_array();
        for( auto &elem : sm->vehicles ) {
            // json lib doesn't know how to turn a vehicle * into a vehicle,
            // so we have to iterate manually.
            jsout.write( *elem );
        }
        jsout.end_array();

        // Output the computer
        if (sm->comp.name != "") {
            jsout.member( "computers", sm->comp.save_data() );
        }

        // Output base camp if any
        if (sm->camp.is_valid()) {
            jsout.member( "camp" );
            jsout.write( sm->camp.save_data() );
        }
        if( delete_after_save ) {
            submaps_to_delete.push_back( submap_addr );
        }
        jsout.end_object();
    }

    jsout.end_array();
    fclose_exclusive( fout, filename.c_str() );
}
Ejemplo n.º 8
0
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int argc = __argc;
    char **argv = __argv;
#else
int main(int argc, char *argv[])
{
#endif
    int seed = time(NULL);
    bool verifyexit = false;
    bool check_mods = false;
    std::string dump;
    dump_mode dmode = dump_mode::TSV;
    std::vector<std::string> opts;
    std::string world; /** if set try to load first save in this world on startup */

    // Set default file paths
#ifdef PREFIX
#define Q(STR) #STR
#define QUOTE(STR) Q(STR)
    PATH_INFO::init_base_path(std::string(QUOTE(PREFIX)));
#else
    PATH_INFO::init_base_path("");
#endif

#if (defined USE_HOME_DIR || defined USE_XDG_DIR)
    PATH_INFO::init_user_dir();
#else
    PATH_INFO::init_user_dir("./");
#endif
    PATH_INFO::set_standard_filenames();

    MAP_SHARING::setDefaults();
    {
        const char *section_default = nullptr;
        const char *section_map_sharing = "Map sharing";
        const char *section_user_directory = "User directories";
        const std::array<arg_handler, 12> first_pass_arguments = {{
            {
                "--seed", "<string of letters and or numbers>",
                "Sets the random number generator's seed value",
                section_default,
                [&seed](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    const unsigned char *hash_input = (const unsigned char *) params[0];
                    seed = djb2_hash(hash_input);
                    return 1;
                }
            },
            {
                "--jsonverify", nullptr,
                "Checks the cdda json files",
                section_default,
                [&verifyexit](int, const char **) -> int {
                    verifyexit = true;
                    return 0;
                }
            },
            {
                "--check-mods", "[mods...]",
                "Checks the json files belonging to cdda mods",
                section_default,
                [&check_mods,&opts]( int n, const char *params[] ) -> int {
                    check_mods = true;
                    test_mode = true;
                    for( int i = 0; i < n; ++i ) {
                        opts.emplace_back( params[ i ] );
                    }
                    return 0;
                }
            },
            {
                "--dump-stats", "<what> [mode = TSV] [opts...]",
                "Dumps item stats",
                section_default,
                [&dump,&dmode,&opts](int n, const char *params[]) -> int {
                    if( n < 1 ) {
                        return -1;
                    }
                    test_mode = true;
                    dump = params[ 0 ];
                    for( int i = 2; i < n; ++i ) {
                        opts.emplace_back( params[ i ] );
                    }
                    if( n >= 2 ) {
                        if( !strcmp( params[ 1 ], "TSV" ) ) {
                            dmode = dump_mode::TSV;
                            return 0;
                        } else if( !strcmp( params[ 1 ], "HTML" ) ) {
                            dmode = dump_mode::HTML;
                            return 0;
                        } else {
                            return -1;
                        }
                    }
                    return 0;
                }
            },
            {
                "--world", "<name>",
                "Load world",
                section_default,
                [&world](int n, const char *params[]) -> int {
                    if( n < 1 ) {
                        return -1;
                    }
                    world = params[0];
                    return 1;
                }
            },
            {
                "--basepath", "<path>",
                "Base path for all game data subdirectories",
                section_default,
                [](int num_args, const char **params) {
                    if (num_args < 1) return -1;
                    PATH_INFO::init_base_path(params[0]);
                    PATH_INFO::set_standard_filenames();
                    return 1;
                }
            },
            {
                "--shared", nullptr,
                "Activates the map-sharing mode",
                section_map_sharing,
                [](int, const char **) -> int {
                    MAP_SHARING::setSharing(true);
                    MAP_SHARING::setCompetitive(true);
                    MAP_SHARING::setWorldmenu(false);
                    return 0;
                }
            },
            {
                "--username", "<name>",
                "Instructs map-sharing code to use this name for your character.",
                section_map_sharing,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    MAP_SHARING::setUsername(params[0]);
                    return 1;
                }
            },
            {
                "--addadmin", "<username>",
                "Instructs map-sharing code to use this name for your character and give you "
                    "access to the cheat functions.",
                section_map_sharing,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    MAP_SHARING::addAdmin(params[0]);
                    return 1;
                }
            },
            {
                "--adddebugger", "<username>",
                "Informs map-sharing code that you're running inside a debugger",
                section_map_sharing,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    MAP_SHARING::addDebugger(params[0]);
                    return 1;
                }
            },
            {
                "--competitive", nullptr,
                "Instructs map-sharing code to disable access to the in-game cheat functions",
                section_map_sharing,
                [](int, const char **) -> int {
                    MAP_SHARING::setCompetitive(true);
                    return 0;
                }
            },
            {
                "--userdir", "<path>",
                "Base path for user-overrides to files from the ./data directory and named below",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::init_user_dir(params[0]);
                    PATH_INFO::set_standard_filenames();
                    return 1;
                }
            }
        }};

        // The following arguments are dependent on one or more of the previous flags and are run
        // in a second pass.
        const std::array<arg_handler, 9> second_pass_arguments = {{
            {
                "--worldmenu", nullptr,
                "Enables the world menu in the map-sharing code",
                section_map_sharing,
                [](int, const char **) -> int {
                    MAP_SHARING::setWorldmenu(true);
                    return true;
                }
            },
            {
                "--datadir", "<directory name>",
                "Sub directory from which game data is loaded",
                nullptr,
                [](int num_args, const char **params) -> int {
                      if (num_args < 1) return -1;
                      PATH_INFO::update_pathname("datadir", params[0]);
                      PATH_INFO::update_datadir();
                      return 1;
                }
            },
            {
                "--savedir", "<directory name>",
                "Subdirectory for game saves",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("savedir", params[0]);
                    return 1;
                }
            },
            {
                "--configdir", "<directory name>",
                "Subdirectory for game configuration",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("config_dir", params[0]);
                    PATH_INFO::update_config_dir();
                    return 1;
                }
            },
            {
                "--memorialdir", "<directory name>",
                "Subdirectory for memorials",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("memorialdir", params[0]);
                    return 1;
                }
            },
            {
                "--optionfile", "<filename>",
                "Name of the options file within the configdir",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("options", params[0]);
                    return 1;
                }
            },
            {
                "--keymapfile", "<filename>",
                "Name of the keymap file within the configdir",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("keymap", params[0]);
                    return 1;
                }
            },
            {
                "--autopickupfile", "<filename>",
                "Name of the autopickup options file within the configdir",
                nullptr,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("autopickup", params[0]);
                    return 1;
                }
            },
            {
                "--motdfile", "<filename>",
                "Name of the message of the day file within the motd directory",
                nullptr,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("motd", params[0]);
                    return 1;
                }
            },
        }};

        // Process CLI arguments.
        const size_t num_first_pass_arguments =
            sizeof(first_pass_arguments) / sizeof(first_pass_arguments[0]);
        const size_t num_second_pass_arguments =
            sizeof(second_pass_arguments) / sizeof(second_pass_arguments[0]);
        int saved_argc = --argc; // skip program name
        const char **saved_argv = (const char **)++argv;
        while (argc) {
            if(!strcmp(argv[0], "--help")) {
                printHelpMessage(first_pass_arguments.data(), num_first_pass_arguments,
                    second_pass_arguments.data(), num_second_pass_arguments);
                return 0;
            } else {
                bool arg_handled = false;
                for (size_t i = 0; i < num_first_pass_arguments; ++i) {
                    auto &arg_handler = first_pass_arguments[i];
                    if (!strcmp(argv[0], arg_handler.flag)) {
                        argc--;
                        argv++;
                        int args_consumed = arg_handler.handler(argc, (const char **)argv);
                        if (args_consumed < 0) {
                            printf("Failed parsing parameter '%s'\n", *(argv - 1));
                            exit(1);
                        }
                        argc -= args_consumed;
                        argv += args_consumed;
                        arg_handled = true;
                        break;
                    }
                }
                // Skip other options.
                if (!arg_handled) {
                    --argc;
                    ++argv;
                }
            }
        }
        while (saved_argc) {
            bool arg_handled = false;
            for (size_t i = 0; i < num_second_pass_arguments; ++i) {
                auto &arg_handler = second_pass_arguments[i];
                if (!strcmp(saved_argv[0], arg_handler.flag)) {
                    --saved_argc;
                    ++saved_argv;
                    int args_consumed = arg_handler.handler(saved_argc, saved_argv);
                    if (args_consumed < 0) {
                        printf("Failed parsing parameter '%s'\n", *(argv - 1));
                        exit(1);
                    }
                    saved_argc -= args_consumed;
                    saved_argv += args_consumed;
                    arg_handled = true;
                    break;
                }
            }
            // Ingore unknown options.
            if (!arg_handled) {
                --saved_argc;
                ++saved_argv;
            }
        }
    }

    if (!assure_dir_exist(FILENAMES["user_dir"].c_str())) {
        printf("Can't open or create %s. Check permissions.\n",
               FILENAMES["user_dir"].c_str());
        exit(1);
    }

    setupDebug();

/**
 * OS X does not populate locale env vars correctly (they usually default to
 * "C") so don't bother trying to set the locale based on them.
 */
#if (!defined MACOSX)
    if (setlocale(LC_ALL, "") == NULL) {
        DebugLog(D_WARNING, D_MAIN) << "Error while setlocale(LC_ALL, '').";
    } else {
#endif
        try {
            std::locale::global( std::locale( "" ) );
        } catch( const std::exception& ) {
            // if user default locale retrieval isn't implemented by system
            try{
                // default to basic C locale
                std::locale::global( std::locale::classic() );
            } catch( const std::exception &err ) {
                debugmsg( "%s", err.what() );
                exit_handler(-999);
            }
        }
#if (!defined MACOSX)
    }
#endif

    get_options().init();
    get_options().load();
    set_language();

    // in test mode don't initialize curses to avoid escape sequences being inserted into output stream
    if( !test_mode ) {
        try {
			catacurses::init_interface();
        } catch( const std::exception &err ) {
            // can't use any curses function as it has not been initialized
            std::cerr << "Error while initializing the interface: " << err.what() << std::endl;
            DebugLog( D_ERROR, DC_ALL ) << "Error while initializing the interface: " << err.what() << "\n";
            return 1;
        }
    }

    srand(seed);

    g = new game;
    // First load and initialize everything that does not
    // depend on the mods.
    try {
        g->load_static_data();
        if (verifyexit) {
            exit_handler(0);
        }
        if( !dump.empty() ) {
            init_colors();
            exit( g->dump_stats( dump, dmode, opts ) ? 0 : 1 );
        }
        if( check_mods ) {
            init_colors();
            loading_ui ui( false );
            exit( g->check_mod_data( opts, ui ) && !test_dirty ? 0 : 1 );
        }
    } catch( const std::exception &err ) {
        debugmsg( "%s", err.what() );
        exit_handler(-999);
    }

    // Now we do the actual game.

    g->init_ui();

    curs_set(0); // Invisible cursor here, because MAPBUFFER.load() is crash-prone

#if (!(defined _WIN32 || defined WINDOWS))
    struct sigaction sigIntHandler;
    sigIntHandler.sa_handler = exit_handler;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGINT, &sigIntHandler, NULL);
#endif

#ifdef LOCALIZE
    std::string lang = "";
#if (defined _WIN32 || defined WINDOWS)
    lang = getLangFromLCID( GetUserDefaultLCID() );
#else
    const char *v = setlocale( LC_ALL, NULL );
    if( v != NULL ) {
        lang = v;

        if( lang == "C" ) {
            lang = "en";
        }
    }
#endif
    if( get_option<std::string>( "USE_LANG" ).empty() && ( lang.empty() || !isValidLanguage( lang ) ) ) {
        select_language();
        set_language();
    }
#endif

    while( true ) {
        if( !world.empty() ) {
            if( !g->load( world ) ) {
                break;
            }
            world.clear(); // ensure quit returns to opening screen

        } else {
            main_menu menu;
            if( !menu.opening_screen() ) {
                break;
            }
        }

        while( !g->do_turn() );
    };


    exit_handler(-999);
    return 0;
}
Ejemplo n.º 9
0
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int argc = __argc;
    char **argv = __argv;
#else
int main(int argc, char *argv[])
{
#endif
    int seed = time(NULL);
    bool verifyexit = false;
    bool check_all_mods = false;

    // Set default file paths
#ifdef PREFIX
#define Q(STR) #STR
#define QUOTE(STR) Q(STR)
    init_base_path(std::string(QUOTE(PREFIX)));
#else
    PATH_INFO::init_base_path("");
#endif

#ifdef USE_HOME_DIR
    PATH_INFO::init_user_dir();
#else
    PATH_INFO::init_user_dir("./");
#endif
    PATH_INFO::set_standart_filenames();

    MAP_SHARING::setDefaults();

    // Process CLI arguments
    int saved_argc = --argc; // skip program name
    char **saved_argv = ++argv;

    while (argc) {
        if(std::string(argv[0]) == "--seed") {
            argc--;
            argv++;
            if(argc) {
                seed = djb2_hash((unsigned char *)argv[0]);
                argc--;
                argv++;
            }
        } else if(std::string(argv[0]) == "--jsonverify") {
            argc--;
            argv++;
            verifyexit = true;
        } else if(std::string(argv[0]) == "--check-mods") {
            argc--;
            argv++;
            check_all_mods = true;
        } else if(std::string(argv[0]) == "--basepath") {
            argc--;
            argv++;
            if(argc) {
                PATH_INFO::init_base_path(std::string(argv[0]));
                PATH_INFO::set_standart_filenames();
                argc--;
                argv++;
            }
        } else if(std::string(argv[0]) == "--userdir") {
            argc--;
            argv++;
            if (argc) {
                PATH_INFO::init_user_dir( argv[0] );
                PATH_INFO::set_standart_filenames();
                argc--;
                argv++;
            }
        } else if(std::string(argv[0]) == "--username") {
            argc--;
            argv++;
            if (argc) {
                MAP_SHARING::setUsername(std::string(argv[0]));
                argc--;
                argv++;
            }
        } else if(std::string(argv[0]) == "--addadmin") {
            argc--;
            argv++;
            if (argc) {
                MAP_SHARING::addAdmin(std::string(argv[0]));
                argc--;
                argv++;
            }
        } else if(std::string(argv[0]) == "--adddebugger") {
            argc--;
            argv++;
            if (argc) {
                MAP_SHARING::addDebugger(std::string(argv[0]));
                argc--;
                argv++;
            }
        } else if(std::string(argv[0]) == "--shared") {
            argc--;
            argv++;
            MAP_SHARING::setSharing(true);
            MAP_SHARING::setCompetitive(true);
            MAP_SHARING::setWorldmenu(false);
        } else if(std::string(argv[0]) == "--competitive") {
            argc--;
            argv++;
            MAP_SHARING::setCompetitive(true);
        } else { // Skipping other options.
            argc--;
            argv++;
        }
    }
    while (saved_argc) {
        if(std::string(saved_argv[0]) == "--worldmenu") {
            saved_argc--;
            saved_argv++;
            MAP_SHARING::setWorldmenu(true);
        } else if(std::string(saved_argv[0]) == "--datadir") {
            saved_argc--;
            saved_argv++;
            if(saved_argc) {
                PATH_INFO::update_pathname("datadir", std::string(saved_argv[0]));
                PATH_INFO::update_datadir();
                saved_argc--;
                saved_argv++;
            }
        } else if(std::string(saved_argv[0]) == "--savedir") {
            saved_argc--;
            saved_argv++;
            if(saved_argc) {
                PATH_INFO::update_pathname("savedir", std::string(saved_argv[0]));
                saved_argc--;
                saved_argv++;
            }
        } else if(std::string(saved_argv[0]) == "--configdir") {
            saved_argc--;
            saved_argv++;
            if(saved_argc) {
                PATH_INFO::update_pathname("config_dir", std::string(saved_argv[0]));
                PATH_INFO::update_config_dir();
                saved_argc--;
                saved_argv++;
            }
        } else if(std::string(saved_argv[0]) == "--optionfile") {
            saved_argc--;
            saved_argv++;
            if(saved_argc) {
                PATH_INFO::update_pathname("options", std::string(saved_argv[0]));
                saved_argc--;
                saved_argv++;
            }
        } else if(std::string(saved_argv[0]) == "--keymapfile") {
            saved_argc--;
            saved_argv++;
            if(saved_argc) {
                PATH_INFO::update_pathname("keymap", std::string(saved_argv[0]));
                saved_argc--;
                saved_argv++;
            }
        } else if(std::string(saved_argv[0]) == "--autopickupfile") {
            saved_argc--;
            saved_argv++;
            if(saved_argc) {
                PATH_INFO::update_pathname("autopickup", std::string(saved_argv[0]));
                saved_argc--;
                saved_argv++;
            }
        } else if(std::string(saved_argv[0]) == "--motdfile") {
            saved_argc--;
            saved_argv++;
            if(saved_argc) {
                PATH_INFO::update_pathname("motd", std::string(saved_argv[0]));
                saved_argc--;
                saved_argv++;
            }
        } else { // ignore unknown args.
            saved_argc--;
            saved_argv++;
        }
    }

    // setup debug loggind
#ifdef ENABLE_LOGGING
    setupDebug();
#endif
    // set locale to system default
    setlocale(LC_ALL, "");
#ifdef LOCALIZE
    const char *locale_dir;
#ifdef __linux__
    if (!FILENAMES["base_path"].empty()) {
        locale_dir = std::string(FILENAMES["base_path"] + "share/locale").c_str();
    } else {
        locale_dir = "lang/mo";
    }
#else
    locale_dir = "lang/mo";
#endif // __linux__

    bindtextdomain("cataclysm-dda", locale_dir);
    bind_textdomain_codeset("cataclysm-dda", "UTF-8");
    textdomain("cataclysm-dda");
#endif // LOCALIZE

    // ncurses stuff
    initOptions();
    load_options(); // For getting size options
#ifdef LOCALIZE
    setlocale(LC_ALL, OPTIONS["USE_LANG"].getValue().c_str());
#endif // LOCALIZE
    if (initscr() == NULL) { // Initialize ncurses
        DebugLog() << "initscr failed!\n";
        return 1;
    }
    init_interface();
    noecho();  // Don't echo keypresses
    cbreak();  // C-style breaks (e.g. ^C to SIGINT)
    keypad(stdscr, true); // Numpad is numbers
#if !(defined TILES || defined _WIN32 || defined WINDOWS)
    // For tiles or windows, this is handled already in initscr().
    init_colors();
#endif
    // curs_set(0); // Invisible cursor
    set_escdelay(10); // Make escape actually responsive

    std::srand(seed);

    g = new game;
    // First load and initialize everything that does not
    // depend on the mods.
    try {
        if (!assure_dir_exist(FILENAMES["user_dir"].c_str())) {
            debugmsg("Can't open or create %s. Check permissions.",
                     FILENAMES["user_dir"].c_str());
            exit_handler(-999);
        }
        g->load_static_data();
        if (verifyexit) {
            if(g->game_error()) {
                exit_handler(-999);
            }
            exit_handler(0);
        }
        if (check_all_mods) {
            // Here we load all the mods and check their
            // consistency (both is done in check_all_mod_data).
            g->init_ui();
            popup_nowait("checking all mods");
            g->check_all_mod_data();
            if(g->game_error()) {
                exit_handler(-999);
            }
            // At this stage, the mods (and core game data)
            // are find and we could start playing, but this
            // is only for verifying that stage, so we exit.
            exit_handler(0);
        }
    } catch(std::string &error_message) {
        if(!error_message.empty()) {
            debugmsg("%s", error_message.c_str());
        }
        exit_handler(-999);
    }

    // Now we do the actuall game

    g->init_ui();
    if(g->game_error()) {
        exit_handler(-999);
    }

    curs_set(0); // Invisible cursor here, because MAPBUFFER.load() is crash-prone

#if (!(defined _WIN32 || defined WINDOWS))
    struct sigaction sigIntHandler;
    sigIntHandler.sa_handler = exit_handler;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGINT, &sigIntHandler, NULL);
#endif

    bool quit_game = false;
    do {
        if(!g->opening_screen()) {
            quit_game = true;
        }
        while (!quit_game && !g->do_turn()) ;
        if (g->game_quit() || g->game_error()) {
            quit_game = true;
        }
    } while (!quit_game);


    exit_handler(-999);

    return 0;
}
Ejemplo n.º 10
0
bool game::opening_screen()
{
    // Play title music, whoo!
    play_music( "title" );

    world_generator->set_active_world( NULL );
    // This actually _loads_ what worlds exist.
    world_generator->get_all_worlds();

    WINDOW *w_background = newwin( TERMY, TERMX, 0, 0 );
    WINDOW_PTR w_backgroundptr( w_background );
    werase( w_background );
    wrefresh( w_background );

    // main window should also expand to use available display space.
    // expanding to evenly use up half of extra space, for now.
    int extra_w = ( ( TERMX - FULL_SCREEN_WIDTH ) / 2 ) - 1;
    int extra_h = ( ( TERMY - FULL_SCREEN_HEIGHT ) / 2 ) - 1;
    extra_w = ( extra_w > 0 ? extra_w : 0 );
    extra_h = ( extra_h > 0 ? extra_h : 0 );
    const int total_w = FULL_SCREEN_WIDTH + extra_w;
    const int total_h = FULL_SCREEN_HEIGHT + extra_h;

    // position of window within main display
    const int x0 = ( TERMX - total_w ) / 2;
    const int y0 = ( TERMY - total_h ) / 2;

    WINDOW *w_open = newwin( total_h, total_w, y0, x0 );
    WINDOW_PTR w_openptr( w_open );

    const int iMenuOffsetX = 0;
    int iMenuOffsetY = total_h - 3;
    // note: if iMenuOffset is changed,
    // please update MOTD and credits to indicate how long they can be.

    // fill menu with translated menu items
    vMenuItems.clear();
    vMenuItems.push_back( pgettext( "Main Menu", "<M|m>OTD" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<N|n>ew Game" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "Lo<a|A>d" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<W|w>orld" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<S|s>pecial" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<O|o>ptions" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "H<e|E|?>lp" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<C|c>redits" ) );
    vMenuItems.push_back( pgettext( "Main Menu", "<Q|q>uit" ) );

    // determine hotkeys from (possibly translated) menu item text
    vMenuHotkeys.clear();
    for( auto item : vMenuItems ) {
        vMenuHotkeys.push_back( get_hotkeys( item ) );
    }

    std::vector<std::string> vSubItems;
    vSubItems.push_back( pgettext( "Main Menu|New Game", "<C|c>ustom Character" ) );
    vSubItems.push_back( pgettext( "Main Menu|New Game", "<P|p>reset Character" ) );
    vSubItems.push_back( pgettext( "Main Menu|New Game", "<R|r>andom Character" ) );
    if( !MAP_SHARING::isSharing() ) { // "Play Now" function doesn't play well together with shared maps
        vSubItems.push_back( pgettext( "Main Menu|New Game", "Play <N|n>ow!" ) );
    }
    std::vector<std::vector<std::string>> vNewGameHotkeys;
    for( auto item : vSubItems ) {
        vNewGameHotkeys.push_back( get_hotkeys( item ) );
    }

    std::vector<std::string> vWorldSubItems;
    vWorldSubItems.push_back( pgettext( "Main Menu|World", "<C|c>reate World" ) );
    vWorldSubItems.push_back( pgettext( "Main Menu|World", "<D|d>elete World" ) );
    vWorldSubItems.push_back( pgettext( "Main Menu|World", "<R|r>eset World" ) );
    std::vector<std::vector<std::string>> vWorldHotkeys;
    for( auto item : vWorldSubItems ) {
        vWorldHotkeys.push_back( get_hotkeys( item ) );
    }

    mmenu_refresh_title();
    print_menu( w_open, 0, iMenuOffsetX, iMenuOffsetY );

    std::vector<std::string> savegames, templates;
    dirent *dp;
    DIR *dir;

    if( !assure_dir_exist( FILENAMES["config_dir"] ) ) {
        popup( _( "Unable to make config directory. Check permissions." ) );
        return false;
    }

    if( !assure_dir_exist( FILENAMES["savedir"] ) ) {
        popup( _( "Unable to make save directory. Check permissions." ) );
        return false;
    }

    if( !assure_dir_exist( FILENAMES["templatedir"] ) ) {
        popup( _( "Unable to make templates directory. Check permissions." ) );
        return false;
    }
    dir = opendir( FILENAMES["templatedir"].c_str() );
    while( ( dp = readdir( dir ) ) ) {
        std::string tmp = dp->d_name;
        if( tmp.find( ".template" ) != std::string::npos ) {
            templates.push_back( tmp.substr( 0, tmp.find( ".template" ) ) );
        }
    }
    closedir( dir );

    int sel1 = 1, sel2 = 1, sel3 = 1, layer = 1;
    input_context ctxt( "MAIN_MENU" );
    ctxt.register_cardinal();
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "DELETE_TEMPLATE" );
    // for the menu shortcuts
    ctxt.register_action( "ANY_INPUT" );
    bool start = false;

    // Load MOTD and Credits, load it once as it shouldn't change for the duration of the application being open
    mmenu_refresh_motd();
    mmenu_refresh_credits();

    u = player();

    while( !start ) {
        print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY, ( sel1 == 0 || sel1 == 7 ) ? false : true );

        if( layer == 1 ) {
            if( sel1 == 0 ) { // Print the MOTD.
                const int motdy = ( iMenuOffsetY - mmenu_motd.size() ) * 2 / 3;
                const int motdx = 8 + extra_w / 2;
                for( size_t i = 0; i < mmenu_motd.size(); i++ ) {
                    mvwprintz( w_open, motdy + i, motdx, c_ltred, mmenu_motd[i].c_str() );
                }

                wrefresh( w_open );
                refresh();
            } else if( sel1 == 7 ) { // Print the Credits.
                const int credy = ( iMenuOffsetY - mmenu_credits.size() ) * 2 / 3;
                const int credx = 8 + extra_w / 2;
                for( size_t i = 0; i < mmenu_credits.size(); i++ ) {
                    mvwprintz( w_open, credy + i, credx, c_ltred, mmenu_credits[i].c_str() );
                }

                wrefresh( w_open );
                refresh();
            }

            std::string action = ctxt.handle_input();
            std::string sInput = ctxt.get_raw_input().text;
            // check automatic menu shortcuts
            for( size_t i = 0; i < vMenuHotkeys.size(); ++i ) {
                for( auto hotkey : vMenuHotkeys[i] ) {
                    if( sInput == hotkey ) {
                        sel1 = i;
                        action = "CONFIRM";
                    }
                }
            }
            // also check special keys
            if( action == "QUIT" ) {
                // Quit
                sel1 = 8;
                action = "CONFIRM";
            } else if( action == "LEFT" ) {
                if( sel1 > 0 ) {
                    sel1--;
                } else {
                    sel1 = 8;
                }
                sfx::play_variant_sound( "menu_move", "default", 100 );
            } else if( action == "RIGHT" ) {
                if( sel1 < 8 ) {
                    sel1++;
                } else {
                    sel1 = 0;
                }
                sfx::play_variant_sound( "menu_move", "default", 100 );
            }
            if( ( action == "UP" || action == "CONFIRM" ) && sel1 > 0 && sel1 != 7 ) {
                if( sel1 == 5 ) {
                    get_options().show();
                } else if( sel1 == 6 ) {
                    display_help();
                } else if( sel1 == 8 ) {
                    uquit = QUIT_MENU;
                    return false;
                } else {
                    sel2 = 0;
                    layer = 2;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY, ( sel1 == 0 || sel1 == 7 ) ? false : true );
                }
            }
        } else if( layer == 2 ) {
            if( sel1 == 1 ) { // New Character
                if( MAP_SHARING::isSharing() &&
                    world_generator->all_worlds.empty() ) { //don't show anything when there are no worlds (will not work if there are special maps)
                    layer = 1;
                    sel1 = 1;
                    continue;
                }

                print_menu_items( w_open, vSubItems, sel2, iMenuOffsetY - 2, iMenuOffsetX );
                wrefresh( w_open );
                refresh();

                std::string action = ctxt.handle_input();
                std::string sInput = ctxt.get_raw_input().text;
                for( size_t i = 0; i < vNewGameHotkeys.size(); ++i ) {
                    for( auto hotkey : vNewGameHotkeys[i] ) {
                        if( sInput == hotkey ) {
                            sel2 = i;
                            action = "CONFIRM";
                        }
                    }
                }
                if( action == "LEFT" ) {
                    sel2--;
                    if( sel2 < 0 ) {
                        sel2 = vSubItems.size() - 1;
                    }
                } else if( action == "RIGHT" ) {
                    sel2++;
                    if( sel2 >= ( int )vSubItems.size() ) {
                        sel2 = 0;
                    }
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                    sel1 = 1;
                }
                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 == 0 || sel2 == 2 || sel2 == 3 ) {
                        // First load the mods, this is done by
                        // loading the world.
                        // Pick a world, suppressing prompts if it's "play now" mode.
                        WORLDPTR world = world_generator->pick_world( sel2 != 3 );
                        if( world == NULL ) {
                            continue;
                        }
                        world_generator->set_active_world( world );
                        setup();
                        if( !u.create( sel2 == 0 ? PLTYPE_CUSTOM : ( sel2 == 2 ? PLTYPE_RANDOM : PLTYPE_NOW ) ) ) {
                            u = player();
                            continue;
                        }

                        werase( w_background );
                        wrefresh( w_background );

                        if( !start_game( world->world_name ) ) {
                            u = player();
                            continue;
                        }
                        start = true;
                    } else if( sel2 == 1 ) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if( sel1 == 2 ) { // Load Character
                if( world_generator->all_worldnames.empty() ) {
                    mvwprintz( w_open, iMenuOffsetY - 2, 15 + iMenuOffsetX + extra_w / 2,
                               c_red, _( "No Worlds found!" ) );
                } else {
                    for( int i = 0; i < ( int )world_generator->all_worldnames.size(); ++i ) {
                        int line = iMenuOffsetY - 2 - i;
                        std::string world_name = world_generator->all_worldnames[i];
                        int savegames_count = world_generator->all_worlds[world_name]->world_saves.size();
                        nc_color color1, color2;
                        if( world_name == "TUTORIAL" || world_name == "DEFENSE" ) {
                            color1 = c_ltcyan;
                            color2 = h_ltcyan;
                        } else {
                            if( world_generator->world_need_lua_build( world_name ) ) {
                                color1 = c_dkgray;
                                color2 = h_dkgray;
                            } else {
                                color1 = c_white;
                                color2 = h_white;
                            }
                        }
                        mvwprintz( w_open, line, 15 + iMenuOffsetX + extra_w / 2,
                                   ( sel2 == i ? color2 : color1 ), "%s (%d)",
                                   world_name.c_str(), savegames_count );
                    }
                }
                wrefresh( w_open );
                refresh();
                const std::string action = ctxt.handle_input();
                if( world_generator->all_worldnames.empty() && ( action == "DOWN" || action == "CONFIRM" ) ) {
                    layer = 1;
                } else if( action == "DOWN" ) {
                    if( sel2 > 0 ) {
                        sel2--;
                    } else {
                        sel2 = world_generator->all_worldnames.size() - 1;
                    }
                } else if( action == "UP" ) {
                    if( sel2 < ( int )world_generator->all_worldnames.size() - 1 ) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if( action == "LEFT" || action == "QUIT" ) {
                    layer = 1;
                } else if( action == "RIGHT" || action == "CONFIRM" ) {
                    if( sel2 >= 0 && sel2 < ( int )world_generator->all_worldnames.size() ) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if( sel1 == 3 ) { // World Menu
                // Show options for Create, Destroy, Reset worlds.
                // Create world goes directly to Make World screen.
                // Reset and Destroy ask for world to modify.
                // Reset empties world of everything but options, then makes new world within it.
                // Destroy asks for confirmation, then destroys everything in world and then removes world folder.

                // only show reset / destroy world if there is at least one valid world existing!

                if( MAP_SHARING::isSharing() && !MAP_SHARING::isWorldmenu() && !MAP_SHARING::isAdmin() ) {
                    layer = 1;
                    popup( _( "Only the admin can change worlds." ) );
                    continue;
                }

                int world_subs_to_display = ( !world_generator->all_worldnames.empty() ) ? vWorldSubItems.size() :
                                            1;
                std::vector<std::string> world_subs;
                int xoffset = 25 + iMenuOffsetX + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for( int i = 0; i < world_subs_to_display; ++i ) {
                    world_subs.push_back( vWorldSubItems[i] );
                    xlen += vWorldSubItems[i].size() + 2; // Open and close brackets added
                }
                xlen += world_subs.size() - 1;
                if( world_subs.size() > 1 ) {
                    xoffset -= 6;
                }
                print_menu_items( w_open, world_subs, sel2, yoffset, xoffset - ( xlen / 4 ) );
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                std::string sInput = ctxt.get_raw_input().text;
                for( int i = 0; i < world_subs_to_display; ++i ) {
                    for( auto hotkey : vWorldHotkeys[i] ) {
                        if( sInput == hotkey ) {
                            sel2 = i;
                            action = "CONFIRM";
                        }
                    }
                }

                if( action == "LEFT" ) {
                    if( sel2 > 0 ) {
                        --sel2;
                    } else {
                        sel2 = world_subs_to_display - 1;
                    }
                } else if( action == "RIGHT" ) {
                    if( sel2 < world_subs_to_display - 1 ) {
                        ++sel2;
                    } else {
                        sel2 = 0;
                    }
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                }

                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 == 0 ) { // Create world
                        // Open up world creation screen!
                        if( world_generator->make_new_world() ) {
                            return opening_screen();
                        } else {
                            layer = 1;
                        }
                    } else if( sel2 == 1 || sel2 == 2 ) { // Delete World | Reset World
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if( sel1 == 4 ) { // Special game
                if( MAP_SHARING::isSharing() ) { // Thee can't save special games, therefore thee can't share them
                    layer = 1;
                    popup( _( "Special games don't work with shared maps." ) );
                    continue;
                }

                std::vector<std::string> special_names;
                int xoffset = 32 + iMenuOffsetX  + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for( int i = 1; i < NUM_SPECIAL_GAMES; i++ ) {
                    std::string spec_name = special_game_name( special_game_id( i ) );
                    special_names.push_back( spec_name );
                    xlen += spec_name.size() + 2;
                }
                xlen += special_names.size() - 1;
                print_menu_items( w_open, special_names, sel2, yoffset, xoffset - ( xlen / 4 ) );

                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                if( action == "LEFT" ) {
                    if( sel2 > 0 ) {
                        sel2--;
                    } else {
                        sel2 = NUM_SPECIAL_GAMES - 2;
                    }
                } else if( action == "RIGHT" ) {
                    if( sel2 < NUM_SPECIAL_GAMES - 2 ) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                }
                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 >= 0 && sel2 < NUM_SPECIAL_GAMES - 1 ) {
                        gamemode = get_special_game( special_game_id( sel2 + 1 ) );
                        // check world
                        WORLDPTR world = world_generator->make_new_world( special_game_id( sel2 + 1 ) );
                        if( world == NULL ) {
                            continue;
                        }
                        world_generator->set_active_world( world );
                        setup();
                        if( !gamemode->init() ) {
                            gamemode.reset();
                            u = player();
                            continue;
                        }
                        start = true;
                    }
                }
            }
        } else if( layer == 3 ) {
            bool available = false;

            if( sel1 == 2 ) { // Load Game
                savegames = world_generator->all_worlds[world_generator->all_worldnames[sel2]]->world_saves;
                std::string wn = world_generator->all_worldnames[sel2];

                //hide savegames if lua is not available for a lua-built world
                if( ( wn != "TUTORIAL" && wn != "DEFENSE" ) && world_generator->world_need_lua_build( wn ) ) {
                    savegames.clear();
                    mvwprintz( w_open, iMenuOffsetY - 2, 15 + iMenuOffsetX + extra_w / 2,
                               c_red, _( "This world requires the game to be compiled with Lua." ) );
                } else if( savegames.empty() ) {
                    mvwprintz( w_open, iMenuOffsetY - 2, 19 + 19 + iMenuOffsetX + extra_w / 2,
                               c_red, _( "No save games found!" ) );
                } else {
                    for( std::vector<std::string>::iterator it = savegames.begin();
                         it != savegames.end(); ) {
                        std::string savename = base64_decode( *it );
                        if( MAP_SHARING::isSharing() && savename != MAP_SHARING::getUsername() ) {
                            it = savegames.erase( it );
                        } else {
                            // calculates the index from distance between it and savegames.begin()
                            int i = it - savegames.begin();
                            available = true;
                            int line = iMenuOffsetY - 2 - i;
                            mvwprintz( w_open, line, 19 + 19 + iMenuOffsetX + extra_w / 2,
                                       ( sel3 == i ? h_white : c_white ),
                                       base64_decode( *it ).c_str() );
                            ++it;
                        }
                    }
                    if( !available ) {
                        mvwprintz( w_open, iMenuOffsetY - 2, 19 + 19 + iMenuOffsetX + extra_w / 2,
                                   c_red, _( "No save games found!" ) );
                    }
                }
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                if( savegames.empty() && ( action == "DOWN" || action == "CONFIRM" ) ) {
                    layer = 2;
                } else if( action == "DOWN" ) {
                    if( sel3 > 0 ) {
                        sel3--;
                    } else {
                        sel3 = savegames.size() - 1;
                    }
                } else if( action == "UP" ) {
                    if( sel3 < ( int )savegames.size() - 1 ) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if( action == "LEFT" || action == "QUIT" ) {
                    layer = 2;
                    sel3 = 0;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                }
                if( action == "RIGHT" || action == "CONFIRM" ) {
                    if( sel3 >= 0 && sel3 < ( int )savegames.size() ) {
                        werase( w_background );
                        wrefresh( w_background );
                        WORLDPTR world = world_generator->all_worlds[world_generator->all_worldnames[sel2]];
                        world_generator->set_active_world( world );
                        setup();

                        load( world->world_name, savegames[sel3] );
                        start = true;
                    }
                }
            } else if( sel1 == 3 ) { // Show world names
                int i = 0;
                for( std::vector<std::string>::iterator it = world_generator->all_worldnames.begin();
                     it != world_generator->all_worldnames.end(); ++it ) {
                    int savegames_count = world_generator->all_worlds[*it]->world_saves.size();
                    int line = iMenuOffsetY - 4 - i;
                    nc_color color1, color2;
                    if( *it == "TUTORIAL" || *it == "DEFENSE" ) {
                        color1 = c_ltcyan;
                        color2 = h_ltcyan;
                    } else {
                        color1 = c_white;
                        color2 = h_white;
                    }
                    mvwprintz( w_open, line, 26 + iMenuOffsetX + extra_w / 2,
                               ( sel3 == i ? color2 : color1 ), "%s (%d)", ( *it ).c_str(), savegames_count );
                    ++i;
                }
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();

                if( action == "DOWN" ) {
                    if( sel3 > 0 ) {
                        --sel3;
                    } else {
                        sel3 = world_generator->all_worldnames.size() - 1;
                    }
                } else if( action == "UP" ) {
                    if( sel3 < ( int )world_generator->all_worldnames.size() - 1 ) {
                        ++sel3;
                    } else {
                        sel3 = 0;
                    }
                } else if( action == "LEFT" || action == "QUIT" ) {
                    layer = 2;

                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                }
                if( action == "RIGHT" || action == "CONFIRM" ) {
                    if( sel3 >= 0 && sel3 < ( int )world_generator->all_worldnames.size() ) {
                        bool query_yes = false;
                        bool do_delete = false;
                        if( sel2 == 1 ) { // Delete World
                            if( query_yn( _( "Delete the world and all saves?" ) ) ) {
                                query_yes = true;
                                do_delete = true;
                            }
                        } else if( sel2 == 2 ) { // Reset World
                            if( query_yn( _( "Remove all saves and regenerate world?" ) ) ) {
                                query_yes = true;
                                do_delete = false;
                            }
                        }

                        if( query_yes ) {
                            delete_world( world_generator->all_worldnames[sel3], do_delete );

                            savegames.clear();
                            MAPBUFFER.reset();
                            overmap_buffer.clear();

                            layer = 2;

                            if( do_delete ) {
                                // delete world and all contents
                                world_generator->remove_world( world_generator->all_worldnames[sel3] );
                            } else {
                                // clear out everything but worldoptions from this world
                                world_generator->all_worlds[world_generator->all_worldnames[sel3]]->world_saves.clear();
                            }
                            if( world_generator->all_worldnames.empty() ) {
                                sel2 = 0; // reset to create world selection
                            }
                        } else {
                            // hacky resolution to the issue of persisting world names on the screen
                            return opening_screen();
                        }
                    }
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                }
            } else { // Character Templates
                if( templates.empty() ) {
                    mvwprintz( w_open, iMenuOffsetY - 4, iMenuOffsetX + 20 + extra_w / 2,
                               c_red, _( "No templates found!" ) );
                } else {
                    mvwprintz( w_open, iMenuOffsetY - 2, iMenuOffsetX + 20 + extra_w / 2,
                               c_white, _( "Press 'd' to delete a preset." ) );
                    for( int i = 0; i < ( int )templates.size(); i++ ) {
                        int line = iMenuOffsetY - 4 - i;
                        mvwprintz( w_open, line, 20 + iMenuOffsetX + extra_w / 2,
                                   ( sel3 == i ? h_white : c_white ), templates[i].c_str() );
                    }
                }
                wrefresh( w_open );
                refresh();
                std::string action = ctxt.handle_input();
                if( action == "DOWN" ) {
                    if( sel3 > 0 ) {
                        sel3--;
                    } else {
                        sel3 = templates.size() - 1;
                    }
                } else if( templates.empty() && ( action == "UP" || action == "CONFIRM" ) ) {
                    sel1 = 1;
                    layer = 2;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                } else if( action == "UP" ) {
                    if( sel3 < ( int )templates.size() - 1 ) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if( action == "LEFT"  || action == "QUIT" || templates.empty() ) {
                    sel1 = 1;
                    layer = 2;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY );
                } else if( !templates.empty() && action == "DELETE_TEMPLATE" ) {
                    if( query_yn( _( "Are you sure you want to delete %s?" ),
                                  templates[sel3].c_str() ) ) {
                        const auto path = FILENAMES["templatedir"] + templates[sel3] + ".template";
                        if( std::remove( path.c_str() ) != 0 ) {
                            popup( _( "Sorry, something went wrong." ) );
                        } else {
                            templates.erase( templates.begin() + sel3 );
                            if( ( size_t )sel3 > templates.size() - 1 ) {
                                sel3--;
                            }
                        }
                    }
                } else if( action == "RIGHT" || action == "CONFIRM" ) {
                    WORLDPTR world = world_generator->pick_world();
                    if( world == NULL ) {
                        u = player();
                        continue;
                    }
                    world_generator->set_active_world( world );
                    setup();
                    if( !u.create( PLTYPE_TEMPLATE, templates[sel3] ) ) {
                        u = player();
                        continue;
                    }
                    werase( w_background );
                    wrefresh( w_background );
                    if( !start_game( world_generator->active_world->world_name ) ) {
                        u = player();
                        continue;
                    }
                    start = true;
                }
            }
        }
    }
    w_openptr.reset();
    w_backgroundptr.reset();
    if( start == false ) {
        uquit = QUIT_MENU;
    } else {
        refresh_all();
        draw();
    }
    return start;
}
Ejemplo n.º 11
0
bool main_menu::opening_screen()
{
    // Play title music, whoo!
    play_music( "title" );

    world_generator->set_active_world( NULL );
    world_generator->init();

    init_windows();
    init_strings();
    print_menu( w_open, 0, iMenuOffsetX, iMenuOffsetY );

    if( !assure_dir_exist( FILENAMES["config_dir"] ) ) {
        popup( _( "Unable to make config directory. Check permissions." ) );
        return false;
    }

    if( !assure_dir_exist( FILENAMES["savedir"] ) ) {
        popup( _( "Unable to make save directory. Check permissions." ) );
        return false;
    }

    if( !assure_dir_exist( FILENAMES["templatedir"] ) ) {
        popup( _( "Unable to make templates directory. Check permissions." ) );
        return false;
    }

    for( std::string path : get_files_from_path( ".template", FILENAMES["templatedir"], false,
            true ) ) {
        path = native_to_utf8( path );
        path.erase( path.find( ".template" ), std::string::npos );
        path.erase( 0, path.find_last_of( "\\//" ) + 1 );
        templates.push_back( path );
    }
    std::sort( templates.begin(), templates.end(), std::greater<std::string>() );

    ctxt.register_cardinal();
    ctxt.register_action( "QUIT" );
    ctxt.register_action( "CONFIRM" );
    ctxt.register_action( "DELETE_TEMPLATE" );
    // for the menu shortcuts
    ctxt.register_action( "ANY_INPUT" );
    bool start = false;

    g->u = player();

    // Make [Load Game] the default cursor position if there's game save available
    if( !world_generator->all_worldnames().empty() ) {
        sel1 = 2;
    }

    while( !start ) {
        print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY, ( sel1 != 0 ) );

        if( layer == 1 ) {
            if( sel1 == 0 ) { // Print the MOTD.
                const int motdy = ( iMenuOffsetY - mmenu_motd.size() ) * 2 / 3;
                const int motdx = 8 + extra_w / 2;
                for( size_t i = 0; i < mmenu_motd.size(); i++ ) {
                    mvwprintz( w_open, motdy + i, motdx, c_light_red, mmenu_motd[i].c_str() );
                }

                wrefresh( w_open );
                catacurses::refresh();
            }

            std::string action = handle_input_timeout( ctxt );

            std::string sInput = ctxt.get_raw_input().text;
            // check automatic menu shortcuts
            for( size_t i = 0; i < vMenuHotkeys.size(); ++i ) {
                for( auto hotkey : vMenuHotkeys[i] ) {
                    if( sInput == hotkey ) {
                        sel1 = i;
                        action = "CONFIRM";
                    }
                }
            }
            // also check special keys
            if( action == "QUIT" ) {
                if( query_yn( _( "Really quit?" ) ) ) {
                    sel1 = 8;
                    action = "CONFIRM";
                }
            } else if( action == "LEFT" ) {
                if( sel1 > 0 ) {
                    sel1--;
                } else {
                    sel1 = 8;
                }
                on_move();
            } else if( action == "RIGHT" ) {
                if( sel1 < 8 ) {
                    sel1++;
                } else {
                    sel1 = 0;
                }
                on_move();
            }
            if( ( action == "UP" || action == "CONFIRM" ) && sel1 > 0 ) {
                if( sel1 == 6 ) {
                    display_help();
                } else if( sel1 == 7 ) {
                    display_credits();
                } else if( sel1 == 8 ) {
                    return false;
                } else {
                    sel2 = 0;
                    layer = 2;
                    print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY, ( sel1 != 0 ) );

                    switch( sel1 ) {
                        case 1:
                            start = new_character_tab();
                            break;
                        case 2:
                            start = load_character_tab();
                            break;
                        case 3:
                            world_tab();
                            break;
                        default:
                            break;
                    }
                }
            }
        } else if( layer == 2 ) {
            if( sel1 == 4 ) { // Special game
                if( MAP_SHARING::isSharing() ) { // Thee can't save special games, therefore thee can't share them
                    layer = 1;
                    popup( _( "Special games don't work with shared maps." ) );
                    continue;
                }

                std::vector<std::string> special_names;
                int xoffset = 32 + iMenuOffsetX  + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for( int i = 1; i < NUM_SPECIAL_GAMES; i++ ) {
                    std::string spec_name = special_game_name( special_game_id( i ) );
                    special_names.push_back( spec_name );
                    xlen += spec_name.size() + 2;
                }
                xlen += special_names.size() - 1;
                print_menu_items( w_open, special_names, sel2, yoffset, xoffset - ( xlen / 4 ) );

                wrefresh( w_open );
                catacurses::refresh();
                std::string action = handle_input_timeout( ctxt );
                if( action == "LEFT" ) {
                    if( sel2 > 0 ) {
                        sel2--;
                    } else {
                        sel2 = NUM_SPECIAL_GAMES - 2;
                    }
                    on_move();
                } else if( action == "RIGHT" ) {
                    if( sel2 < NUM_SPECIAL_GAMES - 2 ) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                    on_move();
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                }
                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 >= 0 && sel2 < NUM_SPECIAL_GAMES - 1 ) {
                        g->gamemode = get_special_game( special_game_id( sel2 + 1 ) );
                        // check world
                        WORLDPTR world = world_generator->make_new_world( special_game_id( sel2 + 1 ) );
                        if( world == NULL ) {
                            continue;
                        }
                        world_generator->set_active_world( world );
                        try {
                            g->setup();
                        } catch( const std::exception &err ) {
                            debugmsg( "Error: %s", err.what() );
                            g->gamemode.reset();
                            g->u = player();
                            continue;
                        }
                        if( !g->gamemode->init() ) {
                            g->gamemode.reset();
                            g->u = player();
                            continue;
                        }
                        start = true;
                    }
                }
            } else if( sel1 == 5 ) {  // Settings Menu
                int settings_subs_to_display = vSettingsSubItems.size();
                std::vector<std::string> settings_subs;
                int xoffset = 46 + iMenuOffsetX + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for( int i = 0; i < settings_subs_to_display; ++i ) {
                    settings_subs.push_back( vSettingsSubItems[i] );
                    xlen += vSettingsSubItems[i].size() + 2; // Open and close brackets added
                }
                xlen += settings_subs.size() - 1;
                if( settings_subs.size() > 1 ) {
                    xoffset -= 6;
                }
                print_menu_items( w_open, settings_subs, sel2, yoffset, xoffset - ( xlen / 4 ) );
                wrefresh( w_open );
                catacurses::refresh();
                std::string action = handle_input_timeout( ctxt );
                std::string sInput = ctxt.get_raw_input().text;
                for( int i = 0; i < settings_subs_to_display; ++i ) {
                    for( auto hotkey : vSettingsHotkeys[i] ) {
                        if( sInput == hotkey ) {
                            sel2 = i;
                            action = "CONFIRM";
                        }
                    }
                }

                if( action == "LEFT" ) {
                    if( sel2 > 0 ) {
                        --sel2;
                    } else {
                        sel2 = settings_subs_to_display - 1;
                    }
                    on_move();
                } else if( action == "RIGHT" ) {
                    if( sel2 < settings_subs_to_display - 1 ) {
                        ++sel2;
                    } else {
                        sel2 = 0;
                    }
                    on_move();
                } else if( action == "DOWN" || action == "QUIT" ) {
                    layer = 1;
                }

                if( action == "UP" || action == "CONFIRM" ) {
                    if( sel2 == 0 ) {
                        get_options().show( true );
                        // The language may have changed- gracefully handle this.
                        init_strings();
                        print_menu( w_open, sel1, iMenuOffsetX, iMenuOffsetY, ( sel1 != 0 ) );
                    } else if( sel2 == 1 ) {
                        input_context ctxt_default = get_default_mode_input_context();
                        ctxt_default.display_menu();
                    } else if( sel2 == 2 ) {
                        get_auto_pickup().show();
                    } else if( sel2 == 3 ) {
                        get_safemode().show();
                    } else if( sel2 == 4 ) {
                        all_colors.show_gui();
                    }
                }
            }
        }
    }
    if( start ) {
        g->refresh_all();
        g->draw();
    }
    return start;
}
Ejemplo n.º 12
0
bool game::opening_screen()
{
    world_generator->set_active_world(NULL);
    // This actually _loads_ what worlds exist.
    world_generator->get_all_worlds();

    WINDOW *w_background = newwin(TERMY, TERMX, 0, 0);
    werase(w_background);
    wrefresh(w_background);

    // main window should also expand to use available display space.
    // expanding to evenly use up half of extra space, for now.
    int extra_w = ((TERMX - FULL_SCREEN_WIDTH) / 2) - 1;
    int extra_h = ((TERMY - FULL_SCREEN_HEIGHT) / 2) - 1;
    extra_w = (extra_w > 0 ? extra_w : 0);
    extra_h = (extra_h > 0 ? extra_h : 0);
    const int total_w = FULL_SCREEN_WIDTH + extra_w;
    const int total_h = FULL_SCREEN_HEIGHT + extra_h;

    // position of window within main display
    const int x0 = (TERMX - total_w) / 2;
    const int y0 = (TERMY - total_h) / 2;

    WINDOW *w_open = newwin(total_h, total_w, y0, x0);

    const int iMenuOffsetX = 2;
    int iMenuOffsetY = total_h - 3;

    std::vector<std::string> vSubItems;
    vSubItems.push_back(pgettext("Main Menu|New Game", "<C>ustom Character"));
    vSubItems.push_back(pgettext("Main Menu|New Game", "<P>reset Character"));
    vSubItems.push_back(pgettext("Main Menu|New Game", "<R>andom Character"));
    vSubItems.push_back(pgettext("Main Menu|New Game", "Play <N>ow!"));

    std::vector<std::string> vWorldSubItems;
    vWorldSubItems.push_back(pgettext("Main Menu|World", "<C>reate World"));
    vWorldSubItems.push_back(pgettext("Main Menu|World", "<D>elete World"));
    vWorldSubItems.push_back(pgettext("Main Menu|World", "<R>eset World"));

    print_menu(w_open, 0, iMenuOffsetX, iMenuOffsetY);

    std::vector<std::string> savegames, templates;
    dirent *dp;
    DIR *dir;

    if (!assure_dir_exist("save")) {
        popup(_("Unable to make save directory. Check permissions."));
        return false;
    }

    dir = opendir("data");
    while ((dp = readdir(dir))) {
        std::string tmp = dp->d_name;
        if (tmp.find(".template") != std::string::npos) {
            templates.push_back(tmp.substr(0, tmp.find(".template")));
        }
    }
    closedir(dir);

    int sel1 = 1, sel2 = 1, sel3 = 1, layer = 1;
    InputEvent input;
    int chInput;
    bool start = false;

    // Load MOTD and store it in a string
    // Only load it once, it shouldn't change for the duration of the application being open
    static std::vector<std::string> motd;
    if (motd.empty()) {
        std::ifstream motd_file;
        motd_file.open("data/motd");
        if (!motd_file.is_open()) {
            motd.push_back(_("No message today."));
        } else {
            while (!motd_file.eof()) {
                std::string tmp;
                getline(motd_file, tmp);
                if (!tmp.length() || tmp[0] != '#') {
                    motd.push_back(tmp);
                }
            }
        }
    }

    // Load Credits and store it in a string
    // Only load it once, it shouldn't change for the duration of the application being open
    static std::vector<std::string> credits;
    if (credits.empty()) {
        std::ifstream credits_file;
        credits_file.open("data/credits");
        if (!credits_file.is_open()) {
            credits.push_back(_("No message today."));
        } else {
            while (!credits_file.eof()) {
                std::string tmp;
                getline(credits_file, tmp);
                if (!tmp.length() || tmp[0] != '#') {
                    credits.push_back(tmp);
                }
            }
        }
    }

    u = player();

    while(!start) {
        print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY, (sel1 == 0 || sel1 == 7) ? false : true);

        if (layer == 1) {
            if (sel1 == 0) { // Print the MOTD.
                for (int i = 0; i < motd.size() && i < 16; i++) {
                    mvwprintz(w_open, i + 6, 8 + extra_w / 2, c_ltred, motd[i].c_str());
                }

                wrefresh(w_open);
                refresh();
            } else if (sel1 == 7) { // Print the Credits.
                for (int i = 0; i < credits.size() && i < 16; i++) {
                    mvwprintz(w_open, i + 6, 8 + extra_w / 2, c_ltred, credits[i].c_str());
                }

                wrefresh(w_open);
                refresh();
            }

            chInput = getch();

            if (chInput == 'm' || chInput == 'M') {
                // MOTD
                sel1 = 0;
                chInput = '\n';
            } else if (chInput == 'n' || chInput == 'N') {
                // New Game
                sel1 = 1;
                chInput = '\n';
            } else if (chInput == 'a' || chInput == 'A') {
                // Load Game
                sel1 = 2;
                chInput = '\n';
            } else if (chInput == 'w' || chInput == 'W') {
                // World
                sel1 = 3;
                chInput = '\n';
            } else if (chInput == 's' || chInput == 'S') {
                // Special Game
                sel1 = 4;
                chInput = '\n';
            } else if (chInput == 'o' || chInput == 'O') {
                // Options
                sel1 = 5;
                chInput = '\n';
            } else if (chInput == 'e' || chInput == 'E' || chInput == '?') {
                // Help
                sel1 = 6;
                chInput = '\n';
            } else if (chInput == 'c' || chInput == 'C') {
                // Credits
                sel1 = 7;
                chInput = '\n';
            } else if (chInput == 'q' || chInput == 'Q' || chInput == KEY_ESCAPE) {
                // Quit
                sel1 = 8;
                chInput = '\n';
            }

            if (chInput == KEY_LEFT || chInput == 'h') {
                if (sel1 > 0) {
                    sel1--;
                } else {
                    sel1 = 8;
                }
            } else if (chInput == KEY_RIGHT || chInput == 'l') {
                if (sel1 < 8) {
                    sel1++;
                } else {
                    sel1 = 0;
                }
            } else if ((chInput == KEY_UP || chInput == 'k' || chInput == '\n') && sel1 > 0 && sel1 != 7) {
                if (sel1 == 5) {
                    show_options();
                } else if (sel1 == 6) {
                    display_help();
                } else if (sel1 == 8) {
                    uquit = QUIT_MENU;
                    delwin(w_open);
                    delwin(w_background);
                    return false;
                } else {
                    sel2 = 0;
                    layer = 2;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY, (sel1 == 0 || sel1 == 7) ? false : true);
                }
            }
        } else if (layer == 2) {
            if (sel1 == 1) { // New Character
                print_menu_items(w_open, vSubItems, sel2, iMenuOffsetY - 2, iMenuOffsetX);
                wrefresh(w_open);
                refresh();
                chInput = getch();

                if (chInput == 'c' || chInput == 'C') {
                    sel2 = 0;
                    chInput = '\n'  ;
                } else if (chInput == 'p' || chInput == 'P') {
                    sel2 = 1;
                    chInput = '\n';
                } else if (chInput == 'r' || chInput == 'R') {
                    sel2 = 2;
                    chInput = '\n';
                } else if (chInput == 'n' || chInput == 'N') {
                    sel2 = 3;
                    chInput = '\n';
                }

                if (chInput == KEY_LEFT || chInput == 'h') {
                    sel2--;
                    if (sel2 < 0) {
                        sel2 = vSubItems.size() - 1;
                    }
                }
                if (chInput == KEY_RIGHT || chInput == 'l') {
                    sel2++;
                    if (sel2 >= vSubItems.size()) {
                        sel2 = 0;
                    }
                } else if (chInput == KEY_DOWN || chInput == 'j' || chInput == KEY_ESCAPE) {
                    layer = 1;
                    sel1 = 1;
                }
                if (chInput == KEY_UP || chInput == 'k' || chInput == '\n') {
                    if (sel2 == 0 || sel2 == 2 || sel2 == 3) {
                        // First load the mods, this is done by
                        // loading the world.
                        // Pick a world, supressing prompts if it's "play now" mode.
                        WORLDPTR world = world_generator->pick_world( sel2 != 3 );
                        if (world == NULL) {
                            continue;
                        }
                        world_generator->set_active_world(world);
                        setup();
                        if (!u.create((sel2 == 0) ? PLTYPE_CUSTOM :
                                                    ((sel2 == 2) ? PLTYPE_RANDOM : PLTYPE_NOW))) {
                            u = player();
                            continue;
                        }
                        werase(w_background);
                        wrefresh(w_background);

                        MAPBUFFER.load(world->world_name);
                        start_game(world->world_name);
                        start = true;
                    } else if (sel2 == 1) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if (sel1 == 2) { // Load Character
                if (world_generator->all_worldnames.empty()) {
                    mvwprintz(w_open, iMenuOffsetY - 2, 15 + iMenuOffsetX + extra_w / 2,
                              c_red, _("No Worlds found!"));
                } else {
                    for (int i = 0; i < world_generator->all_worldnames.size(); ++i) {
                      int line = iMenuOffsetY - 2 - i;
                      std::string world_name = world_generator->all_worldnames[i];
                      int savegames_count = world_generator->all_worlds[world_name]->world_saves.size();
                      mvwprintz(w_open, line, 15 + iMenuOffsetX + extra_w / 2,
                                (sel2 == i ? h_white : c_white), "%s (%d)", world_name.c_str(), savegames_count);
                    }
                }
                wrefresh(w_open);
                refresh();
                input = get_input();
                if (world_generator->all_worldnames.empty() && (input == DirectionS || input == Confirm)) {
                    layer = 1;
                } else if (input == DirectionS) {
                    if (sel2 > 0) {
                        sel2--;
                    } else {
                        sel2 = world_generator->all_worldnames.size() - 1;
                    }
                } else if (input == DirectionN) {
                    if (sel2 < world_generator->all_worldnames.size() - 1) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if (input == DirectionW || input == Cancel) {
                    layer = 1;
                }
                if (input == DirectionE || input == Confirm) {
                    if (sel2 >= 0 && sel2 < world_generator->all_worldnames.size()) {
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if (sel1 == 3) {  // World Menu
                // Show options for Create, Destroy, Reset worlds.
                // Create world goes directly to Make World screen.
                // Reset and Destroy ask for world to modify.
                // Reset empties world of everything but options, then makes new world within it.
                // Destroy asks for confirmation, then destroys everything in world and then removes world folder.

                // only show reset / destroy world if there is at least one valid world existing!

                int world_subs_to_display = (world_generator->all_worldnames.size() > 0)? vWorldSubItems.size(): 1;
                std::vector<std::string> world_subs;
                int xoffset = 25 + iMenuOffsetX + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for (int i = 0; i < world_subs_to_display; ++i) {
                    world_subs.push_back(vWorldSubItems[i]);
                    xlen += vWorldSubItems[i].size() + 2; // Open and close brackets added
                }
                xlen += world_subs.size() - 1;
                if (world_subs.size() > 1) {
                    xoffset -= 6;
                }
                print_menu_items(w_open, world_subs, sel2, yoffset, xoffset - (xlen / 4));
                wrefresh(w_open);
                refresh();
                chInput = getch();
                input = get_input(chInput);

                //shortcuts
                if (chInput == 'c' || chInput == 'C') {
                    sel2 = 0;
                    input = Confirm;
                } else if ((chInput == 'd' || chInput == 'D') && (world_subs_to_display > 1)) {
                    sel2 = 1;
                    input = Confirm;
                } else if ((chInput == 'r' || chInput == 'R') && (world_subs_to_display > 1)) {
                    sel2 = 2;
                    input = Confirm;
                }

                if (input == DirectionW) {
                    if (sel2 > 0) {
                        --sel2;
                    } else {
                        sel2 = world_subs_to_display - 1;
                    }
                } else if (input == DirectionE) {
                    if (sel2 < world_subs_to_display - 1) {
                        ++sel2;
                    } else {
                        sel2 = 0;
                    }
                } else if (input == DirectionS || input == Cancel) {
                    layer = 1;
                }

                if (input == DirectionN || input == Confirm) {
                    if (sel2 == 0) { // Create world
                        // Open up world creation screen!
                        if (world_generator->make_new_world()) {
                            return opening_screen();
                        } else {
                            layer = 1;
                        }
                    } else if (sel2 == 1 || sel2 == 2) { // Delete World | Reset World
                        layer = 3;
                        sel3 = 0;
                    }
                }
            } else if (sel1 == 4) { // Special game
                std::vector<std::string> special_names;
                int xoffset = 32 + iMenuOffsetX  + extra_w / 2;
                int yoffset = iMenuOffsetY - 2;
                int xlen = 0;
                for (int i = 1; i < NUM_SPECIAL_GAMES; i++) {
                    std::string spec_name = special_game_name(special_game_id(i));
                    special_names.push_back(spec_name);
                    xlen += spec_name.size() + 2;
                }
                xlen += special_names.size() - 1;
                print_menu_items(w_open, special_names, sel2, yoffset, xoffset - (xlen / 4));

                wrefresh(w_open);
                refresh();
                input = get_input();
                if (input == DirectionW) {
                    if (sel2 > 0) {
                        sel2--;
                    } else {
                        sel2 = NUM_SPECIAL_GAMES - 2;
                    }
                } else if (input == DirectionE) {
                    if (sel2 < NUM_SPECIAL_GAMES - 2) {
                        sel2++;
                    } else {
                        sel2 = 0;
                    }
                } else if (input == DirectionS || input == Cancel) {
                    layer = 1;
                }
                if (input == DirectionN || input == Confirm) {
                    if (sel2 >= 0 && sel2 < NUM_SPECIAL_GAMES - 1) {
                        delete gamemode;
                        gamemode = get_special_game( special_game_id(sel2 + 1) );
                        // check world
                        WORLDPTR world = world_generator->make_new_world(special_game_id(sel2 + 1));
                        if (world == NULL) {
                            continue;
                        }
                        world_generator->set_active_world(world);
                        setup();
                        if (!gamemode->init()) {
                            delete gamemode;
                            gamemode = NULL;
                            u = player();
                            continue;
                        }
                        start = true;
                    }
                }
            }
        } else if (layer == 3) {
            if (sel1 == 2) { // Load Game
                savegames = world_generator->all_worlds[world_generator->all_worldnames[sel2]]->world_saves;
                if (savegames.empty()) {
                    mvwprintz(w_open, iMenuOffsetY - 2, 19 + 19 + iMenuOffsetX + extra_w / 2,
                              c_red, _("No save games found!"));
                } else {
                    for (int i = 0; i < savegames.size(); i++) {
                        int line = iMenuOffsetY - 2 - i;
                        mvwprintz(w_open, line, 19 + 19 + iMenuOffsetX + extra_w / 2,
                                  (sel3 == i ? h_white : c_white),
                                  base64_decode(savegames[i]).c_str());
                    }
                }
                wrefresh(w_open);
                refresh();
                input = get_input();
                if (savegames.size() == 0 && (input == DirectionS || input == Confirm)) {
                    layer = 2;
                } else if (input == DirectionS) {
                    if (sel3 > 0) {
                        sel3--;
                    } else {
                        sel3 = savegames.size() - 1;
                    }
                } else if (input == DirectionN) {
                    if (sel3 < savegames.size() - 1) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if (input == DirectionW || input == Cancel) {
                    layer = 2;
                    sel3 = 0;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                }
                if (input == DirectionE || input == Confirm) {
                    if (sel3 >= 0 && sel3 < savegames.size()) {
                        werase(w_background);
                        wrefresh(w_background);
                        WORLDPTR world = world_generator->all_worlds[world_generator->all_worldnames[sel2]];
                        world_generator->set_active_world(world);
                        setup();
                        MAPBUFFER.load(world->world_name);

                        load(world->world_name, savegames[sel3]);
                        start = true;
                    }
                }
            } else if (sel1 == 3) { // Show world names
                int i = 0;
                for (std::vector<std::string>::iterator it = world_generator->all_worldnames.begin();
                     it != world_generator->all_worldnames.end(); ++it) {
                    int savegames_count = world_generator->all_worlds[*it]->world_saves.size();
                    int line = iMenuOffsetY - 4 - i;
                    mvwprintz(w_open, line, 26 + iMenuOffsetX + extra_w / 2,
                              (sel3 == i ? h_white : c_white), "%s (%d)", (*it).c_str(), savegames_count);
                    ++i;
                }
                wrefresh(w_open);
                refresh();
                input = get_input();

                if (input == DirectionS) {
                    if (sel3 > 0) {
                        --sel3;
                    } else {
                        sel3 = world_generator->all_worldnames.size() - 1;
                    }
                } else if (input == DirectionN) {
                    if (sel3 < world_generator->all_worldnames.size() - 1) {
                        ++sel3;
                    } else {
                        sel3 = 0;
                    }
                } else if (input == DirectionW || input == Cancel) {
                    layer = 2;

                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                }
                if (input == DirectionE || input == Confirm) {
                    if (sel3 >= 0 && sel3 < world_generator->all_worldnames.size()) {
                        bool query_yes = false;
                        bool do_delete = false;
                        if (sel2 == 1) { // Delete World
                            if (query_yn(_("Delete the world and all saves?"))) {
                                query_yes = true;
                                do_delete = true;
                            }
                        } else if (sel2 == 2) { // Reset World
                            if (query_yn(_("Remove all saves and regenerate world?"))) {
                                query_yes = true;
                                do_delete = false;
                            }
                        }

                        if (query_yes) {
                            delete_world(world_generator->all_worldnames[sel3], do_delete);

                            savegames.clear();
                            MAPBUFFER.reset();
                            MAPBUFFER.make_volatile();
                            overmap_buffer.clear();

                            layer = 2;

                            if (do_delete) {
                                // delete world and all contents
                                world_generator->remove_world(world_generator->all_worldnames[sel3]);
                            } else {
                                // clear out everything but worldoptions from this world
                                world_generator->all_worlds[world_generator->all_worldnames[sel3]]->world_saves.clear();
                            }
                            if (world_generator->all_worldnames.size() == 0) {
                                sel2 = 0; // reset to create world selection
                            }
                        } else {
                            // hacky resolution to the issue of persisting world names on the screen
                            return opening_screen();
                        }
                    }
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                }
            } else { // Character Templates
                if (templates.size() == 0) {
                    mvwprintz(w_open, iMenuOffsetY - 4, iMenuOffsetX + 20 + extra_w / 2,
                              c_red, _("No templates found!"));
                } else {
                    for (int i = 0; i < templates.size(); i++) {
                        int line = iMenuOffsetY - 4 - i;
                        mvwprintz(w_open, line, 20 + iMenuOffsetX + extra_w / 2,
                                  (sel3 == i ? h_white : c_white), templates[i].c_str());
                    }
                }
                wrefresh(w_open);
                refresh();
                input = get_input();
                if (input == DirectionS) {
                    if (sel3 > 0) {
                        sel3--;
                    } else {
                        sel3 = templates.size() - 1;
                    }
                } else if (templates.size() == 0 && (input == DirectionN || input == Confirm)) {
                    sel1 = 1;
                    layer = 2;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                } else if (input == DirectionN) {
                    if (sel3 < templates.size() - 1) {
                        sel3++;
                    } else {
                        sel3 = 0;
                    }
                } else if (input == DirectionW  || input == Cancel || templates.size() == 0) {
                    sel1 = 1;
                    layer = 2;
                    print_menu(w_open, sel1, iMenuOffsetX, iMenuOffsetY);
                } else if (input == DirectionE || input == Confirm) {
                    WORLDPTR world = world_generator->pick_world();
                    if (world == NULL) {
                        u = player();
                        continue;
                    }
                    world_generator->set_active_world(world);
                    setup();
                    if (!u.create(PLTYPE_TEMPLATE, templates[sel3])) {
                        u = player();
                        continue;
                    }
                    werase(w_background);
                    wrefresh(w_background);
                    MAPBUFFER.load(world_generator->active_world->world_name);
                    start_game(world_generator->active_world->world_name);
                    start = true;
                }
            }
        }
    }
    delwin(w_open);
    delwin(w_background);
    if (start == false) {
        uquit = QUIT_MENU;
    } else {
        refresh_all();
        draw();
    }
    return start;
}
Ejemplo n.º 13
0
int APIENTRY WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int argc = __argc;
    char **argv = __argv;
#else
int main(int argc, char *argv[])
{
#endif
    int seed = time(NULL);
    bool verifyexit = false;
    bool check_all_mods = false;

    // Set default file paths
#ifdef PREFIX
#define Q(STR) #STR
#define QUOTE(STR) Q(STR)
    PATH_INFO::init_base_path(std::string(QUOTE(PREFIX)));
#else
    PATH_INFO::init_base_path("");
#endif

#if (defined USE_HOME_DIR || defined USE_XDG_DIR)
    PATH_INFO::init_user_dir();
#else
    PATH_INFO::init_user_dir("./");
#endif
    PATH_INFO::set_standard_filenames();

    MAP_SHARING::setDefaults();
    {
        const char *section_default = nullptr;
        const char *section_map_sharing = "Map sharing";
        const char *section_user_directory = "User directories";
        const arg_handler first_pass_arguments[] = {
            {
                "--seed", "<string of letters and or numbers>",
                "Sets the random number generator's seed value",
                section_default,
                [&seed](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    const unsigned char *hash_input = (const unsigned char *) params[0];
                    seed = djb2_hash(hash_input);
                    return 1;
                }
            },
            {
                "--jsonverify", nullptr,
                "Checks the cdda json files",
                section_default,
                [&verifyexit](int, const char **) -> int {
                    verifyexit = true;
                    return 0;
                }
            },
            {
                "--check-mods", nullptr,
                "Checks the json files belonging to cdda mods",
                section_default,
                [&check_all_mods](int, const char **) -> int {
                    check_all_mods = true;
                    return 0;
                }
            },
            {
                "--basepath", "<path>",
                "Base path for all game data subdirectories",
                section_default,
                [](int num_args, const char **params) {
                    if (num_args < 1) return -1;
                    PATH_INFO::init_base_path(params[0]);
                    PATH_INFO::set_standard_filenames();
                    return 1;
                }
            },
            {
                "--shared", nullptr,
                "Activates the map-sharing mode",
                section_map_sharing,
                [](int, const char **) -> int {
                    MAP_SHARING::setSharing(true);
                    MAP_SHARING::setCompetitive(true);
                    MAP_SHARING::setWorldmenu(false);
                    return 0;
                }
            },
            {
                "--username", "<name>",
                "Instructs map-sharing code to use this name for your character.",
                section_map_sharing,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    MAP_SHARING::setUsername(params[0]);
                    return 1;
                }
            },
            {
                "--addadmin", "<username>",
                "Instructs map-sharing code to use this name for your character and give you "
                    "access to the cheat functions.",
                section_map_sharing,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    MAP_SHARING::addAdmin(params[0]);
                    return 1;
                }
            },
            {
                "--adddebugger", "<username>",
                "Informs map-sharing code that you're running inside a debugger",
                section_map_sharing,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    MAP_SHARING::addDebugger(params[0]);
                    return 1;
                }
            },
            {
                "--competitive", nullptr,
                "Instructs map-sharing code to disable access to the in-game cheat functions",
                section_map_sharing,
                [](int, const char **) -> int {
                    MAP_SHARING::setCompetitive(true);
                    return 0;
                }
            },
            {
                "--userdir", "<path>",
                "Base path for user-overrides to files from the ./data directory and named below",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::init_user_dir(params[0]);
                    PATH_INFO::set_standard_filenames();
                    return 1;
                }
            }
        };

        // The following arguments are dependent on one or more of the previous flags and are run
        // in a second pass.
        const arg_handler second_pass_arguments[] = {
            {
                "--worldmenu", nullptr,
                "Enables the world menu in the map-sharing code",
                section_map_sharing,
                [](int, const char **) -> int {
                    MAP_SHARING::setWorldmenu(true);
                    return true;
                }
            },
            {
                "--datadir", "<directory name>",
                "Sub directory from which game data is loaded",
                nullptr,
                [](int num_args, const char **params) -> int {
                      if (num_args < 1) return -1;
                      PATH_INFO::update_pathname("datadir", params[0]);
                      PATH_INFO::update_datadir();
                      return 1;
                }
            },
            {
                "--savedir", "<directory name>",
                "Subdirectory for game saves",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("savedir", params[0]);
                    return 1;
                }
            },
            {
                "--configdir", "<directory name>",
                "Subdirectory for game configuration",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("config_dir", params[0]);
                    PATH_INFO::update_config_dir();
                    return 1;
                }
            },
            {
                "--memorialdir", "<directory name>",
                "Subdirectory for memorials",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("memorialdir", params[0]);
                    return 1;
                }
            },
            {
                "--optionfile", "<filename>",
                "Name of the options file within the configdir",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("options", params[0]);
                    return 1;
                }
            },
            {
                "--keymapfile", "<filename>",
                "Name of the keymap file within the configdir",
                section_user_directory,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("keymap", params[0]);
                    return 1;
                }
            },
            {
                "--autopickupfile", "<filename>",
                "Name of the autopickup options file within the configdir",
                nullptr,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("autopickup", params[0]);
                    return 1;
                }
            },
            {
                "--motdfile", "<filename>",
                "Name of the message of the day file within the motd directory",
                nullptr,
                [](int num_args, const char **params) -> int {
                    if (num_args < 1) return -1;
                    PATH_INFO::update_pathname("motd", params[0]);
                    return 1;
                }
            },
        };

        // Process CLI arguments.
        const size_t num_first_pass_arguments =
            sizeof(first_pass_arguments) / sizeof(first_pass_arguments[0]);
        const size_t num_second_pass_arguments =
            sizeof(second_pass_arguments) / sizeof(second_pass_arguments[0]);
        int saved_argc = --argc; // skip program name
        const char **saved_argv = (const char **)++argv;
        while (argc) {
            if(!strcmp(argv[0], "--help")) {
                printHelpMessage(first_pass_arguments, num_first_pass_arguments,
                    second_pass_arguments, num_second_pass_arguments);
                return 0;
            } else {
                bool arg_handled = false;
                for (size_t i = 0; i < num_first_pass_arguments; ++i) {
                    auto &arg_handler = first_pass_arguments[i];
                    if (!strcmp(argv[0], arg_handler.flag)) {
                        argc--;
                        argv++;
                        int args_consumed = arg_handler.handler(argc, (const char **)argv);
                        if (args_consumed < 0) {
                            printf("Failed parsing parameter '%s'\n", *(argv - 1));
                            exit(1);
                        }
                        argc -= args_consumed;
                        argv += args_consumed;
                        arg_handled = true;
                        break;
                    }
                }
                // Skip other options.
                if (!arg_handled) {
                    --argc;
                    ++argv;
                }
            }
        }
        while (saved_argc) {
            bool arg_handled = false;
            for (size_t i = 0; i < num_second_pass_arguments; ++i) {
                auto &arg_handler = second_pass_arguments[i];
                if (!strcmp(saved_argv[0], arg_handler.flag)) {
                    --saved_argc;
                    ++saved_argv;
                    int args_consumed = arg_handler.handler(saved_argc, saved_argv);
                    if (args_consumed < 0) {
                        printf("Failed parsing parameter '%s'\n", *(argv - 1));
                        exit(1);
                    }
                    saved_argc -= args_consumed;
                    saved_argv += args_consumed;
                    arg_handled = true;
                    break;
                }
            }
            // Ingore unknown options.
            if (!arg_handled) {
                --saved_argc;
                ++saved_argv;
            }
        }
    }

    if (!assure_dir_exist(FILENAMES["user_dir"].c_str())) {
        printf("Can't open or create %s. Check permissions.\n",
               FILENAMES["user_dir"].c_str());
        exit(1);
    }

    setupDebug();

    if (setlocale(LC_ALL, "") == NULL) {
        DebugLog(D_WARNING, D_MAIN) << "Error while setlocale(LC_ALL, '').";
    }

    // Options strings loaded with system locale
    get_options().init();
    get_options().load();

    set_language(true);

    if (initscr() == NULL) { // Initialize ncurses
        DebugLog( D_ERROR, DC_ALL ) << "initscr failed!";
        return 1;
    }
    init_interface();
    noecho();  // Don't echo keypresses
    cbreak();  // C-style breaks (e.g. ^C to SIGINT)
    keypad(stdscr, true); // Numpad is numbers
#if !(defined TILES || defined _WIN32 || defined WINDOWS)
    // For tiles or windows, this is handled already in initscr().
    init_colors();
#endif
    // curs_set(0); // Invisible cursor
    set_escdelay(10); // Make escape actually responsive

    std::srand(seed);

    g = new game;
    // First load and initialize everything that does not
    // depend on the mods.
    try {
        g->load_static_data();
        if (verifyexit) {
            if(g->game_error()) {
                exit_handler(-999);
            }
            exit_handler(0);
        }
        if (check_all_mods) {
            // Here we load all the mods and check their
            // consistency (both is done in check_all_mod_data).
            g->init_ui();
            popup_nowait("checking all mods");
            g->check_all_mod_data();
            if(g->game_error()) {
                exit_handler(-999);
            }
            // At this stage, the mods (and core game data)
            // are find and we could start playing, but this
            // is only for verifying that stage, so we exit.
            exit_handler(0);
        }
    } catch( const std::exception &err ) {
        debugmsg( "%s", err.what() );
        exit_handler(-999);
    }

    // Now we do the actual game.

    g->init_ui();
    if(g->game_error()) {
        exit_handler(-999);
    }

    curs_set(0); // Invisible cursor here, because MAPBUFFER.load() is crash-prone

#if (!(defined _WIN32 || defined WINDOWS))
    struct sigaction sigIntHandler;
    sigIntHandler.sa_handler = exit_handler;
    sigemptyset(&sigIntHandler.sa_mask);
    sigIntHandler.sa_flags = 0;
    sigaction(SIGINT, &sigIntHandler, NULL);
#endif

    bool quit_game = false;
    do {
        if(!g->opening_screen()) {
            quit_game = true;
        }
        while (!quit_game && !g->do_turn()) ;
        if (g->game_quit() || g->game_error()) {
            quit_game = true;
        }
    } while (!quit_game);


    exit_handler(-999);

    return 0;
}
Ejemplo n.º 14
0
bool mod_manager::copy_mod_contents(const t_mod_list &mods_to_copy,
                                    const std::string &output_base_path)
{
    if (mods_to_copy.empty()) {
        // nothing to copy, so technically we succeeded already!
        return true;
    }
    std::vector<std::string> search_extensions;
    search_extensions.push_back(".json");

    DebugLog( D_INFO, DC_ALL ) << "Copying mod contents into directory: " << output_base_path;

    if (!assure_dir_exist(output_base_path)) {
        DebugLog( D_ERROR, DC_ALL ) << "Unable to create or open mod directory at [" << output_base_path <<
                                    "] for saving";
        return false;
    }

    std::ostringstream number_stream;
    for (size_t i = 0; i < mods_to_copy.size(); ++i) {
        number_stream.str(std::string());
        number_stream.width(5);
        number_stream.fill('0');
        number_stream << (i + 1);
        MOD_INFORMATION &mod = *mod_map[mods_to_copy[i]];
        size_t start_index = mod.path.size();

        // now to get all of the json files inside of the mod and get them ready to copy
        auto input_files = get_files_from_path(".json", mod.path, true, true);
        auto input_dirs  = get_directories_with(search_extensions, mod.path, true);

        if (input_files.empty() && mod.path.find(MOD_SEARCH_FILE) != std::string::npos) {
            // Self contained mod, all data is inside the modinfo.json file
            input_files.push_back(mod.path);
            start_index = mod.path.find_last_of("/\\");
            if (start_index == std::string::npos) {
                start_index = 0;
            }
        }

        if (input_files.empty()) {
            continue;
        }

        // create needed directories
        std::ostringstream cur_mod_dir;
        cur_mod_dir << output_base_path << "/mod_" << number_stream.str();

        std::queue<std::string> dir_to_make;
        dir_to_make.push(cur_mod_dir.str());
        for( auto &input_dir : input_dirs ) {
            dir_to_make.push( cur_mod_dir.str() + "/" + input_dir.substr( start_index ) );
        }

        while (!dir_to_make.empty()) {
            if (!assure_dir_exist(dir_to_make.front())) {
                DebugLog( D_ERROR, DC_ALL ) << "Unable to create or open mod directory at [" <<
                                            dir_to_make.front() << "] for saving";
            }

            dir_to_make.pop();
        }

        std::ofstream fout;
        // trim file paths from full length down to just /data forward
        for( auto &input_file : input_files ) {
            std::string output_path = input_file;
            output_path = cur_mod_dir.str() + output_path.substr(start_index);

            std::ifstream infile( input_file.c_str(), std::ifstream::in | std::ifstream::binary );
            // and stuff it into ram
            std::istringstream iss(
                std::string(
                    (std::istreambuf_iterator<char>(infile)),
                    std::istreambuf_iterator<char>()
                )
            );
            infile.close();

            fout.open(output_path.c_str());
            fout << iss.str();
            fout.close();
        }
    }
    return true;
}
Ejemplo n.º 15
0
void load_auto_pickup(bool bCharacter)
{
    std::ifstream fin;
    std::string sFile = FILENAMES["autopickup"];

    if (bCharacter) {
        sFile = world_generator->active_world->world_path + "/" + base64_encode(g->u.name) + ".apu.txt";
    }

    bool legacy_autopickup_loaded = false;
    fin.open(sFile.c_str());
    if(!fin.is_open()) {
        if( !bCharacter ) {
            fin.open(FILENAMES["legacy_autopickup"].c_str());
        }
        if( !fin.is_open() ) {
            assure_dir_exist(FILENAMES["config_dir"]);
            create_default_auto_pickup(bCharacter);
            fin.open(sFile.c_str());
        } else {
            legacy_autopickup_loaded = true;
        }

        if(!fin.is_open()) {
            DebugLog( D_ERROR, DC_ALL ) << "Could neither read nor create " << sFile;
            return;
        }
    }

    vAutoPickupRules[(bCharacter) ? APU_CHARACTER : APU_GLOBAL].clear();

    std::string sLine;
    while(!fin.eof()) {
        getline(fin, sLine);

        if(sLine != "" && sLine[0] != '#') {
            int iNum = std::count(sLine.begin(), sLine.end(), ';');

            if(iNum != 2) {
                DebugLog( D_ERROR, DC_ALL ) << "Bad Rule: " << sLine;
            } else {
                std::string sRule = "";
                bool bActive = true;
                bool bExclude = false;

                size_t iPos = 0;
                int iCol = 1;
                do {
                    iPos = sLine.find(";");

                    std::string sTemp = (iPos == std::string::npos) ? sLine : sLine.substr(0, iPos);

                    if (iCol == 1) {
                        sRule = sTemp;

                    } else if (iCol == 2) {
                        bActive = (sTemp == "T" || sTemp == "True") ? true : false;

                    } else if (iCol == 3) {
                        bExclude = (sTemp == "T" || sTemp == "True") ? true : false;
                    }

                    iCol++;

                    if (iPos != std::string::npos) {
                        sLine = sLine.substr(iPos + 1, sLine.size());
                    }

                } while(iPos != std::string::npos);

                vAutoPickupRules[(bCharacter) ? APU_CHARACTER : APU_GLOBAL].push_back(cPickupRules(sRule, bActive,
                        bExclude));
            }
        }
    }

    fin.close();
    merge_vector();
    createPickupRules();
    if( legacy_autopickup_loaded ) {
        assure_dir_exist(FILENAMES["config_dir"]);
        save_auto_pickup( bCharacter );
    }
}