void credits_parse_table(const char* filename) { try { read_file_text(filename, CF_TYPE_TABLES); reset_parse(); // any metadata? if (optional_string("$Music:")) { stuff_string(Credits_music_name, F_NAME, NAME_LENGTH); } if (optional_string("$Number of Images:")) { int temp; stuff_int(&temp); if (temp > 0) Credits_num_images = temp; } if (optional_string("$Start Image Index:")) { stuff_int(&Credits_artwork_index); // bounds check if (Credits_artwork_index < 0) { Credits_artwork_index = 0; } else if (Credits_artwork_index >= Credits_num_images) { Credits_artwork_index = Credits_num_images - 1; } } if (optional_string("$Text scroll rate:")) { stuff_float(&Credits_scroll_rate); if (Credits_scroll_rate < 0.01f) Credits_scroll_rate = 0.01f; } if (optional_string("$Artworks display time:")) { stuff_float(&Credits_artwork_display_time); if (Credits_artwork_display_time < 0.01f) Credits_artwork_display_time = 0.01f; } if (optional_string("$Artworks fade time:")) { stuff_float(&Credits_artwork_fade_time); if (Credits_artwork_fade_time < 0.01f) Credits_artwork_fade_time = 0.01f; } if (optional_string("$SCP Credits position:")) { char mode[NAME_LENGTH]; stuff_string(mode, F_NAME, NAME_LENGTH); if (!stricmp(mode, "Start")) SCP_credits_position = START; else if (!stricmp(mode, "End")) SCP_credits_position = END; else Warning(LOCATION, "Unknown credits position mode \"%s\".", mode); } ignore_white_space(); SCP_string credits_text; SCP_string line; SCP_vector<int> charNum; SCP_vector<const char*> lines; int numLines = -1; bool first_run = true; while (!check_for_string_raw("#end")) { // Read in a line of text stuff_string_line(line); // This is a bit odd but it means if a total conversion uses different credits the // Volition credit won't happen // Also don't append the default credits anymore when there was already a parsed table if (first_run && !Credits_parsed && !line.compare(mod_check)) { credits_text.append(unmodified_credits); } first_run = false; if (line.empty()) { // If the line is empty then just append a newline, don't bother with splitting it first credits_text.append("\n"); } else { // split_str doesn't take care of this. charNum.clear(); // Split the string into multiple lines if it's too long numLines = split_str(line.c_str(), Credits_text_coords[gr_screen.res][2], charNum, lines, -1); // Make sure that we have valid data Assertion(lines.size() == (size_t)numLines, "split_str reported %d lines but vector contains " SIZE_T_ARG " entries!", numLines, lines.size()); Assertion(lines.size() <= charNum.size(), "Something has gone wrong while splitting strings. Got " SIZE_T_ARG " lines but only " SIZE_T_ARG " chacter lengths.", lines.size(), charNum.size()); // Now add all splitted lines to the credit text and append a newline to the end for (int i = 0; i < numLines; i++) { credits_text.append(SCP_string(lines[i], charNum[i])); credits_text.append("\n"); } } } Credit_text_parts.push_back(credits_text); Credits_parsed = true; } catch (const parse::ParseException& e) { mprintf(("TABLES: Unable to parse '%s'! Error message = %s.\n", filename, e.what())); return; } }
void credits_init() { int i, w, h; credits_screen_buttons *b; char line[512] = ""; char *linep1, *linep2; int credits_spooled_music_index = event_music_get_spooled_music_index("Cinema"); if(credits_spooled_music_index != -1){ char *credits_wavfile_name = Spooled_music[credits_spooled_music_index].filename; if(credits_wavfile_name != NULL){ credits_load_music(credits_wavfile_name); } } // Use this id to trigger the start of music playing on the briefing screen Credits_music_begin_timestamp = timestamp(CREDITS_MUSIC_DELAY); Credits_frametime = 0; Credits_last_time = timer_get_milliseconds(); Credit_text = NULL; Credit_text_malloced = 0; // allocate enough space for credits text CFILE *fp = cfopen( NOX("credits.tbl"), "rb" ); if(fp != NULL){ int rval, size; size = cfilelength(fp); Credit_text = (char *) vm_malloc(size + 200 + strlen(fs2_open_credit_text) + strlen(unmodified_credits)); if (Credit_text == NULL) { return; } else { Credit_text_malloced = 1; } cfclose(fp); // open localization lcl_ext_open(); if ((rval = setjmp(parse_abort)) != 0) { mprintf(("TABLES: Unable to parse '%s'! Error code = %i.\n", "credits.tbl", rval)); lcl_ext_close(); return; } read_file_text("credits.tbl"); reset_parse(); // keep reading everything in strcpy(Credit_text, fs2_open_credit_text); bool first_run = true; while(!check_for_string_raw("#end")){ stuff_string_line(line, sizeof(line)); // This is a bit odd but it means if a total conversion uses different credits the // Volition credit won't happen if(first_run == true) { if(strcmp(line, mod_check) == 0) { strcat(Credit_text, unmodified_credits); } first_run = false; } linep1 = line; do { linep2 = split_str_once(linep1, Credits_text_coords[gr_screen.res][2]); Assert( linep2 != linep1 ); strcat(Credit_text, linep1); strcat(Credit_text, "\n"); linep1 = linep2; } while (linep2 != NULL); } // close localization lcl_ext_close(); } else { Credit_text = NOX("No credits available.\n"); } int ch; for ( i = 0; Credit_text[i]; i++ ) { ch = Credit_text[i]; switch (ch) { case -4: ch = 129; break; case -28: ch = 132; break; case -10: ch = 148; break; case -23: ch = 130; break; case -30: ch = 131; break; case -25: ch = 135; break; case -21: ch = 137; break; case -24: ch = 138; break; case -17: ch = 139; break; case -18: ch = 140; break; case -60: ch = 142; break; case -55: ch = 144; break; case -12: ch = 147; break; case -14: ch = 149; break; case -5: ch = 150; break; case -7: ch = 151; break; case -42: ch = 153; break; case -36: ch = 154; break; case -31: ch = 160; break; case -19: ch = 161; break; case -13: ch = 162; break; case -6: ch = 163; break; case -32: ch = 133; break; case -22: ch = 136; break; case -20: ch = 141; break; } Credit_text[i] = (char)ch; } gr_get_string_size(&w, &h, Credit_text); Credit_start_pos = i2fl(Credits_text_coords[gr_screen.res][CREDITS_H_COORD]); Credit_stop_pos = -i2fl(h); Credit_position = Credit_start_pos; Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0); Ui_window.set_mask_bmap(Credits_bitmap_mask_fname[gr_screen.res]); common_set_interface_palette("InterfacePalette"); // set the interface palette for (i=0; i<NUM_BUTTONS; i++) { b = &Buttons[i][gr_screen.res]; b->button.create(&Ui_window, "", b->x, b->y, 60, 30, (i < 2), 1); // set up callback for when a mouse first goes over a button b->button.set_highlight_action(common_play_highlight_sound); b->button.set_bmaps(b->filename); b->button.link_hotspot(b->hotspot); } // add some text Ui_window.add_XSTR("Technical Database", 1055, Buttons[TECH_DATABASE_BUTTON][gr_screen.res].xt, Buttons[TECH_DATABASE_BUTTON][gr_screen.res].yt, &Buttons[TECH_DATABASE_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Mission Simulator", 1056, Buttons[SIMULATOR_BUTTON][gr_screen.res].xt, Buttons[SIMULATOR_BUTTON][gr_screen.res].yt, &Buttons[SIMULATOR_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Cutscenes", 1057, Buttons[CUTSCENES_BUTTON][gr_screen.res].xt, Buttons[CUTSCENES_BUTTON][gr_screen.res].yt, &Buttons[CUTSCENES_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Credits", 1058, Buttons[CREDITS_BUTTON][gr_screen.res].xt, Buttons[CREDITS_BUTTON][gr_screen.res].yt, &Buttons[CREDITS_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_GREEN); Ui_window.add_XSTR("Exit", 1420, Buttons[EXIT_BUTTON][gr_screen.res].xt, Buttons[EXIT_BUTTON][gr_screen.res].yt, &Buttons[EXIT_BUTTON][gr_screen.res].button, UI_XSTR_COLOR_PINK); if (Player->flags & PLAYER_FLAGS_IS_MULTI) { Buttons[SIMULATOR_BUTTON][gr_screen.res].button.disable(); Buttons[CUTSCENES_BUTTON][gr_screen.res].button.disable(); } Buttons[EXIT_BUTTON][gr_screen.res].button.set_hotkey(KEY_CTRLED | KEY_ENTER); Background_bitmap = bm_load(Credits_bitmap_fname[gr_screen.res]); Credits_artwork_index = rand() % NUM_IMAGES; for (i=0; i<NUM_IMAGES; i++){ Credits_bmps[i] = -1; } // CreditsWin01 = bm_load(NOX("CreditsWin01")); // CreditsWin02 = bm_load(NOX("CreditsWin02")); // CreditsWin03 = bm_load(NOX("CreditsWin03")); // CreditsWin04 = bm_load(NOX("CreditsWin04")); }