Files
source/FeaturesScreen.cpp
T
Sevenfm be80da650c Various improvements by rftr:
- added more toggles to the features screen: drop all, suppression, drassen/city counterattacks, dynamic opinions and dialogue, and weather
- fixed weather rendering check for individual weather types
- added mousewheel support to options screen and features screen to navigate through pages
- added keyboard inputs to options screen and features screen: TAB toggles between features and options, and A/D/leftarrow/rightarrow navigates through pages

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@9230 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2022-01-03 22:49:43 +00:00

1607 lines
50 KiB
C++

#ifdef PRECOMPILEDHEADERS
#include "JA2 All.h"
#else
#include "Types.h"
#include "FeaturesScreen.h"
#include "Video.h"
#include "Font Control.h"
#include "Game Clock.h"
#include "Text Input.h"
#include "WordWrap.h"
#include "SaveLoadScreen.h"
#include "Render Dirty.h"
#include "WordWrap.h"
#include "WCheck.h"
#include "Utilities.h"
#include "Debug.h"
#include "Sound Control.h"
#include "Ambient Control.h"
#include "Worlddat.h"
#include "Worlddef.h"
#include "GameSettings.h"
#include "Game Init.h"
#include "English.h"
#include "Overhead.h"
#include "Gap.h"
#include "Cursors.h"
#include "SysUtil.h"
#include "Exit Grids.h"
#include "Text.h"
#include "Interface Control.h"
#include "Message.h"
#include "Language Defines.h"
#include "Multi Language Graphic Utils.h"
#include "Map Information.h"
#include "Sys Globals.h"
#include "insurance.h"
#endif
#include "connect.h"
#include "WorldMan.h"
#include "Init.h"
#include "Game Events.h"
extern UINT32 guiDoneButton; // symbol already declared globally in AimArchives.cpp (jonathanl)
namespace FeaturesScreen
{
// this enum must be kept in sync with z113FeaturesScreenText
enum Text
{
FST_TITLE,
FST_DESCRIPTION,
FST_HOVER_FOR_MORE_INFO,
};
/////////////////////////////////
//
// Global Variables
//
/////////////////////////////////
UINT32 guiFeaturesBackGroundImage;
UINT32 guiFeaturesAddOnImages;
BOOLEAN gfFeaturesScreenEntry = TRUE;
BOOLEAN gfFeaturesScreenExit = FALSE;
BOOLEAN gfRedrawFeaturesScreen = TRUE;
BOOLEAN gfEnteredFromMapScreen = FALSE; // entered from options screen or new game screen
UINT32 guiFeaturesScreen = FEATURES_SCREEN;
UINT32 guiPreviousScreen = FEATURES_SCREEN;
BOOLEAN gfExitFeaturesDueToMessageBox = FALSE;
BOOLEAN gfExitFeaturesAfterMessageBox = FALSE;
INT32 giFeaturesMessageBox = -1; // Options pop up messages index value
INT8 gbHighLightedOptionText = -1;
// Goto save game Button
void BtnOptGotoSaveGameCallback(GUI_BUTTON* btn, INT32 reason);
UINT32 guiOptGotoSaveGameBtn;
INT32 giOptionsButtonImages;
// Goto load game button
void BtnOptGotoLoadGameCallback(GUI_BUTTON* btn, INT32 reason);
UINT32 guiOptGotoLoadGameBtn;
INT32 giGotoLoadBtnImage;
// QuitButton
void BtnOptQuitCallback(GUI_BUTTON* btn, INT32 reason);
UINT32 guiQuitButton;
INT32 giQuitBtnImage;
// Options Button
void BtnOptionsCallback(GUI_BUTTON* btn, INT32 reason);
UINT32 guiOptionsButton;
INT32 giOptionsBtnImage;
// arynn : need more option screen toggles : Add in button that allow for options column paging
// Options Screen globals
INT16 OptionsList_Column_Offset = 0; // the first column's -or- "half page" start
INT16 Current_First_Option_Index; // index of the first (single) option in the first column, used in lookup option vs togglebox
INT16 Max_Number_Of_Pages = 0; // dynamic column counter per build/mode type
void Establish_Features_Screen_Rules(void); // define the display rules
void Build_Features_List_Reinterpretation(void); // interpret rules and build a set of which options are used for use in options screen
void Create_Toggle_Buttons(void); // these two are blcok removals from functions, an isolation of toggle create/destroy
void Destroy_Toggle_Buttons(void);
// Next Button
void BtnOptNextCallback(GUI_BUTTON* btn, INT32 reason);
UINT32 guiOptNextButton;
INT32 giOptNextBtnImage;
// Prev Button
void BtnOptPrevCallback(GUI_BUTTON* btn, INT32 reason);
UINT32 guiOptPrevButton;
INT32 giOptPrevBtnImage;
// Done Button
void BtnDoneCallback(GUI_BUTTON* btn, INT32 reason);
INT32 giDoneBtnImage;
//checkbox to toggle tracking mode on or off
UINT32 guiFeaturesToggles[MAX_NUMBER_OF_OPTION_TOGGLES]; //array of ButtonID, index's for button list
BOOL Buttons_Exist_State = 0;
void BtnOptionsTogglesCallback(GUI_BUTTON* btn, INT32 reason);
//Mouse regions for the name of the option
MOUSE_REGION gSelectedOptionTextRegion[MAX_NUMBER_OF_OPTION_TOGGLES];
void SelectedOptionTextRegionCallBack(MOUSE_REGION* pRegion, INT32 iReason);
void SelectedOptionTextRegionMovementCallBack(MOUSE_REGION* pRegion, INT32 reason);
//Mouse regions for the area around the toggle boxs
MOUSE_REGION gSelectedToggleBoxAreaRegion;
void SelectedToggleBoxAreaRegionMovementCallBack(MOUSE_REGION* pRegion, INT32 reason);
//toggle box correspondence to option tracker
//1 define the render rules,
//2 recast real options into new array under constraints of rules,
//3 then using a pager system, create a subset that will fit on screen
int toggle_box_feature_rules[NUM_FEATURE_FLAGS]; // index = game option value = render state
int toggle_box_gGameSettings_recast[NUM_FEATURE_FLAGS + OPT_FIRST_COLUMN_TOGGLE_CUT_OFF];
// index = reinterpreted positions value = game_option or state
//" + OPT_FIRST_COLUMN_TOGGLE_CUT_OFF " to account for potential empty togglebox positions up to next whole column
int toggle_box_array[MAX_NUMBER_OF_OPTION_TOGGLES]; // index = option position on screen value = game_option or state
/////////////////////////////////
//
// Function ProtoTypes
//
/////////////////////////////////
BOOLEAN EnterScreen();
void RenderScreen();
void ExitScreen();
void HandleScreen();
void GetUserInput();
void SetToggleBoxes();
void SetExitScreen(UINT32 uiExitScreen);
void NextPage();
void PreviousPage();
void ConfirmQuitToMainMenuMessageBoxCallBack(UINT8 bExitValue);
void HandleOptionToggle(UINT8 Button_UserData_0, UINT8 Button_UserData_1, BOOLEAN fState, BOOLEAN fDown, BOOLEAN fPlaySound);
void HandleHighLightedText(BOOLEAN fHighLight);
void DrawLeftPanel();
/////////////////////////////////
//
// Code
//
/////////////////////////////////
UINT32 Init()
{
//Set so next time we come in, we can set up
gfFeaturesScreenEntry = TRUE;
//init rules and paging extent
Establish_Features_Screen_Rules();
Build_Features_List_Reinterpretation(); //need to calc paging max before next/prev button creation
return(TRUE);
}
UINT32 Handle()
{
StartFrameBufferRender();
if (gfFeaturesScreenEntry)
{
EnterScreen();
gfFeaturesScreenEntry = FALSE;
gfFeaturesScreenExit = FALSE;
gfRedrawFeaturesScreen = TRUE;
RenderScreen();
//Blit the background to the save buffer
BlitBufferToBuffer(guiRENDERBUFFER, guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
InvalidateRegion(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
}
RestoreBackgroundRects();
GetUserInput();
RenderScreen();
HandleScreen();
if (gfRedrawFeaturesScreen)
{
RenderButtons();
gfRedrawFeaturesScreen = FALSE;
}
// render buttons marked dirty
MarkButtonsDirty();
RenderButtons();
// ATE: Put here to save RECTS before any fast help being drawn...
SaveBackgroundRects();
RenderButtonsFastHelp();
ExecuteBaseDirtyRectQueue();
EndFrameBufferRender();
if (gfFeaturesScreenExit)
{
ExitScreen();
gfFeaturesScreenExit = FALSE;
gfFeaturesScreenEntry = TRUE;
UnPauseGame();
}
return(guiFeaturesScreen);
}
UINT32 Shutdown()
{
return(TRUE);
}
void Establish_Features_Screen_Rules(void)
{
UINT16 counter;
// ary-05/05/2009 : note : pre-emptive definition of "game options render state". Show/Hide/etc options on option screen.
// : note : enum of states possible :
// : note : state -2 = is a state defined later, after rules build-up, and denotes the unused spots that exceed the final page.
// : note : state -1 = used in toggle_box_array, after rules build-up. and denotes the unused spots that are within last page.
// : note : state 0 = skip this option, consider it to be non-existant.. do not render..
// : note : state 1 = normal, default
// : note : state 2 = text only, no box, no option to toggle, a "header/divider" type rendering
//Re-init toggle_box_feature_rules[]
for (counter = 0; counter < NUM_FEATURE_FLAGS; counter++)
{
//this loop will re-initialize toggle_box_feature_rules[counter1] to "display as normally" state
toggle_box_feature_rules[counter] = 1;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
////// begining of features content rules ////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
}
void Build_Features_List_Reinterpretation(void)
{
// This function fills out a recast of gGameSettings.fOptions[],
// it differs by constraint foun in Establish_Features_Screen_Rules()
INT16 counter1, counter2, index_of_last_valid_option;
for (counter1 = 0; counter1 < (NUM_FEATURE_FLAGS + OPT_FIRST_COLUMN_TOGGLE_CUT_OFF); counter1++)
{
toggle_box_gGameSettings_recast[counter1] = -2;
}
index_of_last_valid_option = 0; //track where inside the recast we ran out of actual options,
//we then pad the rest with -1's
//also, this is the basis for column counting
// ary-05/05/2009 : counter1 represents the position inside toggle_box_gGameSettings_recast[], we dont skip these until there are no more options
// : counter2 represents the position inside gGameSettings.fOptions[], skip invalids until valid or NUM_FEATURE_FLAGS
counter2 = 0; // init prior to the loop
for (counter1 = 0; counter1 < NUM_FEATURE_FLAGS; counter1++)
{
for (; counter2 < NUM_FEATURE_FLAGS; )
{
if (toggle_box_feature_rules[counter2]) // might be change to bit_vect, or some other mechanic, but for only 0 is not rendered
{
toggle_box_gGameSettings_recast[counter1] = counter2;
index_of_last_valid_option = counter1;
counter2++;
break;
}
counter2++;
}
}
// pick up final tail of toggle box up to the next whole column
if ((index_of_last_valid_option + 1) % OPT_FIRST_COLUMN_TOGGLE_CUT_OFF)
{
Max_Number_Of_Pages = ((index_of_last_valid_option + 1) / OPT_FIRST_COLUMN_TOGGLE_CUT_OFF) + 1;
for (counter1 = (index_of_last_valid_option + 1);
counter1 < (Max_Number_Of_Pages * OPT_FIRST_COLUMN_TOGGLE_CUT_OFF);
counter1++)
{
toggle_box_gGameSettings_recast[counter1] = -1;
}
}
else
{
Max_Number_Of_Pages = ((index_of_last_valid_option + 1) / OPT_FIRST_COLUMN_TOGGLE_CUT_OFF);
// no tail to fill out, index_of_last_valid_option is the last option up to a whole column
}
}
void Create_Toggle_Buttons(void)
{
UINT16 counter1;
UINT16 usPosY = 0, usBoxPosX, usTextPosX;
UINT16 usTextWidth, usTextHeight;
//
// Toggle Boxes
//
// Build up a set of options toggles for render and callbacks. and remember set for deletion of set.
//
// main events:
// fill toggle_box_feature_rules[] (content rules), and global state after conditions have been setup
// fill toggle_box_array[], with options based on content rule, or global rules
// show check_box images and text, create mouse regions, based on toggle_box_array[]
// see Destroy_Toggle_Buttons() for handling of deletion (this is all setup to prevent deletion of uncreated regions)
/////////////////////////////////////////////////////////////////////////////////////////////////////////
Establish_Features_Screen_Rules();
Build_Features_List_Reinterpretation(); // based on rules, build a options_screen version of gGameSetting[], and derive max_pages
// at this point we have an array that describes how the toggle boxes will be handled
// only thing left now is to describe the array of toggle_boxes that is currently about to be displayed on screen
// this should be easy enough, just offset into toggle_box_gGameSettings_recast, and direct copy into toggle_box_array
Current_First_Option_Index = OptionsList_Column_Offset * OPT_FIRST_COLUMN_TOGGLE_CUT_OFF;
for (counter1 = 0; counter1 < MAX_NUMBER_OF_OPTION_TOGGLES; counter1++)
{
//counter1 represents index within toggle_box_array, we have to handle each one
toggle_box_array[counter1] = toggle_box_gGameSettings_recast[counter1 + Current_First_Option_Index];
}
// at this point toggle_box_array has been built properly to content rules.
// now it is time to create/render/keep track of the toggle box options
usTextHeight = GetFontHeight(OPT_MAIN_FONT);
for (counter1 = 0; counter1 < MAX_NUMBER_OF_OPTION_TOGGLES; counter1++)
{
// skip creating toggle box for cases : no option , option supression
if (toggle_box_array[counter1] < 0) // skip every thing for -1
{
continue;
}
if (toggle_box_feature_rules[toggle_box_array[counter1]] == 2) //skip creating the toggle box | mouse regions
{ // this case isnt creating toggle box, but is still using positions on the list, so adjust the graphics cursor
// init or re-init base points of where graphics/text/regions are going to be placed
if (counter1 % OPT_FIRST_COLUMN_TOGGLE_CUT_OFF == 0)
{
//reset the vertical position
usPosY = OPT_TOGGLE_BOX_FIRST_COLUMN_START_Y;
}
//skip over vertical portion
usPosY += OPT_GAP_BETWEEN_TOGGLE_BOXES;
//init/reset horizontal
if (counter1 < OPT_FIRST_COLUMN_TOGGLE_CUT_OFF)
{
usBoxPosX = OPT_TOGGLE_BOX_FIRST_COLUMN_X;
usTextPosX = OPT_TOGGLE_BOX_FIRST_COL_TEXT_X;
}
else
{
usBoxPosX = OPT_TOGGLE_BOX_SECOND_COLUMN_X;
usTextPosX = OPT_TOGGLE_BOX_SECOND_TEXT_X;
}
continue;
}
// init or re-init base points of where graphics/text/regions are going to be placed
if (counter1 % OPT_FIRST_COLUMN_TOGGLE_CUT_OFF == 0)
{
//reset the vertical position
usPosY = OPT_TOGGLE_BOX_FIRST_COLUMN_START_Y;
}
if (counter1 < OPT_FIRST_COLUMN_TOGGLE_CUT_OFF)
{
usBoxPosX = OPT_TOGGLE_BOX_FIRST_COLUMN_X;
usTextPosX = OPT_TOGGLE_BOX_FIRST_COL_TEXT_X;
}
else
{
usBoxPosX = OPT_TOGGLE_BOX_SECOND_COLUMN_X;
usTextPosX = OPT_TOGGLE_BOX_SECOND_TEXT_X;
}
// here is the point when the graphical toggle is drawn and associated with a mouse region
//Check box ID stored to guiFeaturesToggles[] by toggle option
guiFeaturesToggles[counter1] = CreateCheckBoxButton(usBoxPosX, usPosY,
"INTERFACE\\OptionsCheckBoxes_12x12.sti",
MSYS_PRIORITY_HIGH + 10,
BtnOptionsTogglesCallback);
//set the toggle box's UserData[0] to the toggle_box index (which toggle box it is)
//set the toggle box's UserData[1] to the option's index (which option the toggle box represents)
MSYS_SetBtnUserData(guiFeaturesToggles[counter1], 0, counter1);
MSYS_SetBtnUserData(guiFeaturesToggles[counter1], 1, toggle_box_array[counter1]);
usTextWidth = StringPixLength(z113FeaturesToggleText[toggle_box_array[counter1]], OPT_MAIN_FONT);
if (usTextWidth > OPT_TOGGLE_BOX_TEXT_WIDTH)
{
//Get how many lines will be used to display the string, without displaying the string
UINT8 ubNumLines = (UINT8)(DisplayWrappedString(0, 0, OPT_TOGGLE_BOX_TEXT_WIDTH, 2, OPT_MAIN_FONT, OPT_HIGHLIGHT_COLOR,
z113FeaturesToggleText[toggle_box_array[counter1]], FONT_MCOLOR_BLACK, TRUE,
LEFT_JUSTIFIED | DONT_DISPLAY_TEXT) / GetFontHeight(OPT_MAIN_FONT));
usTextWidth = OPT_TOGGLE_BOX_TEXT_WIDTH;
//Create mouse regions for the option toggle text
MSYS_DefineRegion(&gSelectedOptionTextRegion[counter1], usBoxPosX + 13, usPosY,
(usTextPosX + usTextWidth), (UINT16)(usPosY + usTextHeight * ubNumLines), MSYS_PRIORITY_HIGH,
CURSOR_NORMAL, SelectedOptionTextRegionMovementCallBack, SelectedOptionTextRegionCallBack);
MSYS_AddRegion(&gSelectedOptionTextRegion[counter1]);
//set the text's region's UserData[0] to the toggle_box index (which toggle box it is)
//set the text's region's UserData[1] to the option's index (which option the toggle box represents)
MSYS_SetRegionUserData(&gSelectedOptionTextRegion[counter1], 0, counter1);
MSYS_SetRegionUserData(&gSelectedOptionTextRegion[counter1], 1, toggle_box_array[counter1]);
}
else
{
//Create mouse regions for the option toggle text
MSYS_DefineRegion(&gSelectedOptionTextRegion[counter1], usBoxPosX + 13, usPosY,
(usTextPosX + usTextWidth), (UINT16)(usPosY + usTextHeight), MSYS_PRIORITY_HIGH,
CURSOR_NORMAL, SelectedOptionTextRegionMovementCallBack, SelectedOptionTextRegionCallBack);
MSYS_AddRegion(&gSelectedOptionTextRegion[counter1]);
//set the text's region's UserData[0] to the toggle_box index (which toggle box it is)
//set the text's region's UserData[1] to the option's index (which option the toggle box represents)
MSYS_SetRegionUserData(&gSelectedOptionTextRegion[counter1], 0, counter1);
MSYS_SetRegionUserData(&gSelectedOptionTextRegion[counter1], 1, toggle_box_array[counter1]);
}
SetRegionFastHelpText(&gSelectedOptionTextRegion[counter1], z113FeaturesHelpText[toggle_box_array[counter1]]);
SetButtonFastHelpText(guiFeaturesToggles[counter1], z113FeaturesHelpText[toggle_box_array[counter1]]);
usPosY += OPT_GAP_BETWEEN_TOGGLE_BOXES;
}
Buttons_Exist_State = 1; // ok check boxes now exist, its safe to allow text highlights
}
void Destroy_Toggle_Buttons(void)
{
UINT8 counter1;
Buttons_Exist_State = 0; // set this to off, prevents HandleScreen() from causing a CTD when tring to
// higlight text for non-existing checkboxes
//Remove the toggle buttons
for (counter1 = 0; counter1 < MAX_NUMBER_OF_OPTION_TOGGLES; counter1++)
{
if (toggle_box_array[counter1] == -1)
{
// dont delete non existing buttons
continue;
}
if (toggle_box_feature_rules[toggle_box_array[counter1]] == 2)
{
// dont delete non existing buttons
continue;
}
RemoveButton(guiFeaturesToggles[counter1]);
MSYS_RemoveRegion(&gSelectedOptionTextRegion[counter1]);
}
}
BOOLEAN EnterScreen()
{
VOBJECT_DESC VObjectDesc;
//if we are coming from mapscreen
if (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN)
{
guiTacticalInterfaceFlags &= ~INTERFACE_MAPSCREEN;
gfEnteredFromMapScreen = TRUE;
}
// Stop ambients...
StopAmbients();
guiFeaturesScreen = FEATURES_SCREEN;
if (gfExitFeaturesDueToMessageBox)
{
gfRedrawFeaturesScreen = TRUE;
gfExitFeaturesDueToMessageBox = FALSE;
return(TRUE);
}
gfExitFeaturesDueToMessageBox = FALSE;
// load the options screen background graphic and add it
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
FilenameForBPP("INTERFACE\\OptionScreenBase.sti", VObjectDesc.ImageFile);
CHECKF(AddVideoObject(&VObjectDesc, &guiFeaturesBackGroundImage));
// load button, title graphic and add it
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
GetMLGFilename(VObjectDesc.ImageFile, MLG_OPTIONHEADER);
CHECKF(AddVideoObject(&VObjectDesc, &guiFeaturesAddOnImages));
//Save game button
giOptionsButtonImages = LoadButtonImage("INTERFACE\\OptionScreenAddons2.sti", -1, 2, -1, 3, -1);
guiOptGotoSaveGameBtn = CreateIconAndTextButton(giOptionsButtonImages, zOptionsText[OPT_SAVE_GAME], OPT_BUTTON_FONT2,
OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW,
OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
OPT_SAVE_BTN_X, OPT_SAVE_BTN_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnOptGotoSaveGameCallback);
SpecifyDisabledButtonStyle(guiOptGotoSaveGameBtn, DISABLED_STYLE_HATCHED);
if (guiPreviousScreen == MAINMENU_SCREEN || !CanGameBeSaved() || guiPreviousScreen == GAME_INIT_OPTIONS_SCREEN)
{
DisableButton(guiOptGotoSaveGameBtn);
}
//Load game button
giGotoLoadBtnImage = UseLoadedButtonImage(giOptionsButtonImages, -1, 2, -1, 3, -1);
guiOptGotoLoadGameBtn = CreateIconAndTextButton(giGotoLoadBtnImage, zOptionsText[OPT_LOAD_GAME], OPT_BUTTON_FONT2,
OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW,
OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
OPT_LOAD_BTN_X, OPT_LOAD_BTN_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnOptGotoLoadGameCallback);
//Quit to main menu button
giQuitBtnImage = UseLoadedButtonImage(giOptionsButtonImages, -1, 2, -1, 3, -1);
guiQuitButton = CreateIconAndTextButton(giQuitBtnImage, zOptionsText[OPT_MAIN_MENU], OPT_BUTTON_FONT2,
OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW,
OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
OPT_QUIT_BTN_X, OPT_QUIT_BTN_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnOptQuitCallback);
SpecifyDisabledButtonStyle(guiQuitButton, DISABLED_STYLE_HATCHED);
// Options Button
giOptionsBtnImage = UseLoadedButtonImage(giOptionsButtonImages, -1, 2, -1, 3, -1);
guiOptionsButton = CreateIconAndTextButton(giOptionsBtnImage, zOptionsText[OPT_OPTIONS], OPT_BUTTON_FONT2,
OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW,
OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
OPT_SWAP_BTN_X, OPT_SWAP_BTN_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnOptionsCallback);
// ary-05/05/2009 : need more option screen toggles : Add in buttons that allow for options column paging
// Previous Column of options
giOptPrevBtnImage = UseLoadedButtonImage(giOptionsButtonImages, -1, 2, -1, 3, -1);
guiOptPrevButton = CreateIconAndTextButton(giOptPrevBtnImage, zOptionsText[OPT_PREV], OPT_BUTTON_FONT2,
OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW,
OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
OPT_PREV_BTN_X, OPT_PREV_BTN_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnOptPrevCallback);
SpecifyDisabledButtonStyle(guiOptPrevButton, DISABLED_STYLE_HATCHED);
if (OptionsList_Column_Offset == 0)
{
DisableButton(guiOptPrevButton);
}
// Next Column of options
giOptNextBtnImage = UseLoadedButtonImage(giOptionsButtonImages, -1, 2, -1, 3, -1);
guiOptNextButton = CreateIconAndTextButton(giOptNextBtnImage, zOptionsText[OPT_NEXT], OPT_BUTTON_FONT2,
OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW,
OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
OPT_NEXT_BTN_X, OPT_NEXT_BTN_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnOptNextCallback);
SpecifyDisabledButtonStyle(guiOptNextButton, DISABLED_STYLE_HATCHED);
if (OptionsList_Column_Offset >= (Max_Number_Of_Pages - 2))// ary-05/05/2009 : "Max_Number_Of_Pages-2" becaues each "page" = 2 "columns"
{
DisableButton(guiOptNextButton);
}
//Done button
giDoneBtnImage = UseLoadedButtonImage(giOptionsButtonImages, -1, 2, -1, 3, -1);
guiDoneButton = CreateIconAndTextButton(giDoneBtnImage, zOptionsText[OPT_DONE], OPT_BUTTON_FONT2,
OPT_BUTTON_ON_COLOR, DEFAULT_SHADOW,
OPT_BUTTON_OFF_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
OPT_DONE_BTN_X, OPT_DONE_BTN_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnDoneCallback);
Create_Toggle_Buttons(); // ary-05/05/2009 : moved block out of func
//Create a mouse region so when the user leaves a togglebox text region we can detect it then unselect the region
MSYS_DefineRegion(&gSelectedToggleBoxAreaRegion, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, MSYS_PRIORITY_NORMAL,
CURSOR_NORMAL, SelectedToggleBoxAreaRegionMovementCallBack, MSYS_NO_CALLBACK);
MSYS_AddRegion(&gSelectedToggleBoxAreaRegion);
//Remove the mouse region over the clock
RemoveMouseRegionForPauseOfClock();
//Draw the screen
gfRedrawFeaturesScreen = TRUE;
//Set the screen toggle boxes
SetToggleBoxes();
DisableScrollMessages();
//reset
gbHighLightedOptionText = -1;
return(TRUE);
}
void ExitScreen()
{
if (gfExitFeaturesDueToMessageBox)
{
gfFeaturesScreenExit = FALSE;
if (!gfExitFeaturesAfterMessageBox)
return;
gfExitFeaturesAfterMessageBox = FALSE;
gfExitFeaturesDueToMessageBox = FALSE;
}
//The save the current settings to disk
SaveFeatureFlags();
if (guiFeaturesScreen == GAME_SCREEN)
{
EnterTacticalScreen();
}
if (guiFeaturesScreen == SAVE_LOAD_SCREEN && guiPreviousScreen == MAINMENU_SCREEN)
{
giMAXIMUM_NUMBER_OF_PLAYER_SLOTS = CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS;
InitDependingGameStyleOptions();
}
RemoveButton(guiOptGotoSaveGameBtn);
RemoveButton(guiOptGotoLoadGameBtn);
RemoveButton(guiQuitButton);
RemoveButton(guiOptionsButton);
RemoveButton(guiOptNextButton);// ary-05/05/2009 : more option screen toggles
RemoveButton(guiOptPrevButton);
RemoveButton(guiDoneButton);
UnloadButtonImage(giOptionsButtonImages);
UnloadButtonImage(giGotoLoadBtnImage);
UnloadButtonImage(giQuitBtnImage);
UnloadButtonImage(giOptionsBtnImage);
UnloadButtonImage(giOptNextBtnImage);// ary-05/05/2009 : more option screen toggles
UnloadButtonImage(giOptPrevBtnImage);
UnloadButtonImage(giDoneBtnImage);
DeleteVideoObjectFromIndex(guiFeaturesBackGroundImage);
DeleteVideoObjectFromIndex(guiFeaturesAddOnImages);
Destroy_Toggle_Buttons(); // ary-05/05/2009 : moved block out of func
MSYS_RemoveRegion(&gSelectedToggleBoxAreaRegion);
//if we are coming from mapscreen
if (gfEnteredFromMapScreen)
{
gfEnteredFromMapScreen = FALSE;
guiTacticalInterfaceFlags |= INTERFACE_MAPSCREEN;
}
}
void HandleScreen()
{
HandleHighLightedText(TRUE);
}
void RenderScreen()
{
HVOBJECT hPixHandle;
UINT16 usPosY = 0, usPosX;
UINT16 usWidth = 0;
UINT8 count;
CHAR16 sPage[60];
//Get and display the background image
if (GetVideoObject(&hPixHandle, guiFeaturesBackGroundImage))
BltVideoObject(FRAME_BUFFER, hPixHandle, 0, iScreenWidthOffset, iScreenHeightOffset, VO_BLT_SRCTRANSPARENCY, NULL);
//Get and display the titla image
if (GetVideoObject(&hPixHandle, guiFeaturesAddOnImages))
{
BltVideoObject(FRAME_BUFFER, hPixHandle, 0, iScreenWidthOffset, iScreenHeightOffset, VO_BLT_SRCTRANSPARENCY, NULL);
BltVideoObject(FRAME_BUFFER, hPixHandle, 1, iScreenWidthOffset, iScreenHeightOffset + 434, VO_BLT_SRCTRANSPARENCY, NULL);
}
DrawLeftPanel();
//
// Text for the toggle boxes
//
//Display the First column of toggles
for (count = 0; count < MAX_NUMBER_OF_OPTION_TOGGLES; count++)
{
if (toggle_box_array[count] == -1)
{
break;
}// no text for non existing buttons
//setup base points of where graphics/text/regions are going to be placed
if (count % OPT_FIRST_COLUMN_TOGGLE_CUT_OFF == 0)
{
//reset the vertical position
usPosY = OPT_TOGGLE_BOX_FIRST_COLUMN_START_Y + OPT_TOGGLE_TEXT_OFFSET_Y;
}
if (count < OPT_FIRST_COLUMN_TOGGLE_CUT_OFF)
{
usPosX = OPT_TOGGLE_BOX_FIRST_COL_TEXT_X;
}
else
{
usPosX = OPT_TOGGLE_BOX_SECOND_TEXT_X;
}
usWidth = StringPixLength(z113FeaturesToggleText[toggle_box_array[count]], OPT_MAIN_FONT);
// set the colour of the toggle box text
UINT8 fontColor = (count == 0 && OptionsList_Column_Offset == 0) || gGameSettings.fFeatures[FF_FEATURES_SCREEN] ?
OPT_MAIN_COLOR : FONT_GRAY7;
//if the string is going to wrap, move the string up a bit
if (usWidth > OPT_TOGGLE_BOX_TEXT_WIDTH)
DisplayWrappedString(usPosX, usPosY, OPT_TOGGLE_BOX_TEXT_WIDTH, 2, OPT_MAIN_FONT, fontColor,
z113FeaturesToggleText[toggle_box_array[count]], FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED);
else
DrawTextToScreen(z113FeaturesToggleText[toggle_box_array[count]], usPosX, usPosY, 0,
OPT_MAIN_FONT, fontColor, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED);
usPosY += OPT_GAP_BETWEEN_TOGGLE_BOXES;
}
//Display the option page numbers
swprintf(sPage, L"%d / %d", OptionsList_Column_Offset + 1, max(1, Max_Number_Of_Pages - 1));
DisplayWrappedString(OPT_PAGE_X, OPT_PAGE_Y, OPT_SLIDER_TEXT_WIDTH, 2, OPT_BUTTON_FONT2, OPT_MAIN_COLOR,
sPage, FONT_MCOLOR_BLACK, FALSE, RIGHT_JUSTIFIED);
//Set the screen toggle boxes
SetToggleBoxes();
InvalidateRegion(OPTIONS__TOP_LEFT_X, OPTIONS__TOP_LEFT_Y, OPTIONS__BOTTOM_RIGHT_X, OPTIONS__BOTTOM_RIGHT_Y);
}
void GetUserInput()
{
InputAtom Event;
POINT MousePos;
GetCursorPos(&MousePos);
ScreenToClient(ghWindow, &MousePos); // In window coords!
while (DequeueSpecificEvent(&Event, KEY_DOWN | KEY_UP | KEY_REPEAT))
{
if (!HandleTextInput(&Event) && Event.usEvent == KEY_DOWN)
{
switch (Event.usParam)
{
case ESC:
SetExitScreen(guiPreviousScreen);
break;
//Enter the save game screen
case 's':
case 'S':
//if the save game button isnt disabled
if (ButtonList[guiOptGotoSaveGameBtn]->uiFlags & BUTTON_ENABLED)
{
SetExitScreen(SAVE_LOAD_SCREEN);
gfSaveGame = TRUE;
}
break;
//Enter the Load game screen
case 'l':
case 'L':
SetExitScreen(SAVE_LOAD_SCREEN);
gfSaveGame = FALSE;
break;
// toggle between features and options screen
case TAB:
SetExitScreen(OPTIONS_SCREEN);
break;
// page left
case 'a':
case 'A':
case LEFTARROW:
PreviousPage();
break;
// page right
case 'd':
case 'D':
case RIGHTARROW:
NextPage();
break;
#ifdef JA2TESTVERSION
case 'r':
gfRedrawFeaturesScreen = TRUE;
break;
case 'i':
InvalidateRegion(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
break;
//Test keys
case 'y':
{
static UINT32 uiTest2 = NO_SAMPLE;
if (!SoundIsPlaying(uiTest2))
uiTest2 = PlayJA2SampleFromFile("Sounds\\RAID Dive.wav", RATE_11025, HIGHVOLUME, 1, MIDDLEPAN);
}
break;
case 't':
{
/*
{
CHAR8 zCdromRootDrive[512];
HWFILE hFile;
if( !GetCdromLocationFromIniFile( zCdromRootDrive ) )
return;
//Check if a file exists on the cdrom
sprintf( zCdromRootDrive, "%sData\\NPC_Speech.slf", zCdromRootDrive );
// if( FileExistsNoDB( zCdromRootDrive ) )
hFile = FileOpen( zCdromRootDrive, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE );
if( hFile != 0 )
{
FileClose( hFile );
sprintf( zCdromRootDrive, "%sData\\NPC_Speech.slf", zCdromRootDrive );
}
else
{
sprintf( zCdromRootDrive, "%sData\\NPC_Speech.slf", zCdromRootDrive );
}
uiLastTimeToCheckCDromDrive = GetJA2Clock();
}
*/
}
break;
case 'z':
SetErrorMode(SEM_FAILCRITICALERRORS);
break;
case 'q':
// ShouldMercSayPrecedentToRepeatOneSelf( 11, 99 );
break;
#endif
}
}
}
// mousewheel input
if (OptionsList_Column_Offset > 0)
{
BOOL act = FALSE;
// check general screen mouseregion
if (gSelectedToggleBoxAreaRegion.WheelState > 0)
{
act = TRUE;
}
// check toggle box mouseregions
for (int i = 0; i < MAX_NUMBER_OF_OPTION_TOGGLES; ++i)
{
if (act) break;
if (gSelectedOptionTextRegion[i].WheelState > 0)
{
act = TRUE;
}
}
if (act) PreviousPage();
}
if (OptionsList_Column_Offset < Max_Number_Of_Pages-2)
{
BOOL act = FALSE;
// check general screen mouseregion
if (gSelectedToggleBoxAreaRegion.WheelState < 0)
{
act = TRUE;
}
// check toggle box mouseregions
for (int i = 0; i < MAX_NUMBER_OF_OPTION_TOGGLES; ++i)
{
if (act) break;
if (gSelectedOptionTextRegion[i].WheelState < 0)
{
act = TRUE;
}
}
if (act) NextPage();
}
}
void NextPage()
{
ExitScreen();
OptionsList_Column_Offset++;
if (OptionsList_Column_Offset >= Max_Number_Of_Pages - 1) // ary-05/05/2009 : Max_Number_Of_Pages
OptionsList_Column_Offset = (Max_Number_Of_Pages - 2);
Init();
}
void PreviousPage()
{
ExitScreen();
OptionsList_Column_Offset--;
if(OptionsList_Column_Offset < 0)
OptionsList_Column_Offset = 0;
Init();
}
void SetExitScreen(UINT32 uiExitScreen)
{
OptionsList_Column_Offset = 0; // reset the pager till next visit
guiFeaturesScreen = uiExitScreen;
gfFeaturesScreenExit = TRUE;
}
void BtnOptGotoSaveGameCallback(GUI_BUTTON* btn, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
btn->uiFlags |= BUTTON_CLICKED_ON;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
SetExitScreen(SAVE_LOAD_SCREEN);
gfSaveGame = TRUE;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
}
void BtnOptGotoLoadGameCallback(GUI_BUTTON* btn, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
btn->uiFlags |= BUTTON_CLICKED_ON;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
SetExitScreen(SAVE_LOAD_SCREEN);
gfSaveGame = FALSE;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
}
void BtnOptQuitCallback(GUI_BUTTON* btn, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
btn->uiFlags |= BUTTON_CLICKED_ON;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
//Confirm the Exit to the main menu screen
DoMessageBox(MSG_BOX_BASIC_STYLE, zOptionsText[OPT_RETURN_TO_MAIN], FEATURES_SCREEN, MSG_BOX_FLAG_YESNO,
ConfirmQuitToMainMenuMessageBoxCallBack);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
}
void BtnOptionsCallback(GUI_BUTTON* btn, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
btn->uiFlags |= BUTTON_CLICKED_ON;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
SetExitScreen(OPTIONS_SCREEN);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
}
// ary-05/05/2009 : need more option screen toggles : Functions for button callbacks
void BtnOptPrevCallback(GUI_BUTTON* btn, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
btn->uiFlags |= BUTTON_CLICKED_ON;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
ExitScreen();
OptionsList_Column_Offset--;
if (OptionsList_Column_Offset < 0) OptionsList_Column_Offset = 0;
Init(); // ary-05/05/2009 : This is important to refresh the screen properly, it stores a new SAVE_BUFFER
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
}
void BtnOptNextCallback(GUI_BUTTON* btn, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
btn->uiFlags |= BUTTON_CLICKED_ON;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
ExitScreen();
OptionsList_Column_Offset++;
if (OptionsList_Column_Offset >= Max_Number_Of_Pages) // ary-05/05/2009 : Max_Number_Of_Pages
OptionsList_Column_Offset = (Max_Number_Of_Pages - 1);
Init(); // ary-05/05/2009 : This is important to refresh the screen properly, it stores a new SAVE_BUFFER
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
}
void BtnDoneCallback(GUI_BUTTON* btn, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
btn->uiFlags |= BUTTON_CLICKED_ON;
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
SetExitScreen(guiPreviousScreen);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
btn->uiFlags &= (~BUTTON_CLICKED_ON);
InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY,
btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY);
}
}
void BtnOptionsTogglesCallback(GUI_BUTTON* btn, INT32 reason)
{
UINT8 Button_UserData_0 = (UINT8)MSYS_GetBtnUserData(btn, 0);// the toggle box
UINT8 Button_UserData_1 = (UINT8)MSYS_GetBtnUserData(btn, 1);// the option
if (reason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
if (btn->uiFlags & BUTTON_CLICKED_ON)
{
HandleOptionToggle(Button_UserData_0, Button_UserData_1, TRUE, FALSE, FALSE);
btn->uiFlags |= BUTTON_CLICKED_ON;
}
else
{
btn->uiFlags &= ~BUTTON_CLICKED_ON;
HandleOptionToggle(Button_UserData_0, Button_UserData_1, FALSE, FALSE, FALSE);
}
}
else if (reason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
if (btn->uiFlags & BUTTON_CLICKED_ON)
{
HandleOptionToggle(Button_UserData_0, Button_UserData_1, TRUE, TRUE, FALSE);
btn->uiFlags |= BUTTON_CLICKED_ON;
}
else
{
btn->uiFlags &= ~BUTTON_CLICKED_ON;
HandleOptionToggle(Button_UserData_0, Button_UserData_1, FALSE, TRUE, FALSE);
}
}
}
void HandleOptionToggle(UINT8 Button_UserData_0, UINT8 Button_UserData_1, BOOLEAN fState, BOOLEAN fDown, BOOLEAN fPlaySound)
{
//Button_UserData_0 = which toggle box within guiFeaturesToggles[Button_UserData_0]
//Button_UserData_1 = which option the toggle box represents
static UINT32 uiOptionToggleSound = NO_SAMPLE;
if (fState)
{
switch (Button_UserData_1)
{
// FF_DROP_ALL and FF_DROP_ALL_DAMAGED are mutually exclusive
case FF_DROP_ALL:
gGameSettings.fFeatures[FF_DROP_ALL_DAMAGED] = FALSE;
break;
case FF_DROP_ALL_DAMAGED:
gGameSettings.fFeatures[FF_DROP_ALL] = FALSE;
break;
// counterattack/aggressive AI mutual exclusive toggles
case FF_AGGRESSIVE_STRATEGIC_AI:
gGameSettings.fFeatures[FF_AGGRESSIVE_STRATEGIC_AI_2] = FALSE;
break;
case FF_AGGRESSIVE_STRATEGIC_AI_2:
gGameSettings.fFeatures[FF_AGGRESSIVE_STRATEGIC_AI] = FALSE;
break;
// FF_MILITIA_USE_SECTOR_EQUIPMENT and FF_MILITIA_REQUIRE_RESOURCES are mutually exclusive
case FF_MILITIA_REQUIRE_RESOURCES:
gGameSettings.fFeatures[FF_MILITIA_USE_SECTOR_EQUIPMENT] = FALSE;
break;
case FF_MILITIA_USE_SECTOR_EQUIPMENT:
gGameSettings.fFeatures[FF_MILITIA_REQUIRE_RESOURCES] = FALSE;
break;
// enemy role features
case FF_ENEMY_ROLE_MEDIC:
case FF_ENEMY_ROLE_OFFICER:
case FF_ENEMY_ROLE_GENERAL:
gGameSettings.fFeatures[FF_ENEMY_ROLES] = TRUE;
break;
// dynamic opinions and dialogue
case FF_DYNAMIC_DIALOGUE:
gGameSettings.fFeatures[FF_DYNAMIC_OPINIONS] = TRUE;
break;
// arulco strategic division
case FF_ASD_HELICOPTERS:
gGameSettings.fFeatures[FF_ASD] = TRUE;
break;
// zombies
case FF_ZOMBIE_RAIDS:
gGameSettings.fFeatures[FF_ZOMBIES] = TRUE;
break;
// rain/lightning
case FF_ALLOW_LIGHTNING:
gGameSettings.fFeatures[FF_ALLOW_RAIN] = TRUE;
break;
}
gGameSettings.fFeatures[Button_UserData_1] = TRUE;
if (fDown)
DrawCheckBoxButtonOn(guiFeaturesToggles[Button_UserData_0]);
}
else
{
switch (Button_UserData_1)
{
// enemy role features
case FF_ENEMY_ROLES:
gGameSettings.fFeatures[FF_ENEMY_ROLE_MEDIC] = FALSE;
gGameSettings.fFeatures[FF_ENEMY_ROLE_OFFICER] = FALSE;
gGameSettings.fFeatures[FF_ENEMY_ROLE_GENERAL] = FALSE;
break;
// dynamic opinions and dialogue
case FF_DYNAMIC_OPINIONS:
gGameSettings.fFeatures[FF_DYNAMIC_DIALOGUE] = FALSE;
break;
// arulco strategic division
case FF_ASD:
gGameSettings.fFeatures[FF_ASD_HELICOPTERS] = FALSE;
break;
// zombies
case FF_ZOMBIES:
gGameSettings.fFeatures[FF_ZOMBIE_RAIDS] = FALSE;
break;
// rain/lightning
case FF_ALLOW_RAIN:
gGameSettings.fFeatures[FF_ALLOW_LIGHTNING] = FALSE;
break;
}
gGameSettings.fFeatures[Button_UserData_1] = FALSE;
if (fDown)
DrawCheckBoxButtonOff(guiFeaturesToggles[Button_UserData_0]);
}
//stop the sound if
SoundStop(uiOptionToggleSound);
if (fPlaySound)
{
if (fDown)
{
PlayJA2Sample(BIG_SWITCH3_IN, RATE_11025, BTNVOLUME, 1, MIDDLEPAN);
}
else
{
PlayJA2Sample(BIG_SWITCH3_OUT, RATE_11025, BTNVOLUME, 1, MIDDLEPAN);
}
}
InvalidateRegion(OPTIONS__TOP_LEFT_X, OPTIONS__TOP_LEFT_Y, OPTIONS__BOTTOM_RIGHT_X, OPTIONS__BOTTOM_RIGHT_Y);
}
BOOLEAN DoMessageBoxWithRect(UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UINT32 usFlags,
MSGBOX_CALLBACK ReturnCallback, SGPRect* pCenteringRect)
{
// reset exit mode
gfExitFeaturesDueToMessageBox = TRUE;
// do message box and return
giFeaturesMessageBox = DoMessageBox(ubStyle, zString, uiExitScreen, (usFlags | MSG_BOX_FLAG_USE_CENTERING_RECT),
ReturnCallback, pCenteringRect);
// send back return state
return((giFeaturesMessageBox != -1));
}
BOOLEAN DoMessageBox(UINT8 ubStyle, const STR16 zString, UINT32 uiExitScreen, UINT16 usFlags, MSGBOX_CALLBACK ReturnCallback)
{
SGPRect CenteringRect = { 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 };
// reset exit mode
gfExitFeaturesDueToMessageBox = TRUE;
// do message box and return
giFeaturesMessageBox = DoMessageBox(ubStyle, zString, uiExitScreen, (UINT16)(usFlags | MSG_BOX_FLAG_USE_CENTERING_RECT),
ReturnCallback, &CenteringRect);
// send back return state
return((giFeaturesMessageBox != -1));
}
void ConfirmQuitToMainMenuMessageBoxCallBack(UINT8 bExitValue)
{
// yes, Quit to main menu
if (bExitValue == MSG_BOX_RETURN_YES)
{
gfEnteredFromMapScreen = FALSE;
gfExitFeaturesAfterMessageBox = TRUE;
SetExitScreen(MAINMENU_SCREEN);
if (is_networked)
{
// haydent
server_disconnect();
client_disconnect();
}
//We want to reinitialize the game
ReStartingGame();
}
else
{
gfExitFeaturesAfterMessageBox = FALSE;
gfExitFeaturesDueToMessageBox = FALSE;
}
}
void SetToggleBoxes()
{
UINT8 counter;
for (counter = 0; counter < MAX_NUMBER_OF_OPTION_TOGGLES; counter++)
{
if (toggle_box_array[counter] == -1)
{
continue;
}//there are no options to set for this toggle_box
if (toggle_box_feature_rules[toggle_box_array[counter]] == 2)
{
continue;
}//there are no options to set for this toggle_box
if (gGameSettings.fFeatures[toggle_box_array[counter]])
ButtonList[guiFeaturesToggles[counter]]->uiFlags |= BUTTON_CLICKED_ON;
else
ButtonList[guiFeaturesToggles[counter]]->uiFlags &= (~BUTTON_CLICKED_ON);
}
}
void SelectedOptionTextRegionCallBack(MOUSE_REGION* pRegion, INT32 iReason)
{
//Region_UserData_0 = which toggle box within guiFeaturesToggles[Button_UserData_0]
//Region_UserData_1 = which option the toggle box represents
UINT8 Region_UserData_0 = (UINT8)MSYS_GetRegionUserData(pRegion, 0);
UINT8 Region_UserData_1 = (UINT8)MSYS_GetRegionUserData(pRegion, 1);
if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
HandleOptionToggle(Region_UserData_0, Region_UserData_1, (BOOLEAN)(!gGameSettings.fFeatures[Region_UserData_1]), FALSE, TRUE);
InvalidateRegion(pRegion->RegionTopLeftX, pRegion->RegionTopLeftY,
pRegion->RegionBottomRightX, pRegion->RegionBottomRightY);
}
else if (iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN)//iReason & MSYS_CALLBACK_REASON_LBUTTON_REPEAT ||
{
if (gGameSettings.fFeatures[Region_UserData_1])
{
HandleOptionToggle(Region_UserData_0, Region_UserData_1, TRUE, TRUE, TRUE);
}
else
{
HandleOptionToggle(Region_UserData_0, Region_UserData_1, FALSE, TRUE, TRUE);
}
}
}
void SelectedOptionTextRegionMovementCallBack(MOUSE_REGION* pRegion, INT32 reason)
{
INT8 Region_UserData_0 = (INT8)MSYS_GetRegionUserData(pRegion, 0);
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
HandleHighLightedText(FALSE);
gbHighLightedOptionText = -1;
InvalidateRegion(pRegion->RegionTopLeftX, pRegion->RegionTopLeftY,
pRegion->RegionBottomRightX, pRegion->RegionBottomRightY);
}
else if (reason & MSYS_CALLBACK_REASON_GAIN_MOUSE)
{
gbHighLightedOptionText = Region_UserData_0;
InvalidateRegion(pRegion->RegionTopLeftX, pRegion->RegionTopLeftY,
pRegion->RegionBottomRightX, pRegion->RegionBottomRightY);
}
}
void HandleHighLightedText(BOOLEAN fHighLight)
{
UINT16 usPosX = 0;
UINT16 usPosY = 0;
UINT8 counter;
INT8 bHighLight = -1;
UINT16 usWidth;
static INT8 bLastRegion = -1;
if (!Buttons_Exist_State)
{
// there are no buttons/text to highlight, time to leave before any attempt to lookup non-existing pointer data
gbHighLightedOptionText = -1;
return;
}
if (gbHighLightedOptionText == -1)
fHighLight = FALSE;
//if the user has the mouse in one of the checkboxes
for (counter = 0; counter < MAX_NUMBER_OF_OPTION_TOGGLES; counter++)
{
if (toggle_box_array[counter] == -1)
{
continue;
}//there are no options to set for this toggle_box
if (toggle_box_feature_rules[toggle_box_array[counter]] == 2)
{
continue;
}//there are no options to set for this toggle_box
if (ButtonList[guiFeaturesToggles[counter]]->Area.uiFlags & MSYS_MOUSE_IN_AREA)
{
gbHighLightedOptionText = counter;
fHighLight = TRUE;
}
}
// If there is a valid section being highlighted
if (gbHighLightedOptionText != -1)
{
bLastRegion = gbHighLightedOptionText;
}
bHighLight = gbHighLightedOptionText;
if (bLastRegion != -1 && gbHighLightedOptionText == -1)
{
fHighLight = FALSE;
bHighLight = bLastRegion;
bLastRegion = -1;
}
if (bHighLight != -1)
{
if (bHighLight < OPT_FIRST_COLUMN_TOGGLE_CUT_OFF)
{
usPosX = OPT_TOGGLE_BOX_FIRST_COL_TEXT_X;
usPosY = OPT_TOGGLE_BOX_FIRST_COLUMN_START_Y + OPT_TOGGLE_TEXT_OFFSET_Y +
(bHighLight * OPT_GAP_BETWEEN_TOGGLE_BOXES);
}
else
{
usPosX = OPT_TOGGLE_BOX_SECOND_TEXT_X;
usPosY = OPT_TOGGLE_BOX_SECOND_COLUMN_START_Y + OPT_TOGGLE_TEXT_OFFSET_Y +
((bHighLight - OPT_FIRST_COLUMN_TOGGLE_CUT_OFF) * OPT_GAP_BETWEEN_TOGGLE_BOXES);
}
usWidth = StringPixLength(z113FeaturesToggleText[toggle_box_array[bHighLight]], OPT_MAIN_FONT);
//if the string is going to wrap, move the string up a bit
if (usWidth > OPT_TOGGLE_BOX_TEXT_WIDTH)
{
if (fHighLight)
DisplayWrappedString(usPosX, usPosY, OPT_TOGGLE_BOX_TEXT_WIDTH, 2, OPT_MAIN_FONT, OPT_HIGHLIGHT_COLOR,
z113FeaturesToggleText[toggle_box_array[bHighLight]], FONT_MCOLOR_BLACK, TRUE, LEFT_JUSTIFIED);
else
DisplayWrappedString(usPosX, usPosY, OPT_TOGGLE_BOX_TEXT_WIDTH, 2, OPT_MAIN_FONT, OPT_MAIN_COLOR,
z113FeaturesToggleText[toggle_box_array[bHighLight]], FONT_MCOLOR_BLACK, TRUE, LEFT_JUSTIFIED);
}
else
{
if (fHighLight)
DrawTextToScreen(z113FeaturesToggleText[toggle_box_array[bHighLight]], usPosX, usPosY, 0,
OPT_MAIN_FONT, OPT_HIGHLIGHT_COLOR, FONT_MCOLOR_BLACK, TRUE, LEFT_JUSTIFIED);
else
DrawTextToScreen(z113FeaturesToggleText[toggle_box_array[bHighLight]], usPosX, usPosY, 0,
OPT_MAIN_FONT, OPT_MAIN_COLOR, FONT_MCOLOR_BLACK, TRUE, LEFT_JUSTIFIED);
}
}
}
void SelectedToggleBoxAreaRegionMovementCallBack(MOUSE_REGION* pRegion, INT32 reason)
{
if (reason & MSYS_CALLBACK_REASON_LOST_MOUSE)
{
}
else if (reason & MSYS_CALLBACK_REASON_GAIN_MOUSE)
{
UINT8 counter;
//loop through all the toggle box's and remove the in area flag
for (counter = 0; counter < MAX_NUMBER_OF_OPTION_TOGGLES; counter++)
{
if (toggle_box_array[counter] == -1)
{
continue;
}//there are no options to set for this toggle_box
if (toggle_box_feature_rules[toggle_box_array[counter]] == 2)
{
continue;
}//there are no options to set for this toggle_box
ButtonList[guiFeaturesToggles[counter]]->Area.uiFlags &= ~MSYS_MOUSE_IN_AREA;
}
gbHighLightedOptionText = -1;
InvalidateRegion(pRegion->RegionTopLeftX, pRegion->RegionTopLeftY,
pRegion->RegionBottomRightX, pRegion->RegionBottomRightY);
}
}
void DrawLeftPanel()
{
UINT16 uiPosX, uiPosY;
// need to cover a 180x327 pixel background
uiPosX = OPT_SOUND_FX_TEXT_X - 4;
uiPosY = OPT_SOUND_FX_TEXT_Y - 10;
ColorFillVideoSurfaceArea(FRAME_BUFFER, uiPosX, uiPosY, uiPosX + 180, uiPosY + 327, Get16BPPColor(FROMRGB(0, 0, 0)));
// draw the text
SetFontShadow(FONT_MCOLOR_BLACK);
DisplayWrappedString( iScreenWidthOffset + 36, iScreenHeightOffset + 80, 176, 0, FONT14ARIAL, FONT_MCOLOR_WHITE, z113FeaturesScreenText[ FST_TITLE ], FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
DisplayWrappedString( iScreenWidthOffset + 36, iScreenHeightOffset + 95, 176, 0, FONT10ARIAL, FONT_MCOLOR_LTGRAY, z113FeaturesScreenText[ FST_DESCRIPTION ], FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
CHAR16 text[1000];
swprintf(text, L"%s", gbHighLightedOptionText != -1 ? z113FeaturesPanelText[toggle_box_array[gbHighLightedOptionText]] : z113FeaturesScreenText[FST_HOVER_FOR_MORE_INFO]);
DisplayWrappedString( iScreenWidthOffset + 36, iScreenHeightOffset + 125, 176, 0, FONT12ARIAL, FONT_MCOLOR_WHITE, text, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED );
SetFontShadow(DEFAULT_SHADOW);
}
void SetPreviousScreen(UINT32 screenId, BOOLEAN setOptionsToo)
{
guiPreviousScreen = screenId;
if (setOptionsToo)
SetOptionsPreviousScreen(screenId, FALSE);
}
} // namespace