diff --git a/CMakeLists.txt b/CMakeLists.txt index 3db0b414..05cbed94 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,6 +144,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC "src/lips.h" "src/loadsave.cc" "src/loadsave.h" + "src/loop.cc" + "src/loop.h" "src/main.cc" "src/main.h" "src/map_defs.h" diff --git a/src/automap.cc b/src/automap.cc index 5d5e44c3..c195816a 100644 --- a/src/automap.cc +++ b/src/automap.cc @@ -18,6 +18,7 @@ #include "input.h" #include "item.h" #include "kb.h" +#include "loop.h" #include "map.h" #include "memory.h" #include "object.h" @@ -395,6 +396,8 @@ void automapShow(bool isInGame, bool isUsingScanner) bool isoWasEnabled = isoDisable(); gameMouseSetCursor(MOUSE_CURSOR_ARROW); + loopSetFlag(LoopFlag::AUTOMAP); + bool done = false; while (!done) { sharedFpsLimiter.mark(); @@ -488,6 +491,8 @@ void automapShow(bool isInGame, bool isUsingScanner) isoEnable(); } + loopClearFlag(LoopFlag::AUTOMAP); + windowDestroy(window); fontSetCurrent(oldFont); } diff --git a/src/character_editor.cc b/src/character_editor.cc index eaac82f9..4666e2ea 100644 --- a/src/character_editor.cc +++ b/src/character_editor.cc @@ -25,6 +25,7 @@ #include "interface.h" #include "item.h" #include "kb.h" +#include "loop.h" #include "map.h" #include "memory.h" #include "message.h" @@ -787,8 +788,19 @@ struct CustomKarmaFolderDescription { static std::vector gCustomKarmaFolderDescriptions; static std::vector gCustomTownReputationEntries; +int characterEditorShowInner(bool isCreationMode); + +// Wrapper for editor_design_, setting LoopFlag::CHARSCREEN +// (see sfall: CharacterHook) +int characterEditorShow(bool isCreationMode) { + loopSetFlag(LoopFlag::CHARSCREEN); + int result = characterEditorShowInner(isCreationMode); + loopClearFlag(LoopFlag::CHARSCREEN); + return result; +} + // 0x431DF8 -int characterEditorShow(bool isCreationMode) +int characterEditorShowInner(bool isCreationMode) { char* messageListItemText; char line1[128]; diff --git a/src/combat.cc b/src/combat.cc index 071ac851..4a9599e9 100644 --- a/src/combat.cc +++ b/src/combat.cc @@ -23,6 +23,7 @@ #include "item.h" #include "kb.h" #include "loadsave.h" +#include "loop.h" #include "map.h" #include "memory.h" #include "message.h" @@ -102,7 +103,8 @@ static int _compare_faster(const void* a1, const void* a2); static void _combat_sequence_init(Object* a1, Object* a2); static void _combat_sequence(); static void combatAttemptEnd(); -static int _combat_input(); +static int combatInput(); +static int combatInputInner(); static void _combat_set_move_all(); static int _combat_turn(Object* a1, bool a2); static bool _combat_should_end(); @@ -3125,8 +3127,17 @@ void _combat_turn_run() } } +// Wrapper for combatInput, setting LoopFlag::COMBAT_PLAYER_TURN +// (see sfall: PlayerCombatHook) +static int combatInput() { + loopSetFlag(LoopFlag::COMBAT_PLAYER_TURN); + int result = combatInputInner(); + loopClearFlag(LoopFlag::COMBAT_PLAYER_TURN); + return result; +} + // 0x4227F4 -static int _combat_input() +static int combatInputInner() { while ((gCombatState & COMBAT_STATE_0x02) != 0) { sharedFpsLimiter.mark(); @@ -3271,7 +3282,7 @@ static int _combat_turn(Object* a1, bool a2) _combat_outline_on(); } - if (_combat_input() == -1) { + if (combatInput() == -1) { gameUiDisable(1); gameMouseSetCursor(MOUSE_CURSOR_WAIT_WATCH); a1->data.critter.combat.damageLastTurn = 0; @@ -3366,6 +3377,8 @@ static bool _combat_should_end() // 0x422D2C void _combat(STRUCT_664980* attack) { + loopSetFlag(LoopFlag::COMBAT); + if (attack == NULL || (attack->attacker == NULL || attack->attacker->elevation == gElevation) || (attack->defender == NULL || attack->defender->elevation == gElevation)) { @@ -3449,6 +3462,8 @@ void _combat(STRUCT_664980* attack) _game_user_wants_to_quit = 0; } } + + loopClearFlag(LoopFlag::COMBAT); } // 0x422EC4 diff --git a/src/game.cc b/src/game.cc index 5ea3043f..b78ac447 100644 --- a/src/game.cc +++ b/src/game.cc @@ -39,6 +39,8 @@ #include "item.h" #include "kb.h" #include "loadsave.h" +#include "loop.h" +#include "main.h" #include "map.h" #include "memory.h" #include "mouse.h" @@ -352,6 +354,7 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4 // 0x442B84 void gameReset() { + mainSetIsGameLoaded(false); tileDisable(); paletteReset(); randomReset(); @@ -819,7 +822,9 @@ int gameHandleKey(int eventCode, bool isInCombatMode) break; case KEY_F1: soundPlayFile("ib1p1xx1"); + loopSetFlag(LoopFlag::HELP); showHelp(); + loopClearFlag(LoopFlag::HELP); break; case KEY_F2: gameSoundSetMasterVolume(gameSoundGetMasterVolume() - 2047); diff --git a/src/game_dialog.cc b/src/game_dialog.cc index b14066f2..cf0ded18 100644 --- a/src/game_dialog.cc +++ b/src/game_dialog.cc @@ -24,6 +24,7 @@ #include "item.h" #include "kb.h" #include "lips.h" +#include "loop.h" #include "memory.h" #include "mouse.h" #include "object.h" @@ -920,6 +921,8 @@ int _gdialogInitFromScript(int headFid, int reaction) backgroundSoundDelete(); } + loopSetFlag(LoopFlag::DIALOG); + _gdDialogWentOff = true; return 0; @@ -947,6 +950,8 @@ int _gdialogExitFromScript() _tile_scroll_to(gGameDialogOldCenterTile, 2); } + loopClearFlag(LoopFlag::DIALOG); + _gdDestroyHeadWindow(); // CE: Fix Barter button. @@ -1437,6 +1442,8 @@ int gameDialogShowReview() return -1; } + loopSetFlag(LoopFlag::DIALOG_REVIEW); + // probably current top line or something like this, which is used to scroll int v1 = 0; gameDialogReviewWindowUpdate(win, v1); @@ -1474,6 +1481,8 @@ int gameDialogShowReview() sharedFpsLimiter.throttle(); } + loopClearFlag(LoopFlag::DIALOG_REVIEW); + if (gameDialogReviewWindowFree(&win) == -1) { return -1; } diff --git a/src/input.cc b/src/input.cc index 9d61b694..9f615655 100644 --- a/src/input.cc +++ b/src/input.cc @@ -1,14 +1,18 @@ #include "input.h" #include +#include #include "audio_engine.h" #include "color.h" #include "dinput.h" #include "draw.h" #include "kb.h" +#include "loop.h" +#include "main.h" #include "memory.h" #include "mouse.h" +#include "sfall_config.h" #include "svga.h" #include "text_font.h" #include "vcr.h" @@ -116,6 +120,28 @@ static TickerListNode* gTickerListHead; // 0x6AC788 static unsigned int gTickerLastTimestamp; +static bool gSpeedPatchEnabled; +static int gSpeedMultiInitial; +static float gSpeedMulti; +static unsigned int gLastTickCount; +static unsigned int gStoredTickCount; +static float gTickCountFraction; +static time_t gStartTime; +static bool gDefaultDelay; + +static void SetKeyboardDefaultDelay() { + if (gDefaultDelay) return; + gDefaultDelay = true; + gKeyboardKeyRepeatRate = INPUT_DEFAULT_KEYBOARD_KEY_REPEAT_RATE; + gKeyboardKeyRepeatDelay = INPUT_DEFAULT_KEYBOARD_KEY_REPEAT_DELAY; +} + +static void SetKeyboardDelay() { + gKeyboardKeyRepeatRate = static_cast(INPUT_DEFAULT_KEYBOARD_KEY_REPEAT_RATE * gSpeedMulti); + gKeyboardKeyRepeatDelay = static_cast(INPUT_DEFAULT_KEYBOARD_KEY_REPEAT_DELAY * gSpeedMulti); + gDefaultDelay = false; +} + // 0x4C8A70 int inputInit(int a1) { @@ -155,6 +181,18 @@ int inputInit(int a1) // CE: Prevents frying CPU when window is not focused. inputSetIdleFunc(idleImpl); + // SFALL: Speed patch + gSpeedPatchEnabled = false; + configGetBool(&gSfallConfig, SFALL_CONFIG_SPEED_KEY, SFALL_CONFIG_SPEED_ENABLE_KEY, &gSpeedPatchEnabled); + gSpeedMultiInitial = 100; + configGetInt(&gSfallConfig, SFALL_CONFIG_SPEED_KEY, SFALL_CONFIG_SPEED_MULTI_INITIAL_KEY, &gSpeedMultiInitial); + gSpeedMulti = gSpeedMultiInitial / 100.0f; + gLastTickCount = SDL_GetTicks(); + gStoredTickCount = 0; + gTickCountFraction = 0.0f; + gStartTime = time(NULL); + gDefaultDelay = true; + return 0; } @@ -304,7 +342,7 @@ void tickersExecute() return; } - gTickerLastTimestamp = SDL_GetTicks(); + gTickerLastTimestamp = getTicks(); TickerListNode* curr = gTickerListHead; TickerListNode** currPtr = &(gTickerListHead); @@ -606,9 +644,51 @@ void screenshotHandlerConfigure(int keyCode, ScreenshotHandler* handler) } // 0x4C9370 +// Since implementing sfall SpeedPatch, this returns a potentially sped up +// (multiplied) tick count. For the original tick count, call SDL_GetTicks(); unsigned int getTicks() { - return SDL_GetTicks(); + unsigned int newTickCount = SDL_GetTicks(); + if (newTickCount == gLastTickCount) return gStoredTickCount; + + // Just in case someone's been running their computer for 49 days straight + if (gLastTickCount > newTickCount) { + gLastTickCount = newTickCount; + return gStoredTickCount; + } + + float elapsed = static_cast(newTickCount - gLastTickCount); + gLastTickCount = newTickCount; + + // Multiply the tick count difference by the multiplier + if (mainIsGameLoaded() + && gSpeedPatchEnabled + && !mainIsInEndgameSlideshow() + && (loopIsInWorldMap() + || loopIsInCombatEnemyTurn() + || loopIsInCombatWaitingForPlayerAction() + || loopIsOutsideCombatWaitingForPlayerAction() + ) + ) { + elapsed *= gSpeedMulti; + elapsed += gTickCountFraction; + gTickCountFraction = modff(gTickCountFraction, &gTickCountFraction); + if (gDefaultDelay) SetKeyboardDelay(); + } else { + SetKeyboardDefaultDelay(); + } + + gStoredTickCount += static_cast(elapsed); + + return gStoredTickCount; +} + +// Done by sfall (presumably) because this time gets converted to game time. +// If you've played the game at 8x speed for a while, you'll want the time in +// the savefile to agree with the time in the game at the time you saved it. +time_t getLocalTimeAfterSpeedup() +{ + return gStartTime + gStoredTickCount / 1000; } // 0x4C937C @@ -633,7 +713,7 @@ void inputPauseForTocks(unsigned int delay) // 0x4C93B8 void inputBlockForTocks(unsigned int ms) { - unsigned int start = SDL_GetTicks(); + unsigned int start = getTicks(); unsigned int diff; do { // NOTE: Uninline @@ -644,7 +724,7 @@ void inputBlockForTocks(unsigned int ms) // 0x4C93E0 unsigned int getTicksSince(unsigned int start) { - unsigned int end = SDL_GetTicks(); + unsigned int end = getTicks(); // NOTE: Uninline. return getTicksBetween(end, start); diff --git a/src/input.h b/src/input.h index 6728480d..1f820bf6 100644 --- a/src/input.h +++ b/src/input.h @@ -1,8 +1,13 @@ #ifndef FALLOUT_INPUT_H_ #define FALLOUT_INPUT_H_ +#include + namespace fallout { +#define INPUT_DEFAULT_KEYBOARD_KEY_REPEAT_RATE 80 +#define INPUT_DEFAULT_KEYBOARD_KEY_REPEAT_DELAY 500 + typedef void(IdleFunc)(); typedef void(FocusFunc)(bool focus); typedef void(TickerProc)(); @@ -26,6 +31,7 @@ void takeScreenshot(); int screenshotHandlerDefaultImpl(int width, int height, unsigned char* data, unsigned char* palette); void screenshotHandlerConfigure(int keyCode, ScreenshotHandler* handler); unsigned int getTicks(); +time_t getLocalTimeAfterSpeedup(); void inputPauseForTocks(unsigned int ms); void inputBlockForTocks(unsigned int ms); unsigned int getTicksSince(unsigned int a1); diff --git a/src/inventory.cc b/src/inventory.cc index e2f4d9ee..0c481ce1 100644 --- a/src/inventory.cc +++ b/src/inventory.cc @@ -27,6 +27,7 @@ #include "item.h" #include "kb.h" #include "light.h" +#include "loop.h" #include "map.h" #include "message.h" #include "mouse.h" @@ -585,6 +586,9 @@ void inventoryOpen() reg_anim_clear(_inven_dude); inventoryRenderSummary(); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_NORMAL); + + loopSetFlag(LoopFlag::INVENTORY); + inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND); for (;;) { @@ -706,6 +710,8 @@ void inventoryOpen() } } + loopClearFlag(LoopFlag::INVENTORY); + _exit_inventory(isoWasEnabled); // NOTE: Uninline. @@ -2624,6 +2630,9 @@ void inventoryOpenUseItemOn(Object* a1) bool isoWasEnabled = _setup_inventory(INVENTORY_WINDOW_TYPE_USE_ITEM_ON); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_USE_ITEM_ON); + + loopSetFlag(LoopFlag::USE_INTERFACE); + inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND); for (;;) { sharedFpsLimiter.mark(); @@ -2743,6 +2752,8 @@ void inventoryOpenUseItemOn(Object* a1) sharedFpsLimiter.throttle(); } + loopClearFlag(LoopFlag::USE_INTERFACE); + _exit_inventory(isoWasEnabled); // NOTE: Uninline. @@ -4218,6 +4229,9 @@ int inventoryOpenLooting(Object* a1, Object* a2) _display_target_inventory(_target_stack_offset[_target_curr_stack], -1, _target_pud, INVENTORY_WINDOW_TYPE_LOOT); _display_inventory(_stack_offset[_curr_stack], -1, INVENTORY_WINDOW_TYPE_LOOT); _display_body(a2->fid, INVENTORY_WINDOW_TYPE_LOOT); + + loopSetFlag(LoopFlag::LOOT_INTERFACE); + inventorySetCursor(INVENTORY_WINDOW_CURSOR_HAND); bool isCaughtStealing = false; @@ -4466,6 +4480,8 @@ int inventoryOpenLooting(Object* a1, Object* a2) } } + loopClearFlag(LoopFlag::LOOT_INTERFACE); + _exit_inventory(isoWasEnabled); // NOTE: Uninline. @@ -5024,6 +5040,8 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5) return; } + loopSetFlag(LoopFlag::BARTER); + Object* armor = critterGetArmor(a2); if (armor != NULL) { itemRemove(a2, armor, 1); @@ -5338,6 +5356,8 @@ void inventoryOpenTrade(int win, Object* a2, Object* a3, Object* a4, int a5) itemAdd(a2, item1, 1); } + loopClearFlag(LoopFlag::BARTER); + _exit_inventory(isoWasEnabled); // NOTE: Uninline. @@ -5725,6 +5745,8 @@ static int inventoryQuantitySelect(int inventoryWindowType, Object* item, int ma // 0x476AB8 static int inventoryQuantityWindowInit(int inventoryWindowType, Object* item) { + loopSetFlag(LoopFlag::COUNTER_WINDOW); + const int oldFont = fontGetCurrent(); fontSetCurrent(103); @@ -5945,6 +5967,8 @@ static int inventoryQuantityWindowFree(int inventoryWindowType) _moveFrmImages[index].unlock(); } + loopClearFlag(LoopFlag::COUNTER_WINDOW); + windowDestroy(_mt_wid); return 0; diff --git a/src/loadsave.cc b/src/loadsave.cc index a23c01f8..8d92899f 100644 --- a/src/loadsave.cc +++ b/src/loadsave.cc @@ -30,6 +30,8 @@ #include "interface.h" #include "item.h" #include "kb.h" +#include "loop.h" +#include "main.h" #include "map.h" #include "memory.h" #include "message.h" @@ -149,6 +151,8 @@ static int _QuickSnapShot(); static int lsgWindowInit(int windowType); static int lsgWindowFree(int windowType); static int lsgPerformSaveGame(); +int lsgSaveGameInner(int mode); +static int lsgLoadGameInner(int slot); static int lsgLoadGameInSlot(int slot); static int lsgSaveHeaderInSlot(int slot); static int lsgLoadHeaderInSlot(int slot); @@ -326,6 +330,7 @@ static int gLoadSaveWindowOldFont; static FrmImage _loadsaveFrmImages[LOAD_SAVE_FRM_COUNT]; + // 0x47B7E4 void _InitLoadSave() { @@ -346,9 +351,19 @@ void _ResetLoadSave() _MapDirErase(PROTO_DIR_NAME "\\" ITEMS_DIR_NAME "\\", PROTO_FILE_EXT); } +// Wrapper for SaveGame, setting LoopFlag::SAVEGAME +// (see sfall: SaveGame_hook) +int lsgSaveGame(int mode) +{ + loopSetFlag(LoopFlag::SAVEGAME); + int result = lsgSaveGameInner(mode); + loopClearFlag(LoopFlag::SAVEGAME); + return result; +} + // SaveGame // 0x47B88C -int lsgSaveGame(int mode) +int lsgSaveGameInner(int mode) { MessageListItem messageListItem; @@ -850,9 +865,23 @@ static int _QuickSnapShot() return 1; } +// Wrapper for LoadGame, setting the main::isGameLoaded flag if successful +// (see sfall: LoadGame_hook and LoadGame_After) +int lsgLoadGame(int mode) { + loopSetFlag(LoopFlag::LOADGAME); + int result = lsgLoadGameInner(mode); + loopClearFlag(LoopFlag::LOADGAME); + + if (result == 1) { + mainSetIsGameLoaded(true); + } + + return result; +} + // LoadGame // 0x47C640 -int lsgLoadGame(int mode) +int lsgLoadGameInner(int mode) { MessageListItem messageListItem; @@ -1714,7 +1743,7 @@ static int lsgSaveHeaderInSlot(int slot) return -1; } - time_t now = time(NULL); + time_t now = getLocalTimeAfterSpeedup(); struct tm* local = localtime(&now); temp[0] = local->tm_mday; diff --git a/src/loop.cc b/src/loop.cc new file mode 100644 index 00000000..3b60e099 --- /dev/null +++ b/src/loop.cc @@ -0,0 +1,45 @@ +#include "loop.h" + +namespace fallout { + +static uint32_t loopFlags = 0; + +// low-level API + +uint32_t loopCurrentFlags() { + return loopFlags; +} + +bool loopGetFlag(LoopFlag flag) { + return loopFlags & flag; +} + +void loopSetFlag(LoopFlag flag) { + loopFlags |= flag; +} + +void loopClearFlag(LoopFlag flag) { + loopFlags &= ~flag; +} + +// high-level helpers + +bool loopIsInWorldMap() { + return loopFlags & LoopFlag::WORLDMAP; +} + +bool loopIsInCombatEnemyTurn() { + return loopFlags == LoopFlag::COMBAT; +} + +// with no menus open +bool loopIsInCombatWaitingForPlayerAction() { + return loopFlags == (LoopFlag::COMBAT | LoopFlag::COMBAT_PLAYER_TURN); +} + +// with no menus open +bool loopIsOutsideCombatWaitingForPlayerAction() { + return !loopFlags; +} + +} // namespace fallout diff --git a/src/loop.h b/src/loop.h new file mode 100644 index 00000000..bd67df07 --- /dev/null +++ b/src/loop.h @@ -0,0 +1,48 @@ +#ifndef FALLOUT_LOOP_H_ +#define FALLOUT_LOOP_H_ + +#include + +namespace fallout { + +enum LoopFlag : unsigned long { + WORLDMAP = 1 << 0, // 0x1 +// RESERVED = 1 << 1, // 0x2 (unused) + DIALOG = 1 << 2, // 0x4 + ESCMENU = 1 << 3, // 0x8 + SAVEGAME = 1 << 4, // 0x10 + LOADGAME = 1 << 5, // 0x20 + COMBAT = 1 << 6, // 0x40 + OPTIONS = 1 << 7, // 0x80 + HELP = 1 << 8, // 0x100 + CHARSCREEN = 1 << 9, // 0x200 + PIPBOY = 1 << 10, // 0x400 + COMBAT_PLAYER_TURN = 1 << 11, // 0x800 + INVENTORY = 1 << 12, // 0x1000 + AUTOMAP = 1 << 13, // 0x2000 + SKILLDEX = 1 << 14, // 0x4000 + USE_INTERFACE = 1 << 15, // 0x8000 + LOOT_INTERFACE = 1 << 16, // 0x10000 + BARTER = 1 << 17, // 0x20000 +// HERO_WINDOW = 1 << 18, // 0x40000 Hero Appearance mod + DIALOG_REVIEW = 1 << 19, // 0x80000 + COUNTER_WINDOW = 1 << 20, // 0x100000 Counter window for moving multiple items or setting a timer + +// SPECIAL = 1UL << 31 // 0x80000000 Additional special flag for all modes +}; + +// low-level API +uint32_t loopCurrentFlags(); +bool loopGetFlag(LoopFlag flag); +void loopSetFlag(LoopFlag flag); +void loopClearFlag(LoopFlag flag); + +// high-level predicates +bool loopIsInWorldMap(); +bool loopIsInCombatEnemyTurn(); +bool loopIsInCombatWaitingForPlayerAction(); // with no menus open +bool loopIsOutsideCombatWaitingForPlayerAction(); // with no menus open + +} // namespace fallout + +#endif /* FALLOUT_LOOP_H_ */ diff --git a/src/main.cc b/src/main.cc index 027006e8..93ba8615 100644 --- a/src/main.cc +++ b/src/main.cc @@ -172,6 +172,9 @@ static FrmImage _mainMenuBackgroundFrmImage; static FrmImage _mainMenuButtonNormalFrmImage; static FrmImage _mainMenuButtonPressedFrmImage; +static bool gIsGameLoaded = false; +static bool gIsInEndgameSlideshow = false; + // 0x48099C int falloutMain(int argc, char** argv) { @@ -228,6 +231,8 @@ int falloutMain(int argc, char** argv) _main_load_new(mapNameCopy); free(mapNameCopy); + gIsGameLoaded = true; + mainLoop(); paletteFadeTo(gPaletteWhite); @@ -1109,4 +1114,21 @@ static void main_menu_play_sound(const char* fileName) soundPlayFile(fileName); } +// True if game was started, false when on the main menu +bool mainIsGameLoaded() { + return gIsGameLoaded; +} + +void mainSetIsGameLoaded(bool isGameLoaded) { + gIsGameLoaded = isGameLoaded; +} + +bool mainIsInEndgameSlideshow() { + return gIsInEndgameSlideshow; +} + +void mainSetIsInEndgameSlideshow(bool isInEndgameSlideshow) { + gIsInEndgameSlideshow = isInEndgameSlideshow; +} + } // namespace fallout diff --git a/src/main.h b/src/main.h index bd63c8e9..c113c209 100644 --- a/src/main.h +++ b/src/main.h @@ -5,6 +5,13 @@ namespace fallout { int falloutMain(int argc, char** argv); +// True if game was started, false when on the main menu +bool mainIsGameLoaded(); +void mainSetIsGameLoaded(bool isGameLoaded); + +bool mainIsInEndgameSlideshow(); +void mainSetIsInEndgameSlideshow(bool isInEndgameSlideshow); + } // namespace fallout #endif /* MAIN_H */ diff --git a/src/options.cc b/src/options.cc index 9cb11424..462dbd66 100644 --- a/src/options.cc +++ b/src/options.cc @@ -21,6 +21,7 @@ #include "input.h" #include "kb.h" #include "loadsave.h" +#include "loop.h" #include "memory.h" #include "message.h" #include "mouse.h" @@ -455,14 +456,26 @@ int gPreferencesCombatLooks1; static FrmImage _optionsFrmImages[OPTIONS_WINDOW_FRM_COUNT]; static FrmImage _preferencesFrmImages[PREFERENCES_WINDOW_FRM_COUNT]; +int showOptionsWithInitialKeyCodeInner(int initialKeyCode); + +// _do_options // 0x48FC48 int showOptions() { return showOptionsWithInitialKeyCode(-1); } +// Wrapper for do_optionsFunc_, setting LoopFlag::ESCMENU +// (see sfall: EscMenuHook) +int showOptionsWithInitialKeyCode(int initialKeyCode) { + loopSetFlag(LoopFlag::ESCMENU); + int result = showOptionsWithInitialKeyCodeInner(initialKeyCode); + loopClearFlag(LoopFlag::ESCMENU); + return result; +} + // 0x48FC50 -int showOptionsWithInitialKeyCode(int initialKeyCode) +int showOptionsWithInitialKeyCodeInner(int initialKeyCode) { if (optionsWindowInit() == -1) { debugPrint("\nOPTION MENU: Error loading option dialog data!\n"); @@ -527,7 +540,9 @@ int showOptionsWithInitialKeyCode(int initialKeyCode) } if (showPreferences) { + loopSetFlag(LoopFlag::OPTIONS); _do_prefscreen(); + loopClearFlag(LoopFlag::OPTIONS); } else { switch (keyCode) { case KEY_F12: @@ -2063,10 +2078,4 @@ static void _DoThing(int eventCode) _changed = true; } -// 0x48FC48 -int _do_options() -{ - return showOptionsWithInitialKeyCode(-1); -} - } // namespace fallout diff --git a/src/pipboy.cc b/src/pipboy.cc index b553fdc4..df08a315 100644 --- a/src/pipboy.cc +++ b/src/pipboy.cc @@ -22,6 +22,7 @@ #include "input.h" #include "interface.h" #include "kb.h" +#include "loop.h" #include "map.h" #include "memory.h" #include "message.h" @@ -541,6 +542,8 @@ static int pipboyWindowInit(int intent) return -1; } + loopSetFlag(LoopFlag::PIPBOY); + int pipboyWindowX = (screenGetWidth() - PIPBOY_WINDOW_WIDTH) / 2; int pipboyWindowY = (screenGetHeight() - PIPBOY_WINDOW_HEIGHT) / 2; gPipboyWindow = windowCreate(pipboyWindowX, pipboyWindowY, PIPBOY_WINDOW_WIDTH, PIPBOY_WINDOW_HEIGHT, _colorTable[0], WINDOW_FLAG_0x10); @@ -706,6 +709,8 @@ static void pipboyWindowFree() scriptsExecMapUpdateProc(); + loopClearFlag(LoopFlag::PIPBOY); + windowDestroy(gPipboyWindow); messageListFree(&gPipboyMessageList); diff --git a/src/scripts.cc b/src/scripts.cc index d5bf37c2..55d6a8ef 100644 --- a/src/scripts.cc +++ b/src/scripts.cc @@ -21,6 +21,7 @@ #include "game_mouse.h" #include "game_movie.h" #include "input.h" +#include "main.h" #include "memory.h" #include "message.h" #include "object.h" @@ -1006,7 +1007,9 @@ int scriptsHandleRequests() if ((gScriptsRequests & SCRIPT_REQUEST_ENDGAME) != 0) { gScriptsRequests &= ~SCRIPT_REQUEST_ENDGAME; + mainSetIsInEndgameSlideshow(true); endgamePlaySlideshow(); + mainSetIsInEndgameSlideshow(false); endgamePlayMovie(); } diff --git a/src/sfall_config.h b/src/sfall_config.h index 7b4f83e2..5e72b61e 100644 --- a/src/sfall_config.h +++ b/src/sfall_config.h @@ -7,6 +7,7 @@ namespace fallout { #define SFALL_CONFIG_FILE_NAME "ddraw.ini" +#define SFALL_CONFIG_SPEED_KEY "Speed" #define SFALL_CONFIG_MISC_KEY "Misc" #define SFALL_CONFIG_DUDE_NATIVE_LOOK_JUMPSUIT_MALE_KEY "MaleDefaultModel" @@ -59,6 +60,8 @@ namespace fallout { #define SFALL_CONFIG_TWEAKS_FILE_KEY "TweaksFile" #define SFALL_CONFIG_GAME_DIALOG_GENDER_WORDS_KEY "DialogGenderWords" #define SFALL_CONFIG_TOWN_MAP_HOTKEYS_FIX "TownMapHotkeysFix" +#define SFALL_CONFIG_SPEED_ENABLE_KEY "Enable" +#define SFALL_CONFIG_SPEED_MULTI_INITIAL_KEY "SpeedMultiInitial" #define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_MULTIPLIER 1 #define SFALL_CONFIG_BURST_MOD_DEFAULT_CENTER_DIVISOR 3 diff --git a/src/skilldex.cc b/src/skilldex.cc index feb32be3..160b024f 100644 --- a/src/skilldex.cc +++ b/src/skilldex.cc @@ -15,6 +15,7 @@ #include "input.h" #include "interface.h" #include "kb.h" +#include "loop.h" #include "map.h" #include "memory.h" #include "message.h" @@ -105,9 +106,20 @@ static int gSkilldexWindowOldFont; static FrmImage _skilldexFrmImages[SKILLDEX_FRM_COUNT]; +static int skilldexOpenInner(); + +// Wrapper for skilldex_select, setting LoopFlag::SKILLDEX +// (see sfall: SkilldexHook) +int skilldexOpen() { + loopSetFlag(LoopFlag::SKILLDEX); + int rc = skilldexOpenInner(); + loopClearFlag(LoopFlag::SKILLDEX); + return rc; +} + // skilldex_select // 0x4ABFD0 -int skilldexOpen() +int skilldexOpenInner() { if (skilldexWindowInit() == -1) { debugPrint("\n ** Error loading skilldex dialog data! **\n"); diff --git a/src/window_manager.cc b/src/window_manager.cc index 6e13b3e3..867c87d6 100644 --- a/src/window_manager.cc +++ b/src/window_manager.cc @@ -413,7 +413,7 @@ int windowCreate(int x, int y, int width, int height, int a4, int flags) return index; } -// win_remove +// win_remove, win_delete // 0x4D6468 void windowDestroy(int win) { diff --git a/src/worldmap.cc b/src/worldmap.cc index 481ca00e..5da9d9ff 100644 --- a/src/worldmap.cc +++ b/src/worldmap.cc @@ -27,6 +27,7 @@ #include "interface.h" #include "item.h" #include "kb.h" +#include "loop.h" #include "memory.h" #include "mouse.h" #include "object.h" @@ -2941,6 +2942,8 @@ static int wmWorldMapFunc(int a1) return -1; } + loopSetFlag(LoopFlag::WORLDMAP); + wmMatchWorldPosToArea(wmGenData.worldPosX, wmGenData.worldPosY, &(wmGenData.currentAreaId)); unsigned int v24 = 0; @@ -4695,6 +4698,8 @@ static int wmInterfaceExit() int i; TileInfo* tile; + loopClearFlag(LoopFlag::WORLDMAP); + tickersRemove(wmMouseBkProc); _backgroundFrmImage.unlock();