2022-05-19 01:51:26 -07:00
# include "game.h"
# include "actions.h"
# include "animation.h"
2022-06-19 04:27:29 -07:00
# include "art.h"
2022-05-19 01:51:26 -07:00
# include "automap.h"
# include "character_editor.h"
# include "character_selector.h"
# include "color.h"
# include "combat.h"
# include "combat_ai.h"
# include "core.h"
# include "critter.h"
# include "cycle.h"
# include "db.h"
# include "dbox.h"
# include "debug.h"
# include "display_monitor.h"
# include "draw.h"
# include "electronic_registration.h"
# include "endgame.h"
# include "font_manager.h"
# include "game_config.h"
# include "game_dialog.h"
# include "game_memory.h"
# include "game_mouse.h"
# include "game_movie.h"
# include "game_sound.h"
# include "interface.h"
# include "inventory.h"
# include "item.h"
# include "loadsave.h"
# include "map.h"
# include "memory.h"
# include "movie.h"
# include "movie_effect.h"
# include "object.h"
# include "options.h"
# include "palette.h"
# include "party_member.h"
# include "perk.h"
# include "pipboy.h"
2022-05-28 01:57:32 -07:00
# include "platform_compat.h"
2022-05-19 01:51:26 -07:00
# include "proto.h"
# include "queue.h"
# include "random.h"
# include "scripts.h"
2022-05-25 14:16:20 -07:00
# include "sfall_config.h"
2022-05-19 01:51:26 -07:00
# include "skill.h"
# include "skilldex.h"
# include "stat.h"
# include "text_font.h"
# include "tile.h"
# include "trait.h"
# include "trap.h"
# include "version.h"
# include "window_manager.h"
# include "world_map.h"
2022-05-28 14:22:40 -07:00
# ifdef _WIN32
2022-05-19 01:51:26 -07:00
# include <io.h>
2022-05-28 14:22:40 -07:00
# else
# include <unistd.h> // access
# endif
2022-05-19 01:51:26 -07:00
# include <stdio.h>
2022-05-29 06:40:49 -07:00
# include <string.h>
2022-05-19 01:51:26 -07:00
# define HELP_SCREEN_WIDTH (640)
# define HELP_SCREEN_HEIGHT (480)
# define SPLASH_WIDTH (640)
# define SPLASH_HEIGHT (480)
# define SPLASH_COUNT (10)
2022-06-19 03:18:12 -07:00
static int gameLoadGlobalVars ( ) ;
static int gameTakeScreenshot ( int width , int height , unsigned char * buffer , unsigned char * palette ) ;
static void gameFreeGlobalVars ( ) ;
static void showHelp ( ) ;
static int gameDbInit ( ) ;
static void showSplash ( ) ;
2022-05-19 01:51:26 -07:00
// 0x501C9C
2022-06-19 03:18:12 -07:00
static char _aGame_0 [ ] = " game \\ " ;
2022-05-19 01:51:26 -07:00
// 0x5020B8
2022-06-19 03:18:12 -07:00
static char _aDec11199816543 [ ] = VERSION_BUILD_TIME ;
2022-05-19 01:51:26 -07:00
// 0x5186B4
2022-06-19 03:18:12 -07:00
static bool gGameUiDisabled = false ;
2022-05-19 01:51:26 -07:00
// 0x5186B8
2022-06-19 03:18:12 -07:00
static int _game_state_cur = 0 ;
2022-05-19 01:51:26 -07:00
// 0x5186BC
2022-06-19 03:18:12 -07:00
static bool gIsMapper = false ;
2022-05-19 01:51:26 -07:00
// 0x5186C0
int * gGameGlobalVars = NULL ;
// 0x5186C4
int gGameGlobalVarsLength = 0 ;
// 0x5186C8
const char * asc_5186C8 = _aGame_0 ;
// 0x5186CC
int _game_user_wants_to_quit = 0 ;
// misc.msg
//
// 0x58E940
MessageList gMiscMessageList ;
// master.dat loading result
//
// 0x58E948
int _master_db_handle ;
// critter.dat loading result
//
// 0x58E94C
int _critter_db_handle ;
// 0x442580
int gameInitWithOptions ( const char * windowTitle , bool isMapper , int font , int a4 , int argc , char * * argv )
{
2022-05-28 02:34:49 -07:00
char path [ COMPAT_MAX_PATH ] ;
2022-05-19 01:51:26 -07:00
if ( gameMemoryInit ( ) = = - 1 ) {
return - 1 ;
}
2022-05-25 14:16:20 -07:00
// Sfall config should be initialized before game config, since it can
// override it's file name.
sfallConfigInit ( argc , argv ) ;
2022-05-19 01:51:26 -07:00
gameConfigInit ( isMapper , argc , argv ) ;
gIsMapper = isMapper ;
if ( gameDbInit ( ) = = - 1 ) {
gameConfigExit ( false ) ;
2022-05-25 14:16:20 -07:00
sfallConfigExit ( ) ;
2022-05-19 01:51:26 -07:00
return - 1 ;
}
runElectronicRegistration ( ) ;
programWindowSetTitle ( windowTitle ) ;
_initWindow ( 1 , a4 ) ;
paletteInit ( ) ;
char * language ;
if ( configGetString ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_LANGUAGE_KEY , & language ) ) {
2022-05-28 01:57:32 -07:00
if ( compat_stricmp ( language , FRENCH ) = = 0 ) {
2022-05-19 01:51:26 -07:00
keyboardSetLayout ( KEYBOARD_LAYOUT_FRENCH ) ;
2022-05-28 01:57:32 -07:00
} else if ( compat_stricmp ( language , GERMAN ) = = 0 ) {
2022-05-19 01:51:26 -07:00
keyboardSetLayout ( KEYBOARD_LAYOUT_GERMAN ) ;
2022-05-28 01:57:32 -07:00
} else if ( compat_stricmp ( language , ITALIAN ) = = 0 ) {
2022-05-19 01:51:26 -07:00
keyboardSetLayout ( KEYBOARD_LAYOUT_ITALIAN ) ;
2022-05-28 01:57:32 -07:00
} else if ( compat_stricmp ( language , SPANISH ) = = 0 ) {
2022-05-19 01:51:26 -07:00
keyboardSetLayout ( KEYBOARD_LAYOUT_SPANISH ) ;
}
}
2022-06-04 03:22:40 -07:00
// SFALL: Allow to skip splash screen
int skipOpeningMovies = 0 ;
configGetInt ( & gSfallConfig , SFALL_CONFIG_MISC_KEY , SFALL_CONFIG_SKIP_OPENING_MOVIES_KEY , & skipOpeningMovies ) ;
if ( ! gIsMapper & & skipOpeningMovies < 2 ) {
2022-05-19 01:51:26 -07:00
showSplash ( ) ;
}
_trap_init ( ) ;
interfaceFontsInit ( ) ;
fontManagerAdd ( & gModernFontManager ) ;
fontSetCurrent ( font ) ;
screenshotHandlerConfigure ( KEY_F12 , gameTakeScreenshot ) ;
pauseHandlerConfigure ( - 1 , NULL ) ;
tileDisable ( ) ;
randomInit ( ) ;
badwordsInit ( ) ;
skillsInit ( ) ;
statsInit ( ) ;
if ( partyMembersInit ( ) ! = 0 ) {
debugPrint ( " Failed on partyMember_init \n " ) ;
return - 1 ;
}
perksInit ( ) ;
traitsInit ( ) ;
itemsInit ( ) ;
queueInit ( ) ;
critterInit ( ) ;
aiInit ( ) ;
_inven_reset_dude ( ) ;
if ( gameSoundInit ( ) ! = 0 ) {
debugPrint ( " Sound initialization failed. \n " ) ;
}
debugPrint ( " >gsound_init \t " ) ;
movieInit ( ) ;
debugPrint ( " >initMovie \t \t " ) ;
if ( gameMoviesInit ( ) ! = 0 ) {
debugPrint ( " Failed on gmovie_init \n " ) ;
return - 1 ;
}
debugPrint ( " >gmovie_init \t " ) ;
if ( movieEffectsInit ( ) ! = 0 ) {
debugPrint ( " Failed on moviefx_init \n " ) ;
return - 1 ;
}
debugPrint ( " >moviefx_init \t " ) ;
if ( isoInit ( ) ! = 0 ) {
debugPrint ( " Failed on iso_init \n " ) ;
return - 1 ;
}
debugPrint ( " >iso_init \t " ) ;
if ( gameMouseInit ( ) ! = 0 ) {
debugPrint ( " Failed on gmouse_init \n " ) ;
return - 1 ;
}
debugPrint ( " >gmouse_init \t " ) ;
if ( protoInit ( ) ! = 0 ) {
debugPrint ( " Failed on proto_init \n " ) ;
return - 1 ;
}
debugPrint ( " >proto_init \t " ) ;
animationInit ( ) ;
debugPrint ( " >anim_init \t " ) ;
if ( scriptsInit ( ) ! = 0 ) {
debugPrint ( " Failed on scr_init \n " ) ;
return - 1 ;
}
debugPrint ( " >scr_init \t " ) ;
if ( gameLoadGlobalVars ( ) ! = 0 ) {
debugPrint ( " Failed on game_load_info \n " ) ;
return - 1 ;
}
debugPrint ( " >game_load_info \t " ) ;
if ( _scr_game_init ( ) ! = 0 ) {
debugPrint ( " Failed on scr_game_init \n " ) ;
return - 1 ;
}
debugPrint ( " >scr_game_init \t " ) ;
if ( worldmapInit ( ) ! = 0 ) {
debugPrint ( " Failed on wmWorldMap_init \n " ) ;
return - 1 ;
}
debugPrint ( " >wmWorldMap_init \t " ) ;
2022-06-10 14:32:57 -07:00
characterEditorInit ( ) ;
2022-05-19 01:51:26 -07:00
debugPrint ( " >CharEditInit \t " ) ;
pipboyInit ( ) ;
debugPrint ( " >pip_init \t \t " ) ;
_InitLoadSave ( ) ;
lsgInit ( ) ;
debugPrint ( " >InitLoadSave \t " ) ;
if ( gameDialogInit ( ) ! = 0 ) {
debugPrint ( " Failed on gdialog_init \n " ) ;
return - 1 ;
}
debugPrint ( " >gdialog_init \t " ) ;
if ( combatInit ( ) ! = 0 ) {
debugPrint ( " Failed on combat_init \n " ) ;
return - 1 ;
}
debugPrint ( " >combat_init \t " ) ;
if ( automapInit ( ) ! = 0 ) {
debugPrint ( " Failed on automap_init \n " ) ;
return - 1 ;
}
debugPrint ( " >automap_init \t " ) ;
if ( ! messageListInit ( & gMiscMessageList ) ) {
debugPrint ( " Failed on message_init \n " ) ;
return - 1 ;
}
debugPrint ( " >message_init \t " ) ;
sprintf ( path , " %s%s " , asc_5186C8 , " misc.msg " ) ;
if ( ! messageListLoad ( & gMiscMessageList , path ) ) {
debugPrint ( " Failed on message_load \n " ) ;
return - 1 ;
}
debugPrint ( " >message_load \t " ) ;
if ( scriptsDisable ( ) ! = 0 ) {
debugPrint ( " Failed on scr_disable \n " ) ;
return - 1 ;
}
debugPrint ( " >scr_disable \t " ) ;
if ( _init_options_menu ( ) ! = 0 ) {
debugPrint ( " Failed on init_options_menu \n " ) ;
return - 1 ;
}
debugPrint ( " >init_options_menu \n " ) ;
if ( endgameDeathEndingInit ( ) ! = 0 ) {
debugPrint ( " Failed on endgameDeathEndingInit " ) ;
return - 1 ;
}
debugPrint ( " >endgameDeathEndingInit \n " ) ;
2022-08-03 06:06:44 -07:00
// SFALL
premadeCharactersInit ( ) ;
2022-05-19 01:51:26 -07:00
return 0 ;
}
// 0x442B84
void gameReset ( )
{
tileDisable ( ) ;
paletteReset ( ) ;
randomReset ( ) ;
skillsReset ( ) ;
statsReset ( ) ;
perksReset ( ) ;
traitsReset ( ) ;
itemsReset ( ) ;
queueExit ( ) ;
animationReset ( ) ;
lsgInit ( ) ;
critterReset ( ) ;
aiReset ( ) ;
_inven_reset_dude ( ) ;
gameSoundReset ( ) ;
_movieStop ( ) ;
movieEffectsReset ( ) ;
gameMoviesReset ( ) ;
isoReset ( ) ;
gameMouseReset ( ) ;
protoReset ( ) ;
_scr_reset ( ) ;
gameLoadGlobalVars ( ) ;
scriptsReset ( ) ;
worldmapReset ( ) ;
partyMembersReset ( ) ;
2022-06-10 14:32:57 -07:00
characterEditorInit ( ) ;
2022-05-19 01:51:26 -07:00
pipboyReset ( ) ;
_ResetLoadSave ( ) ;
gameDialogReset ( ) ;
combatReset ( ) ;
_game_user_wants_to_quit = 0 ;
automapReset ( ) ;
_init_options_menu ( ) ;
}
// 0x442C34
void gameExit ( )
{
debugPrint ( " \n Game Exit \n " ) ;
2022-08-03 06:06:44 -07:00
// SFALL
premadeCharactersExit ( ) ;
2022-05-19 01:51:26 -07:00
tileDisable ( ) ;
messageListFree ( & gMiscMessageList ) ;
combatExit ( ) ;
gameDialogExit ( ) ;
_scr_game_exit ( ) ;
// NOTE: Uninline.
gameFreeGlobalVars ( ) ;
scriptsExit ( ) ;
animationExit ( ) ;
protoExit ( ) ;
gameMouseExit ( ) ;
isoExit ( ) ;
movieEffectsExit ( ) ;
movieExit ( ) ;
gameSoundExit ( ) ;
aiExit ( ) ;
critterExit ( ) ;
itemsExit ( ) ;
queueExit ( ) ;
perksExit ( ) ;
statsExit ( ) ;
skillsExit ( ) ;
traitsExit ( ) ;
randomExit ( ) ;
badwordsExit ( ) ;
automapExit ( ) ;
paletteExit ( ) ;
worldmapExit ( ) ;
partyMembersExit ( ) ;
endgameDeathEndingExit ( ) ;
interfaceFontsExit ( ) ;
_trap_init ( ) ;
_windowClose ( ) ;
dbExit ( ) ;
gameConfigExit ( true ) ;
2022-05-25 14:16:20 -07:00
sfallConfigExit ( ) ;
2022-05-19 01:51:26 -07:00
}
// 0x442D44
int gameHandleKey ( int eventCode , bool isInCombatMode )
{
if ( _game_state_cur = = 5 ) {
_gdialogSystemEnter ( ) ;
}
if ( eventCode = = - 1 ) {
2022-08-07 04:52:44 -07:00
if ( ( mouseGetEvent ( ) & MOUSE_EVENT_WHEEL ) ! = 0 ) {
int wheelX ;
int wheelY ;
mouseGetWheel ( & wheelX , & wheelY ) ;
int dx = 0 ;
if ( wheelX > 0 ) {
dx = 1 ;
} else if ( wheelX < 0 ) {
dx = - 1 ;
}
int dy = 0 ;
if ( wheelY > 0 ) {
dy = - 1 ;
} else if ( wheelY < 0 ) {
dy = 1 ;
}
mapScroll ( dx , dy ) ;
}
2022-05-19 01:51:26 -07:00
return 0 ;
}
if ( eventCode = = - 2 ) {
int mouseState = mouseGetEvent ( ) ;
int mouseX ;
int mouseY ;
mouseGetPosition ( & mouseX , & mouseY ) ;
if ( ( mouseState & MOUSE_EVENT_LEFT_BUTTON_DOWN ) ! = 0 ) {
if ( ( mouseState & MOUSE_EVENT_LEFT_BUTTON_REPEAT ) = = 0 ) {
if ( mouseX = = _scr_size . left | | mouseX = = _scr_size . right
| | mouseY = = _scr_size . top | | mouseY = = _scr_size . bottom ) {
_gmouse_clicked_on_edge = true ;
}
}
} else {
if ( ( mouseState & MOUSE_EVENT_LEFT_BUTTON_UP ) ! = 0 ) {
_gmouse_clicked_on_edge = false ;
}
}
_gmouse_handle_event ( mouseX , mouseY , mouseState ) ;
return 0 ;
}
if ( _gmouse_is_scrolling ( ) ) {
return 0 ;
}
switch ( eventCode ) {
case - 20 :
if ( interfaceBarEnabled ( ) ) {
_intface_use_item ( ) ;
}
break ;
case KEY_CTRL_Q :
case KEY_CTRL_X :
case KEY_F10 :
soundPlayFile ( " ib1p1xx1 " ) ;
showQuitConfirmationDialog ( ) ;
break ;
case KEY_TAB :
if ( interfaceBarEnabled ( )
2022-05-23 01:44:49 -07:00
& & gPressedPhysicalKeys [ SDL_SCANCODE_LALT ] = = 0
& & gPressedPhysicalKeys [ SDL_SCANCODE_RALT ] = = 0 ) {
2022-05-19 01:51:26 -07:00
soundPlayFile ( " ib1p1xx1 " ) ;
automapShow ( true , false ) ;
}
break ;
case KEY_CTRL_P :
soundPlayFile ( " ib1p1xx1 " ) ;
showPause ( false ) ;
break ;
case KEY_UPPERCASE_A :
case KEY_LOWERCASE_A :
if ( interfaceBarEnabled ( ) ) {
if ( ! isInCombatMode ) {
_combat ( NULL ) ;
}
}
break ;
case KEY_UPPERCASE_N :
case KEY_LOWERCASE_N :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
interfaceCycleItemAction ( ) ;
}
break ;
case KEY_UPPERCASE_M :
case KEY_LOWERCASE_M :
gameMouseCycleMode ( ) ;
break ;
case KEY_UPPERCASE_B :
case KEY_LOWERCASE_B :
// change active hand
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
interfaceBarSwapHands ( true ) ;
}
break ;
case KEY_UPPERCASE_C :
case KEY_LOWERCASE_C :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
bool isoWasEnabled = isoDisable ( ) ;
2022-06-10 14:32:57 -07:00
characterEditorShow ( false ) ;
2022-05-19 01:51:26 -07:00
if ( isoWasEnabled ) {
isoEnable ( ) ;
}
}
break ;
case KEY_UPPERCASE_I :
case KEY_LOWERCASE_I :
// open inventory
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
inventoryOpen ( ) ;
}
break ;
case KEY_ESCAPE :
case KEY_UPPERCASE_O :
case KEY_LOWERCASE_O :
// options
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
showOptions ( ) ;
}
break ;
case KEY_UPPERCASE_P :
case KEY_LOWERCASE_P :
// pipboy
if ( interfaceBarEnabled ( ) ) {
if ( isInCombatMode ) {
soundPlayFile ( " iisxxxx1 " ) ;
// Pipboy not available in combat!
MessageListItem messageListItem ;
char title [ 128 ] ;
strcpy ( title , getmsg ( & gMiscMessageList , & messageListItem , 7 ) ) ;
showDialogBox ( title , NULL , 0 , 192 , 116 , _colorTable [ 32328 ] , NULL , _colorTable [ 32328 ] , 0 ) ;
} else {
soundPlayFile ( " ib1p1xx1 " ) ;
2022-08-07 09:03:43 -07:00
pipboyOpen ( PIPBOY_OPEN_INTENT_UNSPECIFIED ) ;
2022-05-19 01:51:26 -07:00
}
}
break ;
case KEY_UPPERCASE_S :
case KEY_LOWERCASE_S :
// skilldex
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
int mode = - 1 ;
// NOTE: There is an `inc` for this value to build jump table which
// is not needed.
int rc = skilldexOpen ( ) ;
// Remap Skilldex result code to action.
switch ( rc ) {
case SKILLDEX_RC_ERROR :
debugPrint ( " \n ** Error calling skilldex_select()! ** \n " ) ;
break ;
case SKILLDEX_RC_SNEAK :
_action_skill_use ( SKILL_SNEAK ) ;
break ;
case SKILLDEX_RC_LOCKPICK :
mode = GAME_MOUSE_MODE_USE_LOCKPICK ;
break ;
case SKILLDEX_RC_STEAL :
mode = GAME_MOUSE_MODE_USE_STEAL ;
break ;
case SKILLDEX_RC_TRAPS :
mode = GAME_MOUSE_MODE_USE_TRAPS ;
break ;
case SKILLDEX_RC_FIRST_AID :
mode = GAME_MOUSE_MODE_USE_FIRST_AID ;
break ;
case SKILLDEX_RC_DOCTOR :
mode = GAME_MOUSE_MODE_USE_DOCTOR ;
break ;
case SKILLDEX_RC_SCIENCE :
mode = GAME_MOUSE_MODE_USE_SCIENCE ;
break ;
case SKILLDEX_RC_REPAIR :
mode = GAME_MOUSE_MODE_USE_REPAIR ;
break ;
default :
break ;
}
if ( mode ! = - 1 ) {
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( mode ) ;
}
}
break ;
case KEY_UPPERCASE_Z :
case KEY_LOWERCASE_Z :
if ( interfaceBarEnabled ( ) ) {
if ( isInCombatMode ) {
soundPlayFile ( " iisxxxx1 " ) ;
// Pipboy not available in combat!
MessageListItem messageListItem ;
char title [ 128 ] ;
strcpy ( title , getmsg ( & gMiscMessageList , & messageListItem , 7 ) ) ;
showDialogBox ( title , NULL , 0 , 192 , 116 , _colorTable [ 32328 ] , NULL , _colorTable [ 32328 ] , 0 ) ;
} else {
soundPlayFile ( " ib1p1xx1 " ) ;
2022-08-07 09:03:43 -07:00
pipboyOpen ( PIPBOY_OPEN_INTENT_REST ) ;
2022-05-19 01:51:26 -07:00
}
}
break ;
case KEY_HOME :
if ( gDude - > elevation ! = gElevation ) {
mapSetElevation ( gDude - > elevation ) ;
}
if ( gIsMapper ) {
tileSetCenter ( gDude - > tile , TILE_SET_CENTER_FLAG_0x01 ) ;
} else {
_tile_scroll_to ( gDude - > tile , 2 ) ;
}
break ;
case KEY_1 :
case KEY_EXCLAMATION :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
_action_skill_use ( SKILL_SNEAK ) ;
}
break ;
case KEY_2 :
case KEY_AT :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( GAME_MOUSE_MODE_USE_LOCKPICK ) ;
}
break ;
case KEY_3 :
case KEY_NUMBER_SIGN :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( GAME_MOUSE_MODE_USE_STEAL ) ;
}
break ;
case KEY_4 :
case KEY_DOLLAR :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( GAME_MOUSE_MODE_USE_TRAPS ) ;
}
break ;
case KEY_5 :
case KEY_PERCENT :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( GAME_MOUSE_MODE_USE_FIRST_AID ) ;
}
break ;
case KEY_6 :
case KEY_CARET :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( GAME_MOUSE_MODE_USE_DOCTOR ) ;
}
break ;
case KEY_7 :
case KEY_AMPERSAND :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( GAME_MOUSE_MODE_USE_SCIENCE ) ;
}
break ;
case KEY_8 :
case KEY_ASTERISK :
if ( interfaceBarEnabled ( ) ) {
soundPlayFile ( " ib1p1xx1 " ) ;
gameMouseSetCursor ( MOUSE_CURSOR_USE_CROSSHAIR ) ;
gameMouseSetMode ( GAME_MOUSE_MODE_USE_REPAIR ) ;
}
break ;
case KEY_MINUS :
case KEY_UNDERSCORE :
brightnessDecrease ( ) ;
break ;
case KEY_EQUAL :
case KEY_PLUS :
brightnessIncrease ( ) ;
break ;
case KEY_COMMA :
case KEY_LESS :
if ( reg_anim_begin ( 0 ) = = 0 ) {
2022-07-29 06:04:05 -07:00
animationRegisterRotateCounterClockwise ( gDude ) ;
2022-05-19 01:51:26 -07:00
reg_anim_end ( ) ;
}
break ;
case KEY_DOT :
case KEY_GREATER :
if ( reg_anim_begin ( 0 ) = = 0 ) {
2022-07-29 06:04:05 -07:00
animationRegisterRotateClockwise ( gDude ) ;
2022-05-19 01:51:26 -07:00
reg_anim_end ( ) ;
}
break ;
case KEY_SLASH :
case KEY_QUESTION :
if ( 1 ) {
soundPlayFile ( " ib1p1xx1 " ) ;
int month ;
int day ;
int year ;
gameTimeGetDate ( & month , & day , & year ) ;
MessageList messageList ;
if ( messageListInit ( & messageList ) ) {
2022-05-28 02:34:49 -07:00
char path [ COMPAT_MAX_PATH ] ;
2022-05-19 01:51:26 -07:00
sprintf ( path , " %s%s " , asc_5186C8 , " editor.msg " ) ;
if ( messageListLoad ( & messageList , path ) ) {
MessageListItem messageListItem ;
messageListItem . num = 500 + month - 1 ;
if ( messageListGetItem ( & messageList , & messageListItem ) ) {
char * time = gameTimeGetTimeString ( ) ;
char date [ 128 ] ;
sprintf ( date , " %s: %d/%d %s " , messageListItem . text , day , year , time ) ;
displayMonitorAddMessage ( date ) ;
}
}
messageListFree ( & messageList ) ;
}
}
break ;
case KEY_F1 :
soundPlayFile ( " ib1p1xx1 " ) ;
showHelp ( ) ;
break ;
case KEY_F2 :
gameSoundSetMasterVolume ( gameSoundGetMasterVolume ( ) - 2047 ) ;
break ;
case KEY_F3 :
gameSoundSetMasterVolume ( gameSoundGetMasterVolume ( ) + 2047 ) ;
break ;
case KEY_CTRL_S :
case KEY_F4 :
soundPlayFile ( " ib1p1xx1 " ) ;
if ( lsgSaveGame ( 1 ) = = - 1 ) {
debugPrint ( " \n ** Error calling SaveGame()! ** \n " ) ;
}
break ;
case KEY_CTRL_L :
case KEY_F5 :
soundPlayFile ( " ib1p1xx1 " ) ;
if ( lsgLoadGame ( LOAD_SAVE_MODE_NORMAL ) = = - 1 ) {
debugPrint ( " \n ** Error calling LoadGame()! ** \n " ) ;
}
break ;
case KEY_F6 :
if ( 1 ) {
soundPlayFile ( " ib1p1xx1 " ) ;
int rc = lsgSaveGame ( LOAD_SAVE_MODE_QUICK ) ;
if ( rc = = - 1 ) {
debugPrint ( " \n ** Error calling SaveGame()! ** \n " ) ;
} else if ( rc = = 1 ) {
MessageListItem messageListItem ;
// Quick save game successfully saved.
char * msg = getmsg ( & gMiscMessageList , & messageListItem , 5 ) ;
displayMonitorAddMessage ( msg ) ;
}
}
break ;
case KEY_F7 :
if ( 1 ) {
soundPlayFile ( " ib1p1xx1 " ) ;
int rc = lsgLoadGame ( LOAD_SAVE_MODE_QUICK ) ;
if ( rc = = - 1 ) {
debugPrint ( " \n ** Error calling LoadGame()! ** \n " ) ;
} else if ( rc = = 1 ) {
MessageListItem messageListItem ;
// Quick load game successfully loaded.
char * msg = getmsg ( & gMiscMessageList , & messageListItem , 4 ) ;
displayMonitorAddMessage ( msg ) ;
}
}
break ;
case KEY_CTRL_V :
if ( 1 ) {
soundPlayFile ( " ib1p1xx1 " ) ;
char version [ VERSION_MAX ] ;
versionGetVersion ( version ) ;
displayMonitorAddMessage ( version ) ;
displayMonitorAddMessage ( _aDec11199816543 ) ;
}
break ;
case KEY_ARROW_LEFT :
mapScroll ( - 1 , 0 ) ;
break ;
case KEY_ARROW_RIGHT :
mapScroll ( 1 , 0 ) ;
break ;
case KEY_ARROW_UP :
mapScroll ( 0 , - 1 ) ;
break ;
case KEY_ARROW_DOWN :
mapScroll ( 0 , 1 ) ;
break ;
}
// TODO: Incomplete.
return 0 ;
}
// game_ui_disable
// 0x443BFC
void gameUiDisable ( int a1 )
{
if ( ! gGameUiDisabled ) {
gameMouseObjectsHide ( ) ;
_gmouse_disable ( a1 ) ;
keyboardDisable ( ) ;
interfaceBarDisable ( ) ;
gGameUiDisabled = true ;
}
}
// game_ui_enable
// 0x443C30
void gameUiEnable ( )
{
if ( gGameUiDisabled ) {
interfaceBarEnable ( ) ;
keyboardEnable ( ) ;
keyboardReset ( ) ;
_gmouse_enable ( ) ;
gameMouseObjectsShow ( ) ;
gGameUiDisabled = false ;
}
}
// game_ui_is_disabled
// 0x443C60
bool gameUiIsDisabled ( )
{
return gGameUiDisabled ;
}
// 0x443C68
int gameGetGlobalVar ( int var )
{
if ( var < 0 | | var > = gGameGlobalVarsLength ) {
debugPrint ( " ERROR: attempt to reference global var out of range: %d " , var ) ;
return 0 ;
}
return gGameGlobalVars [ var ] ;
}
// 0x443C98
int gameSetGlobalVar ( int var , int value )
{
if ( var < 0 | | var > = gGameGlobalVarsLength ) {
debugPrint ( " ERROR: attempt to reference global var out of range: %d " , var ) ;
return - 1 ;
}
2022-06-08 13:33:54 -07:00
// SFALL: Display karma changes.
if ( var = = GVAR_PLAYER_REPUTATION ) {
bool shouldDisplayKarmaChanges = false ;
configGetBool ( & gSfallConfig , SFALL_CONFIG_MISC_KEY , SFALL_CONFIG_DISPLAY_KARMA_CHANGES_KEY , & shouldDisplayKarmaChanges ) ;
if ( shouldDisplayKarmaChanges ) {
int diff = value - gGameGlobalVars [ var ] ;
if ( diff ! = 0 ) {
char formattedMessage [ 80 ] ;
if ( diff > 0 ) {
sprintf ( formattedMessage , " You gained %d karma. " , diff ) ;
} else {
sprintf ( formattedMessage , " You lost %d karma. " , - diff ) ;
}
displayMonitorAddMessage ( formattedMessage ) ;
}
}
}
2022-05-19 01:51:26 -07:00
gGameGlobalVars [ var ] = value ;
return 0 ;
}
// game_load_info
// 0x443CC8
2022-06-19 03:18:12 -07:00
static int gameLoadGlobalVars ( )
2022-05-19 01:51:26 -07:00
{
return globalVarsRead ( " data \\ vault13.gam " , " GAME_GLOBAL_VARS: " , & gGameGlobalVarsLength , & gGameGlobalVars ) ;
}
// 0x443CE8
2022-07-29 06:04:05 -07:00
int globalVarsRead ( const char * path , const char * section , int * variablesListLengthPtr , int * * variablesListPtr )
2022-05-19 01:51:26 -07:00
{
_inven_reset_dude ( ) ;
2022-07-29 06:04:05 -07:00
File * stream = fileOpen ( path , " rt " ) ;
2022-05-19 01:51:26 -07:00
if ( stream = = NULL ) {
return - 1 ;
}
2022-07-29 06:04:05 -07:00
if ( * variablesListLengthPtr ! = 0 ) {
internal_free ( * variablesListPtr ) ;
* variablesListPtr = NULL ;
* variablesListLengthPtr = 0 ;
2022-05-19 01:51:26 -07:00
}
2022-07-29 06:04:05 -07:00
char string [ 260 ] ;
2022-05-19 01:51:26 -07:00
if ( section ! = NULL ) {
2022-07-29 06:04:05 -07:00
while ( fileReadString ( string , 258 , stream ) ) {
if ( strncmp ( string , section , 16 ) = = 0 ) {
2022-05-19 01:51:26 -07:00
break ;
}
}
}
2022-07-29 06:04:05 -07:00
while ( fileReadString ( string , 258 , stream ) ) {
if ( string [ 0 ] = = ' \n ' ) {
2022-05-19 01:51:26 -07:00
continue ;
}
2022-07-29 06:04:05 -07:00
if ( string [ 0 ] = = ' / ' & & string [ 1 ] = = ' / ' ) {
2022-05-19 01:51:26 -07:00
continue ;
}
2022-07-29 06:04:05 -07:00
char * semicolon = strchr ( string , ' ; ' ) ;
if ( semicolon ! = NULL ) {
* semicolon = ' \0 ' ;
2022-05-19 01:51:26 -07:00
}
2022-07-29 06:04:05 -07:00
* variablesListLengthPtr = * variablesListLengthPtr + 1 ;
* variablesListPtr = ( int * ) internal_realloc ( * variablesListPtr , sizeof ( int ) * * variablesListLengthPtr ) ;
2022-05-19 01:51:26 -07:00
2022-07-29 06:04:05 -07:00
if ( * variablesListPtr = = NULL ) {
2022-05-19 01:51:26 -07:00
exit ( 1 ) ;
}
2022-07-29 06:04:05 -07:00
char * equals = strchr ( string , ' = ' ) ;
if ( equals ! = NULL ) {
sscanf ( equals + 1 , " %d " , * variablesListPtr + * variablesListLengthPtr - 1 ) ;
2022-05-19 01:51:26 -07:00
} else {
2022-07-29 06:04:05 -07:00
* variablesListPtr [ * variablesListLengthPtr - 1 ] = 0 ;
2022-05-19 01:51:26 -07:00
}
}
fileClose ( stream ) ;
return 0 ;
}
// 0x443E2C
int _game_state ( )
{
return _game_state_cur ;
}
// 0x443E34
int _game_state_request ( int a1 )
{
if ( a1 = = 0 ) {
a1 = 1 ;
} else if ( a1 = = 2 ) {
a1 = 3 ;
} else if ( a1 = = 4 ) {
a1 = 5 ;
}
if ( _game_state_cur ! = 4 | | a1 ! = 5 ) {
_game_state_cur = a1 ;
return 0 ;
}
return - 1 ;
}
// 0x443E90
void _game_state_update ( )
{
int v0 ;
v0 = _game_state_cur ;
switch ( _game_state_cur ) {
case 1 :
v0 = 0 ;
break ;
case 3 :
v0 = 2 ;
break ;
case 5 :
v0 = 4 ;
}
_game_state_cur = v0 ;
}
// 0x443EF0
2022-06-19 03:18:12 -07:00
static int gameTakeScreenshot ( int width , int height , unsigned char * buffer , unsigned char * palette )
2022-05-19 01:51:26 -07:00
{
MessageListItem messageListItem ;
if ( screenshotHandlerDefaultImpl ( width , height , buffer , palette ) ! = 0 ) {
// Error saving screenshot.
messageListItem . num = 8 ;
if ( messageListGetItem ( & gMiscMessageList , & messageListItem ) ) {
displayMonitorAddMessage ( messageListItem . text ) ;
}
return - 1 ;
}
// Saved screenshot.
messageListItem . num = 3 ;
if ( messageListGetItem ( & gMiscMessageList , & messageListItem ) ) {
displayMonitorAddMessage ( messageListItem . text ) ;
}
return 0 ;
}
// NOTE: Inlined.
//
// 0x443F50
2022-06-19 03:18:12 -07:00
static void gameFreeGlobalVars ( )
2022-05-19 01:51:26 -07:00
{
gGameGlobalVarsLength = 0 ;
if ( gGameGlobalVars ! = NULL ) {
internal_free ( gGameGlobalVars ) ;
gGameGlobalVars = NULL ;
}
}
// 0x443F74
2022-06-19 03:18:12 -07:00
static void showHelp ( )
2022-05-19 01:51:26 -07:00
{
bool isoWasEnabled = isoDisable ( ) ;
gameMouseObjectsHide ( ) ;
gameMouseSetCursor ( MOUSE_CURSOR_NONE ) ;
bool colorCycleWasEnabled = colorCycleEnabled ( ) ;
colorCycleDisable ( ) ;
2022-05-27 20:57:53 -07:00
int helpWindowX = ( screenGetWidth ( ) - HELP_SCREEN_WIDTH ) / 2 ;
int helpWindowY = ( screenGetHeight ( ) - HELP_SCREEN_HEIGHT ) / 2 ;
int win = windowCreate ( helpWindowX , helpWindowY , HELP_SCREEN_WIDTH , HELP_SCREEN_HEIGHT , 0 , WINDOW_HIDDEN | WINDOW_FLAG_0x04 ) ;
2022-05-19 01:51:26 -07:00
if ( win ! = - 1 ) {
unsigned char * windowBuffer = windowGetBuffer ( win ) ;
if ( windowBuffer ! = NULL ) {
2022-07-29 06:04:05 -07:00
int backgroundFid = buildFid ( OBJ_TYPE_INTERFACE , 297 , 0 , 0 , 0 ) ;
2022-05-19 01:51:26 -07:00
CacheEntry * backgroundHandle ;
unsigned char * backgroundData = artLockFrameData ( backgroundFid , 0 , 0 , & backgroundHandle ) ;
if ( backgroundData ! = NULL ) {
paletteSetEntries ( gPaletteBlack ) ;
blitBufferToBuffer ( backgroundData , HELP_SCREEN_WIDTH , HELP_SCREEN_HEIGHT , HELP_SCREEN_WIDTH , windowBuffer , HELP_SCREEN_WIDTH ) ;
artUnlock ( backgroundHandle ) ;
windowUnhide ( win ) ;
colorPaletteLoad ( " art \\ intrface \\ helpscrn.pal " ) ;
paletteSetEntries ( _cmap ) ;
while ( _get_input ( ) = = - 1 & & _game_user_wants_to_quit = = 0 ) {
}
while ( mouseGetEvent ( ) ! = 0 ) {
_get_input ( ) ;
}
paletteSetEntries ( gPaletteBlack ) ;
}
}
windowDestroy ( win ) ;
colorPaletteLoad ( " color.pal " ) ;
paletteSetEntries ( _cmap ) ;
}
if ( colorCycleWasEnabled ) {
colorCycleEnable ( ) ;
}
gameMouseObjectsShow ( ) ;
if ( isoWasEnabled ) {
isoEnable ( ) ;
}
}
// 0x4440B8
int showQuitConfirmationDialog ( )
{
bool isoWasEnabled = isoDisable ( ) ;
bool gameMouseWasVisible ;
if ( isoWasEnabled ) {
gameMouseWasVisible = gameMouseObjectsIsVisible ( ) ;
} else {
gameMouseWasVisible = false ;
}
if ( gameMouseWasVisible ) {
gameMouseObjectsHide ( ) ;
}
bool cursorWasHidden = cursorIsHidden ( ) ;
if ( cursorWasHidden ) {
mouseShowCursor ( ) ;
}
int oldCursor = gameMouseGetCursor ( ) ;
gameMouseSetCursor ( MOUSE_CURSOR_ARROW ) ;
int rc ;
// Are you sure you want to quit?
MessageListItem messageListItem ;
messageListItem . num = 0 ;
if ( messageListGetItem ( & gMiscMessageList , & messageListItem ) ) {
rc = showDialogBox ( messageListItem . text , 0 , 0 , 169 , 117 , _colorTable [ 32328 ] , NULL , _colorTable [ 32328 ] , DIALOG_BOX_YES_NO ) ;
if ( rc ! = 0 ) {
_game_user_wants_to_quit = 2 ;
}
} else {
rc = - 1 ;
}
gameMouseSetCursor ( oldCursor ) ;
if ( cursorWasHidden ) {
mouseHideCursor ( ) ;
}
if ( gameMouseWasVisible ) {
gameMouseObjectsShow ( ) ;
}
if ( isoWasEnabled ) {
isoEnable ( ) ;
}
return rc ;
}
// 0x44418C
2022-06-19 03:18:12 -07:00
static int gameDbInit ( )
2022-05-19 01:51:26 -07:00
{
int hashing ;
char * main_file_name ;
char * patch_file_name ;
int patch_index ;
2022-05-28 02:34:49 -07:00
char filename [ COMPAT_MAX_PATH ] ;
2022-05-19 01:51:26 -07:00
hashing = 0 ;
main_file_name = NULL ;
patch_file_name = NULL ;
if ( configGetInt ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_HASHING_KEY , & hashing ) ) {
_db_enable_hash_table_ ( ) ;
}
configGetString ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_MASTER_DAT_KEY , & main_file_name ) ;
if ( * main_file_name = = ' \0 ' ) {
main_file_name = NULL ;
}
configGetString ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_MASTER_PATCHES_KEY , & patch_file_name ) ;
if ( * patch_file_name = = ' \0 ' ) {
patch_file_name = NULL ;
}
_master_db_handle = dbOpen ( main_file_name , 0 , patch_file_name , 1 ) ;
if ( _master_db_handle = = - 1 ) {
showMesageBox ( " Could not find the master datafile. Please make sure the FALLOUT CD is in the drive and that you are running FALLOUT from the directory you installed it to. " ) ;
return - 1 ;
}
configGetString ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_CRITTER_DAT_KEY , & main_file_name ) ;
if ( * main_file_name = = ' \0 ' ) {
main_file_name = NULL ;
}
configGetString ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_CRITTER_PATCHES_KEY , & patch_file_name ) ;
if ( * patch_file_name = = ' \0 ' ) {
patch_file_name = NULL ;
}
_critter_db_handle = dbOpen ( main_file_name , 0 , patch_file_name , 1 ) ;
if ( _critter_db_handle = = - 1 ) {
2022-08-16 01:25:56 -07:00
_db_select ( _master_db_handle ) ;
2022-05-19 01:51:26 -07:00
showMesageBox ( " Could not find the critter datafile. Please make sure the FALLOUT CD is in the drive and that you are running FALLOUT from the directory you installed it to. " ) ;
return - 1 ;
}
for ( patch_index = 0 ; patch_index < 1000 ; patch_index + + ) {
sprintf ( filename , " patch%03d.dat " , patch_index ) ;
if ( access ( filename , 0 ) = = 0 ) {
dbOpen ( filename , 0 , NULL , 1 ) ;
}
}
2022-08-16 01:25:56 -07:00
_db_select ( _master_db_handle ) ;
2022-05-19 01:51:26 -07:00
return 0 ;
}
// 0x444384
2022-06-19 03:18:12 -07:00
static void showSplash ( )
2022-05-19 01:51:26 -07:00
{
int splash ;
configGetInt ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_SPLASH_KEY , & splash ) ;
char path [ 64 ] ;
char * language ;
2022-05-28 01:57:32 -07:00
if ( configGetString ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_LANGUAGE_KEY , & language ) & & compat_stricmp ( language , ENGLISH ) ! = 0 ) {
2022-05-19 01:51:26 -07:00
sprintf ( path , " art \\ %s \\ splash \\ " , language ) ;
} else {
sprintf ( path , " art \\ splash \\ " ) ;
}
File * stream ;
for ( int index = 0 ; index < SPLASH_COUNT ; index + + ) {
char filePath [ 64 ] ;
sprintf ( filePath , " %ssplash%d.rix " , path , splash ) ;
stream = fileOpen ( filePath , " rb " ) ;
if ( stream ! = NULL ) {
break ;
}
splash + + ;
if ( splash > = SPLASH_COUNT ) {
splash = 0 ;
}
}
if ( stream = = NULL ) {
return ;
}
2022-05-21 08:22:03 -07:00
unsigned char * palette = ( unsigned char * ) internal_malloc ( 768 ) ;
2022-05-19 01:51:26 -07:00
if ( palette = = NULL ) {
fileClose ( stream ) ;
return ;
}
2022-05-21 08:22:03 -07:00
unsigned char * data = ( unsigned char * ) internal_malloc ( SPLASH_WIDTH * SPLASH_HEIGHT ) ;
2022-05-19 01:51:26 -07:00
if ( data = = NULL ) {
internal_free ( palette ) ;
fileClose ( stream ) ;
return ;
}
paletteSetEntries ( gPaletteBlack ) ;
fileSeek ( stream , 10 , SEEK_SET ) ;
fileRead ( palette , 1 , 768 , stream ) ;
fileRead ( data , 1 , SPLASH_WIDTH * SPLASH_HEIGHT , stream ) ;
fileClose ( stream ) ;
2022-05-21 10:29:02 -07:00
int splashWindowX = ( screenGetWidth ( ) - SPLASH_WIDTH ) / 2 ;
int splashWindowY = ( screenGetHeight ( ) - SPLASH_HEIGHT ) / 2 ;
_scr_blit ( data , SPLASH_WIDTH , SPLASH_HEIGHT , 0 , 0 , SPLASH_WIDTH , SPLASH_HEIGHT , splashWindowX , splashWindowY ) ;
2022-05-19 01:51:26 -07:00
paletteFadeTo ( palette ) ;
internal_free ( data ) ;
internal_free ( palette ) ;
configSetInt ( & gGameConfig , GAME_CONFIG_SYSTEM_KEY , GAME_CONFIG_SPLASH_KEY , splash + 1 ) ;
}
2022-08-19 10:25:14 -07:00
int gameShowDeathDialog ( const char * message )
{
bool isoWasEnabled = isoDisable ( ) ;
bool gameMouseWasVisible ;
if ( isoWasEnabled ) {
gameMouseWasVisible = gameMouseObjectsIsVisible ( ) ;
} else {
gameMouseWasVisible = false ;
}
if ( gameMouseWasVisible ) {
gameMouseObjectsHide ( ) ;
}
bool cursorWasHidden = cursorIsHidden ( ) ;
if ( cursorWasHidden ) {
mouseShowCursor ( ) ;
}
int oldCursor = gameMouseGetCursor ( ) ;
gameMouseSetCursor ( MOUSE_CURSOR_ARROW ) ;
int oldUserWantsToQuit = _game_user_wants_to_quit ;
_game_user_wants_to_quit = 0 ;
int rc = showDialogBox ( message , 0 , 0 , 169 , 117 , _colorTable [ 32328 ] , NULL , _colorTable [ 32328 ] , DIALOG_BOX_LARGE ) ;
_game_user_wants_to_quit = oldUserWantsToQuit ;
gameMouseSetCursor ( oldCursor ) ;
if ( cursorWasHidden ) {
mouseHideCursor ( ) ;
}
if ( gameMouseWasVisible ) {
gameMouseObjectsShow ( ) ;
}
if ( isoWasEnabled ) {
isoEnable ( ) ;
}
return rc ;
}