mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 22:56:30 -10:00
* use std::move() for local variables that are copied but not reused Addresses ~140 Coverity "Variable copied when it could be moved" defects across 74 files. Every std::move() targets a local variable whose value is consumed by push_back, emplace, assignment, lambda capture, or a function call and is never read again afterward. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]> * clang: use std::make_shared * clang: use std::make_unique * address feedback --------- Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
663 lines
21 KiB
C++
663 lines
21 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include "controlconfig/controlsconfig.h"
|
|
#include "freespace.h"
|
|
#include "gamehelp/gameplayhelp.h"
|
|
#include "gamesequence/gamesequence.h"
|
|
#include "gamesnd/gamesnd.h"
|
|
#include "globalincs/alphacolors.h"
|
|
#include "io/key.h"
|
|
#include "mission/missionmessage.h"
|
|
#include "missionui/missionscreencommon.h"
|
|
#include "sound/audiostr.h"
|
|
#include "ui/ui.h"
|
|
#include "weapon/weapon.h"
|
|
|
|
|
|
|
|
// text positioning constants
|
|
#define TITLE_Y 35
|
|
#define Y_START 70
|
|
#define X_OFFSET_1 70
|
|
|
|
// pixel offset for description of key from where key binding starts
|
|
// increased this from 193 to 250 to account for allowing multiple keys -Mjn
|
|
#define KEY_DESCRIPTION_OFFSET 250
|
|
|
|
// different gameplay help pages
|
|
enum : int {
|
|
// The first 9 are the basic retail pages
|
|
GP_HELP_BASIC_KEYS,
|
|
GP_HELP_MOVEMENT_KEYS,
|
|
GP_HELP_COMMON_TARGET_KEYS,
|
|
GP_HELP_ADVANCED_TARGET_KEYS,
|
|
GP_HELP_MESSAGING,
|
|
GP_HELP_WEAPON_KEYS,
|
|
GP_HELP_THROTTLE_AND_ETS_KEYS,
|
|
GP_HELP_VIEW_KEYS,
|
|
GP_HELP_MISC_KEYS,
|
|
|
|
// Plus one for multi only
|
|
GP_HELP_MULTI_KEYS,
|
|
|
|
// Any others defined here will have unique sections within the vector
|
|
// but will need special handling to display in the retail UI
|
|
GP_HELP_FUNCTION_KEYS,
|
|
|
|
First_available_section
|
|
};
|
|
|
|
#define GP_FIRST_SCREEN 0 // keep up to date
|
|
#define GP_LAST_SCREEN_SINGLE 8 // keep up to date
|
|
#define GP_LAST_SCREEN_MULTI 9 // keep up to date
|
|
|
|
// set this to GP_LAST_SCREEN_SINGLE or GP_LAST_SCREEN_MULTI based upon what game mode we're in
|
|
static int Gp_last_screen;
|
|
|
|
#define NUM_BUTTONS 3
|
|
#define PREVIOUS_PAGE_BUTTON 0
|
|
#define NEXT_PAGE_BUTTON 1
|
|
#define CONTINUE_BUTTON 2
|
|
|
|
struct gameplay_help_buttons {
|
|
const char *filename;
|
|
int x, y;
|
|
int hotspot;
|
|
int tab;
|
|
int flags;
|
|
UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
|
|
|
|
gameplay_help_buttons(const char *name, int x1, int y1, int h) : filename(name), x(x1), y(y1), hotspot(h) {}
|
|
};
|
|
|
|
static gameplay_help_buttons Buttons[GR_NUM_RESOLUTIONS][NUM_BUTTONS] = {
|
|
//XSTR:OFF
|
|
{
|
|
gameplay_help_buttons("F1B_00", 15, 389, 0),
|
|
gameplay_help_buttons("F1B_01", 60, 389, 1),
|
|
gameplay_help_buttons("F1B_02", 574, 431, 2)
|
|
},
|
|
{
|
|
gameplay_help_buttons("2_F1B_00", 24, 622, 0),
|
|
gameplay_help_buttons("2_F1B_01", 96, 622, 1),
|
|
gameplay_help_buttons("2_F1B_02", 919, 689, 2)
|
|
},
|
|
//XSTR:ON
|
|
};
|
|
|
|
#define GAME_HELP_NUM_TEXT 2
|
|
static UI_XSTR Game_help_text[GR_NUM_RESOLUTIONS][GAME_HELP_NUM_TEXT] = {
|
|
{ // GR_640
|
|
{ "Press ESC to return to the game", 1441, 263, 389, UI_XSTR_COLOR_GREEN, -1, NULL },
|
|
{ "Continue", 1069, 571, 413, UI_XSTR_COLOR_GREEN, -1, &Buttons[gr_screen.res][CONTINUE_BUTTON].button }
|
|
},
|
|
{ // GR_1024
|
|
{ "Press ESC to return to the game", 1441, 421, 622, UI_XSTR_COLOR_GREEN, -1, NULL },
|
|
{ "Continue", 1069, 928, 663, UI_XSTR_COLOR_GREEN, -1, &Buttons[gr_screen.res][CONTINUE_BUTTON].button }
|
|
}
|
|
};
|
|
|
|
static const char *Game_help_filename[GR_NUM_RESOLUTIONS] = {
|
|
"F1",
|
|
"2_F1"
|
|
};
|
|
|
|
static const char *Game_help_mask_filename[GR_NUM_RESOLUTIONS] = {
|
|
"F1-m",
|
|
"2_F1-m"
|
|
};
|
|
|
|
static UI_WINDOW Ui_window;
|
|
static int Background_bitmap;
|
|
static int Gameplay_help_inited = 0;
|
|
|
|
static int Current_help_page;
|
|
|
|
SCP_vector<gameplay_help_section> Help_text;
|
|
|
|
void gameplay_help_init_control_line(int id, gameplay_help_section &thisHelp)
|
|
{
|
|
char buf[256];
|
|
|
|
auto ci = &Control_config[id];
|
|
|
|
// do not draw if a mod has disabled this control --wookieejedi
|
|
if (ci->disabled) {
|
|
return;
|
|
}
|
|
|
|
buf[0] = 0;
|
|
|
|
strcpy_s(buf, ci->first.textify().c_str());
|
|
|
|
if (!ci->second.empty()) {
|
|
strcat_s(buf, XSTR(", ", 129));
|
|
strcat_s(buf, ci->second.textify().c_str());
|
|
}
|
|
|
|
if (ci->empty()) {
|
|
strcpy_s(buf, XSTR("no binding", 130));
|
|
}
|
|
|
|
thisHelp.key.push_back(buf);
|
|
thisHelp.text.push_back(XSTR(ci->text.c_str(), CONTROL_CONFIG_XSTR + id));
|
|
}
|
|
|
|
void gameplay_help_init_control_line_raw(const char* control_text, const char* control_description, gameplay_help_section &thisHelp)
|
|
{
|
|
thisHelp.key.push_back(control_text);
|
|
thisHelp.text.push_back(control_description);
|
|
}
|
|
|
|
// displays the given help key and text at the specified
|
|
// x and y coordinates
|
|
void gameplay_help_blit_help_text(int x, int y, const SCP_string *control_text, const SCP_string *control_description)
|
|
{
|
|
gr_string(x, y, control_text->c_str(), GR_RESIZE_MENU);
|
|
gr_string(x + KEY_DESCRIPTION_OFFSET, y, control_description->c_str(), GR_RESIZE_MENU);
|
|
}
|
|
|
|
// displays a help section header at the specified y coordinate and an x coordinate
|
|
// calculated from the header string's length
|
|
void gameplay_help_blit_header_text(int y_offset, const SCP_string *header)
|
|
{
|
|
gr_set_color_fast(&Color_bright);
|
|
int w;
|
|
gr_get_string_size(&w, nullptr, header->c_str());
|
|
gr_printf_menu((gr_screen.clip_width - w) / 2, y_offset, "%s", header->c_str());
|
|
gr_set_color_fast(&Color_normal);
|
|
}
|
|
|
|
// game_play_help_set_title() will display the title for the help screen and
|
|
// set the font for the rest of the screen
|
|
void gameplay_help_set_title(const SCP_string *title)
|
|
{
|
|
int sy=TITLE_Y;
|
|
char buf[128];
|
|
|
|
gr_set_color_fast(&Color_bright);
|
|
int w;
|
|
gr_get_string_size(&w, nullptr, title->c_str());
|
|
|
|
gr_printf_menu((gr_screen.clip_width_unscaled - w) / 2,sy,"%s", title->c_str());
|
|
|
|
sprintf(buf, XSTR("Page %d of %d", 132), Current_help_page + 1, Gp_last_screen + 1);
|
|
gr_get_string_size(&w, NULL, buf);
|
|
gr_printf_menu((gr_screen.clip_width_unscaled - w) / 2, sy + gr_get_font_height() + 2, "%s", buf);
|
|
gr_set_color_fast(&Color_normal);
|
|
}
|
|
|
|
// Inits all the gameplay help text and returns it
|
|
// in a nice organized vector of help sections
|
|
SCP_vector<gameplay_help_section> gameplay_help_init_text()
|
|
{
|
|
SCP_vector<gameplay_help_section> complete_help_text;
|
|
|
|
for (int i = 0; i < First_available_section; i++) {
|
|
|
|
gameplay_help_section thisHelp;
|
|
|
|
switch (i) {
|
|
|
|
case GP_HELP_BASIC_KEYS:
|
|
thisHelp.title = XSTR("Basic Keys", 133);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(END_MISSION, thisHelp);
|
|
gameplay_help_init_control_line(FIRE_PRIMARY, thisHelp);
|
|
gameplay_help_init_control_line(MAX_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(ZERO_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV, thisHelp);
|
|
gameplay_help_init_control_line(TOGGLE_AUTO_TARGETING, thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_MOVEMENT_KEYS:
|
|
thisHelp.title = XSTR("Movement Keys", 147);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(FORWARD_THRUST, thisHelp);
|
|
gameplay_help_init_control_line(MAX_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(ONE_THIRD_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(TWO_THIRDS_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(MINUS_5_PERCENT_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(PLUS_5_PERCENT_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(ZERO_THROTTLE, thisHelp);
|
|
gameplay_help_init_control_line(AFTERBURNER, thisHelp);
|
|
gameplay_help_init_control_line(REVERSE_THRUST, thisHelp);
|
|
gameplay_help_init_control_line(PITCH_FORWARD, thisHelp);
|
|
gameplay_help_init_control_line(PITCH_BACK, thisHelp);
|
|
gameplay_help_init_control_line(YAW_LEFT, thisHelp);
|
|
gameplay_help_init_control_line(YAW_RIGHT, thisHelp);
|
|
gameplay_help_init_control_line(BANK_LEFT, thisHelp);
|
|
gameplay_help_init_control_line(BANK_RIGHT, thisHelp);
|
|
gameplay_help_init_control_line(BANK_WHEN_PRESSED, thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_COMMON_TARGET_KEYS:
|
|
thisHelp.title = XSTR("Basic Targeting Keys", 148);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(TARGET_NEXT, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV, thisHelp);
|
|
gameplay_help_init_control_line(TOGGLE_AUTO_TARGETING, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_SHIP_IN_RETICLE, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT_CLOSEST_HOSTILE, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV_CLOSEST_HOSTILE, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT_CLOSEST_FRIENDLY, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV_CLOSEST_FRIENDLY, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT_SUBOBJECT, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV_SUBOBJECT, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_SUBOBJECT_IN_RETICLE, thisHelp);
|
|
gameplay_help_init_control_line(MATCH_TARGET_SPEED, thisHelp);
|
|
gameplay_help_init_control_line(TOGGLE_AUTO_MATCH_TARGET_SPEED, thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_ADVANCED_TARGET_KEYS:
|
|
thisHelp.title = XSTR("Advanced Targeting Keys", 149);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(TARGET_CLOSEST_SHIP_ATTACKING_SELF, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_CLOSEST_SHIP_ATTACKING_TARGET, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_LAST_TRANMISSION_SENDER, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_TARGETS_TARGET, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT_ESCORT_SHIP, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_CLOSEST_REPAIR_SHIP, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT_UNINSPECTED_CARGO, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV_UNINSPECTED_CARGO, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEWEST_SHIP, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT_BOMB, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV_BOMB, thisHelp);
|
|
gameplay_help_init_control_line(STOP_TARGETING_SHIP, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_NEXT_LIVE_TURRET, thisHelp);
|
|
gameplay_help_init_control_line(TARGET_PREV_LIVE_TURRET, thisHelp);
|
|
gameplay_help_init_control_line(STOP_TARGETING_SUBSYSTEM, thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("F5...F12", 143), XSTR("Select target assigned to that hotkey", 150), thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("Shift-F5...F12", 151), XSTR("Add/remove target from that hotkey", 152), thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("Alt-Shift-F5...F12", 153), XSTR("Clear that hotkey", 154), thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_MESSAGING:
|
|
thisHelp.title = XSTR("Messaging Keys", 155);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(SQUADMSG_MENU, thisHelp);
|
|
gameplay_help_init_control_line(REARM_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(ATTACK_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(DISARM_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(DISABLE_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(CAPTURE_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(ENGAGE_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(FORM_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(IGNORE_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(PROTECT_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(COVER_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line(WARP_MESSAGE, thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("F5...F12", 143),
|
|
XSTR("send specified order to these target(s)", 156),
|
|
thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_WEAPON_KEYS:
|
|
thisHelp.title = XSTR("Weapon Keys", 157);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(FIRE_PRIMARY, thisHelp);
|
|
gameplay_help_init_control_line(FIRE_SECONDARY, thisHelp);
|
|
gameplay_help_init_control_line(CYCLE_NEXT_PRIMARY, thisHelp);
|
|
gameplay_help_init_control_line(CYCLE_PREV_PRIMARY, thisHelp);
|
|
gameplay_help_init_control_line(CYCLE_SECONDARY, thisHelp);
|
|
gameplay_help_init_control_line(CYCLE_NUM_MISSLES, thisHelp);
|
|
gameplay_help_init_control_line(LAUNCH_COUNTERMEASURE, thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_THROTTLE_AND_ETS_KEYS:
|
|
thisHelp.title = XSTR("Energy Management Keys", 158);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(SHIELD_EQUALIZE, thisHelp);
|
|
gameplay_help_init_control_line(SHIELD_XFER_TOP, thisHelp);
|
|
gameplay_help_init_control_line(SHIELD_XFER_BOTTOM, thisHelp);
|
|
gameplay_help_init_control_line(SHIELD_XFER_LEFT, thisHelp);
|
|
gameplay_help_init_control_line(SHIELD_XFER_RIGHT, thisHelp);
|
|
gameplay_help_init_control_line(INCREASE_WEAPON, thisHelp);
|
|
gameplay_help_init_control_line(DECREASE_WEAPON, thisHelp);
|
|
gameplay_help_init_control_line(INCREASE_SHIELD, thisHelp);
|
|
gameplay_help_init_control_line(DECREASE_SHIELD, thisHelp);
|
|
gameplay_help_init_control_line(INCREASE_ENGINE, thisHelp);
|
|
gameplay_help_init_control_line(DECREASE_ENGINE, thisHelp);
|
|
gameplay_help_init_control_line(ETS_EQUALIZE, thisHelp);
|
|
/*
|
|
gameplay_help_init_control_line(XFER_LASER, thisHelp);
|
|
gameplay_help_init_control_line(XFER_SHIELD, thisHelp);
|
|
*/
|
|
|
|
break;
|
|
|
|
case GP_HELP_MISC_KEYS:
|
|
thisHelp.title = XSTR("Miscellaneous Keys", 159);
|
|
|
|
thisHelp.header = "";
|
|
|
|
// ending mission
|
|
gameplay_help_init_control_line(END_MISSION, thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("ESC", 160), XSTR("invoke abort mission popup", 161), thisHelp);
|
|
|
|
// time compression
|
|
gameplay_help_init_control_line(TIME_SPEED_UP, thisHelp);
|
|
gameplay_help_init_control_line(TIME_SLOW_DOWN, thisHelp);
|
|
|
|
// radar keys
|
|
gameplay_help_init_control_line(RADAR_RANGE_CYCLE, thisHelp);
|
|
|
|
// escort view keys
|
|
gameplay_help_init_control_line(ADD_REMOVE_ESCORT, thisHelp);
|
|
gameplay_help_init_control_line(ESCORT_CLEAR, thisHelp);
|
|
|
|
// Pause, Print Screenshot
|
|
gameplay_help_init_control_line_raw(XSTR("Pause", 162), XSTR("pause game", 163), thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("Print Scrn", 164), XSTR("take screen shot", 165), thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_VIEW_KEYS:
|
|
thisHelp.title = XSTR("View Keys", 166);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line(PADLOCK_UP, thisHelp);
|
|
gameplay_help_init_control_line(PADLOCK_DOWN, thisHelp);
|
|
gameplay_help_init_control_line(PADLOCK_LEFT, thisHelp);
|
|
gameplay_help_init_control_line(PADLOCK_RIGHT, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_CHASE, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_EXTERNAL, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_EXTERNAL_TOGGLE_CAMERA_LOCK, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_SLEW, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_DIST_INCREASE, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_DIST_DECREASE, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_CENTER, thisHelp);
|
|
gameplay_help_init_control_line(VIEW_OTHER_SHIP, thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_MULTI_KEYS:
|
|
thisHelp.title = XSTR("Multiplayer Keys", 167);
|
|
|
|
thisHelp.header = XSTR("Ingame messaging keys (tap for text, hold for voice)", 168);
|
|
|
|
gameplay_help_init_control_line(MULTI_MESSAGE_ALL, thisHelp);
|
|
gameplay_help_init_control_line(MULTI_MESSAGE_FRIENDLY, thisHelp);
|
|
gameplay_help_init_control_line(MULTI_MESSAGE_HOSTILE, thisHelp);
|
|
gameplay_help_init_control_line(MULTI_MESSAGE_TARGET, thisHelp);
|
|
|
|
break;
|
|
|
|
case GP_HELP_FUNCTION_KEYS:
|
|
thisHelp.title = XSTR("Function Keys", 134);
|
|
|
|
thisHelp.header = "";
|
|
|
|
gameplay_help_init_control_line_raw(XSTR("F1", 135), XSTR("context-sensitive help", 136), thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("F2", 137),
|
|
XSTR("options screen (available anywhere in game)", 138),
|
|
thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("F3", 139), XSTR("hotkey assignment", 140), thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("F4", 141), XSTR("HUD message scroll-back", 142), thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("F5...F12", 143), XSTR("hotkeys", 144), thisHelp);
|
|
gameplay_help_init_control_line_raw(XSTR("Shift-Esc", 145),
|
|
XSTR("quit FreeSpace 2 immediately", 146),
|
|
thisHelp);
|
|
|
|
break;
|
|
|
|
default:
|
|
continue;
|
|
|
|
}
|
|
|
|
complete_help_text.push_back(std::move(thisHelp));
|
|
}
|
|
|
|
return complete_help_text;
|
|
}
|
|
|
|
// called once when the gameplay help state is entered
|
|
void gameplay_help_init()
|
|
{
|
|
int i;
|
|
gameplay_help_buttons *b;
|
|
|
|
if ( Gameplay_help_inited ) {
|
|
return;
|
|
}
|
|
|
|
// init all the help text
|
|
Help_text.clear(); //Make sure the array is empty before we start.
|
|
Help_text = gameplay_help_init_text();
|
|
|
|
common_set_interface_palette("InterfacePalette"); // set the interface palette
|
|
Ui_window.create(0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0);
|
|
Ui_window.set_mask_bmap(Game_help_mask_filename[gr_screen.res]);
|
|
|
|
for (i=0; i<NUM_BUTTONS; i++) {
|
|
b = &Buttons[gr_screen.res][i];
|
|
|
|
b->button.create(&Ui_window, "", b->x, b->y, 60, 30, 0, 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 all xstrs
|
|
for (i=0; i<GAME_HELP_NUM_TEXT; i++)
|
|
{
|
|
Ui_window.add_XSTR(&Game_help_text[gr_screen.res][i]);
|
|
}
|
|
|
|
// set the proper last screen # based upon game mode
|
|
if(Game_mode & GM_MULTIPLAYER){
|
|
Gp_last_screen = GP_LAST_SCREEN_MULTI;
|
|
} else {
|
|
Gp_last_screen = GP_LAST_SCREEN_SINGLE;
|
|
}
|
|
|
|
// setup hotkeys so lights flash when keys are pressed
|
|
Buttons[gr_screen.res][CONTINUE_BUTTON].button.set_hotkey(KEY_CTRLED | KEY_ENTER);
|
|
Buttons[gr_screen.res][PREVIOUS_PAGE_BUTTON].button.set_hotkey(KEY_LEFT);
|
|
Buttons[gr_screen.res][NEXT_PAGE_BUTTON].button.set_hotkey(KEY_RIGHT);
|
|
|
|
Background_bitmap = bm_load(Game_help_filename[gr_screen.res]);
|
|
|
|
Current_help_page = GP_FIRST_SCREEN;
|
|
Gameplay_help_inited = 1;
|
|
}
|
|
|
|
// called when moving to the previous help page
|
|
void gameplay_help_goto_prev_screen()
|
|
{
|
|
Current_help_page--;
|
|
if (Current_help_page < GP_FIRST_SCREEN) {
|
|
Current_help_page = Gp_last_screen;
|
|
}
|
|
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
|
|
|
}
|
|
|
|
// called when proceeding to the next help page
|
|
void gameplay_help_goto_next_screen()
|
|
{
|
|
Current_help_page++;
|
|
if (Current_help_page > Gp_last_screen) {
|
|
Current_help_page = GP_FIRST_SCREEN;
|
|
}
|
|
gamesnd_play_iface(InterfaceSounds::SWITCH_SCREENS);
|
|
}
|
|
|
|
// called when the screen is exited
|
|
void gameplay_help_leave()
|
|
{
|
|
// unpause all game sounds
|
|
weapon_unpause_sounds();
|
|
audiostream_unpause_all();
|
|
message_resume_all();
|
|
|
|
gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
|
|
game_flush();
|
|
}
|
|
|
|
// deal with a keypress on the gameplay help screen
|
|
void gameplay_help_process_key(int k)
|
|
{
|
|
switch ( k ) {
|
|
case KEY_ESC:
|
|
gameplay_help_leave();
|
|
break;
|
|
|
|
case KEY_ENTER:
|
|
case KEY_SPACEBAR:
|
|
case KEY_TAB:
|
|
//gameplay_help_goto_next_screen();
|
|
Buttons[gr_screen.res][NEXT_PAGE_BUTTON].button.press_button();
|
|
break;
|
|
|
|
case KEY_SHIFTED | KEY_TAB:
|
|
Buttons[gr_screen.res][PREVIOUS_PAGE_BUTTON].button.press_button();
|
|
// gameplay_help_goto_prev_screen();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
} // end switch
|
|
}
|
|
|
|
// deal with buttons being pressed on the gameplay help screen
|
|
void gameplay_help_button_pressed(int n)
|
|
{
|
|
switch (n) {
|
|
|
|
case PREVIOUS_PAGE_BUTTON:
|
|
gameplay_help_goto_prev_screen();
|
|
break;
|
|
|
|
case NEXT_PAGE_BUTTON:
|
|
gameplay_help_goto_next_screen();
|
|
break;
|
|
|
|
case CONTINUE_BUTTON:
|
|
gameplay_help_leave();
|
|
gamesnd_play_iface(InterfaceSounds::COMMIT_PRESSED);
|
|
break;
|
|
|
|
default:
|
|
Int3();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Draw the help text onto the screen
|
|
void gameplay_help_draw_text()
|
|
{
|
|
int x_offset, y_offset, separation;
|
|
|
|
separation = gr_get_font_height() + 3;
|
|
|
|
gameplay_help_section thisHelp = Help_text[Current_help_page];
|
|
|
|
gameplay_help_set_title(&thisHelp.title);
|
|
x_offset = X_OFFSET_1;
|
|
y_offset = Y_START;
|
|
|
|
// if we have a header then display it
|
|
if (thisHelp.header.length() > 0) {
|
|
gameplay_help_blit_header_text(y_offset, &thisHelp.header);
|
|
y_offset += separation;
|
|
}
|
|
|
|
// blit help text for each key
|
|
for (int i = 0; i < (int)thisHelp.key.size(); i++) {
|
|
y_offset += separation;
|
|
gameplay_help_blit_help_text(x_offset, y_offset, &thisHelp.key[i], &thisHelp.text[i]);
|
|
}
|
|
|
|
// Special handling of function keys to display on the same page as the basic keys
|
|
if (Current_help_page == GP_HELP_BASIC_KEYS) {
|
|
|
|
y_offset += separation;
|
|
y_offset += separation;
|
|
|
|
thisHelp = Help_text[GP_HELP_FUNCTION_KEYS];
|
|
|
|
gameplay_help_blit_header_text(y_offset, &thisHelp.title);
|
|
|
|
y_offset += separation;
|
|
y_offset += separation;
|
|
|
|
// blit help text for each key
|
|
for (int i = 0; i < (int)thisHelp.key.size(); i++) {
|
|
y_offset += separation;
|
|
gameplay_help_blit_help_text(x_offset, y_offset, &thisHelp.key[i], &thisHelp.text[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// gameplay_help_do_frame() is the function that displays help when acutally playing the game
|
|
void gameplay_help_do_frame(float /*frametime*/)
|
|
{
|
|
int i, k;
|
|
|
|
// ensure the gameplay help interface has been initialized
|
|
if (!Gameplay_help_inited) {
|
|
Int3();
|
|
return;
|
|
}
|
|
|
|
// make sure game sounds are paused
|
|
weapon_pause_sounds();
|
|
audiostream_pause_all();
|
|
message_pause_all();
|
|
|
|
k = Ui_window.process() & ~KEY_DEBUGGED;
|
|
gameplay_help_process_key(k);
|
|
|
|
for (i=0; i<NUM_BUTTONS; i++){
|
|
if (Buttons[gr_screen.res][i].button.pressed()){
|
|
gameplay_help_button_pressed(i);
|
|
}
|
|
}
|
|
|
|
GR_MAYBE_CLEAR_RES(Background_bitmap);
|
|
if (Background_bitmap >= 0) {
|
|
gr_set_bitmap(Background_bitmap);
|
|
gr_bitmap(0, 0, GR_RESIZE_MENU);
|
|
}
|
|
|
|
Ui_window.draw();
|
|
|
|
gameplay_help_draw_text();
|
|
gr_flip();
|
|
}
|