diff options
author | Martin Kiewitz | 2016-02-28 15:50:25 +0100 |
---|---|---|
committer | Martin Kiewitz | 2016-02-28 15:50:25 +0100 |
commit | e6466b20fa510187aaa277756a86ebc71ebf96b8 (patch) | |
tree | f9bf90e15c1ed585e821c0c18e90592781c84c4f | |
parent | aded46f08b476ee1caccc070b8495cafe7094b47 (diff) | |
download | scummvm-rg350-e6466b20fa510187aaa277756a86ebc71ebf96b8.tar.gz scummvm-rg350-e6466b20fa510187aaa277756a86ebc71ebf96b8.tar.bz2 scummvm-rg350-e6466b20fa510187aaa277756a86ebc71ebf96b8.zip |
AGI: Add optional "pause, when entering commands" feature
Shows a prompt window and pauses the game (just like original AGI
did, but original AGI only did it in Hercules rendering mode).
-rw-r--r-- | engines/agi/detection.cpp | 10 | ||||
-rw-r--r-- | engines/agi/detection_tables.h | 7 | ||||
-rw-r--r-- | engines/agi/systemui.cpp | 43 | ||||
-rw-r--r-- | engines/agi/systemui.h | 4 | ||||
-rw-r--r-- | engines/agi/text.cpp | 96 | ||||
-rw-r--r-- | engines/agi/text.h | 4 | ||||
-rw-r--r-- | engines/agi/words.cpp | 2 | ||||
-rw-r--r-- | engines/agi/words.h | 2 |
8 files changed, 147 insertions, 21 deletions
diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index 308489ad0b..7127584ba0 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -181,6 +181,16 @@ static const ADExtraGuiOptionsMap optionsList[] = { } }, + { + GAMEOPTION_COMMAND_PROMPT_WINDOW, + { + _s("Pause, when entering commands"), + _s("Shows a command prompt window and pauses the game (like in SCI) instead of a real-time prompt."), + "commandpromptwindow", + false + } + }, + AD_EXTRA_GUI_OPTIONS_TERMINATOR }; diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h index 87da0c2c01..0938e9d4d6 100644 --- a/engines/agi/detection_tables.h +++ b/engines/agi/detection_tables.h @@ -26,11 +26,12 @@ namespace Agi { #define GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE GUIO_GAMEOPTIONS2 #define GAMEOPTION_DISABLE_MOUSE GUIO_GAMEOPTIONS3 #define GAMEOPTION_USE_HERCULES_FONT GUIO_GAMEOPTIONS4 +#define GAMEOPTION_COMMAND_PROMPT_WINDOW GUIO_GAMEOPTIONS5 // TODO: properly implement GAMEOPTIONs -#define GAMEOPTIONS_DEFAULT GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE,GAMEOPTION_USE_HERCULES_FONT) -#define GAMEOPTIONS_AMIGA GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE,GAMEOPTION_USE_HERCULES_FONT) -#define GAMEOPTIONS_FANMADE_MOUSE GUIO2(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_USE_HERCULES_FONT) +#define GAMEOPTIONS_DEFAULT GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_DISABLE_MOUSE,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW) +#define GAMEOPTIONS_AMIGA GUIO4(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_AMIGA_ALTERNATIVE_PALETTE,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW) +#define GAMEOPTIONS_FANMADE_MOUSE GUIO3(GAMEOPTION_ORIGINAL_SAVELOAD,GAMEOPTION_USE_HERCULES_FONT,GAMEOPTION_COMMAND_PROMPT_WINDOW) #define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp,guioptions) { \ { \ diff --git a/engines/agi/systemui.cpp b/engines/agi/systemui.cpp index 7aa26131c9..aeb1ded4a2 100644 --- a/engines/agi/systemui.cpp +++ b/engines/agi/systemui.cpp @@ -44,6 +44,8 @@ SystemUI::SystemUI(AgiEngine *vm, GfxMgr *gfx, TextMgr *text) { _textStatusSoundOn = "Sound:on"; _textStatusSoundOff = "Sound:off"; + _textEnterCommand = "Enter input\n\n"; + _textPause = " Game paused.\nPress Enter to continue."; _textPauseButton = nullptr; @@ -214,6 +216,47 @@ const char *SystemUI::getInventoryTextReturnToGame() { return _textInventoryReturnToGame; } +bool SystemUI::askForCommand(Common::String &commandText) { + // Let user enter the command (this was originally only available for Hercules rendering, we allow it everywhere) + bool previousEditState = _text->inputGetEditStatus(); + byte previousEditCursor = _text->inputGetCursorChar(); + + _text->drawMessageBox(_textEnterCommand, 0, 36, true); + + _text->inputEditOn(); + + _text->charPos_Push(); + _text->charAttrib_Push(); + + _text->charPos_SetInsideWindow(2, 0); + _text->charAttrib_Set(15, 0); + _text->clearBlockInsideWindow(2, 0, 36, 0); // input line is supposed to be black + _text->inputSetCursorChar('_'); + + _text->stringSet(commandText.c_str()); // Set current command text (may be a command recall) + + _vm->cycleInnerLoopActive(CYCLE_INNERLOOP_GETSTRING); + _text->stringEdit(35); // only allow up to 35 characters + + _text->charAttrib_Pop(); + _text->charPos_Pop(); + _text->inputSetCursorChar(previousEditCursor); + if (!previousEditState) { + _text->inputEditOff(); + } + + _text->closeWindow(); + + if (!_text->stringWasEntered()) { + // User cancelled? exit now + return false; + } + + commandText.clear(); + commandText += (char *)_text->_inputString; + return true; +} + int16 SystemUI::figureOutAutomaticSaveGameSlot(const char *automaticSaveDescription) { int16 matchedGameSlotId = -1; int16 freshGameSlotId = -1; diff --git a/engines/agi/systemui.h b/engines/agi/systemui.h index ffb1238ebe..283de8794c 100644 --- a/engines/agi/systemui.h +++ b/engines/agi/systemui.h @@ -77,6 +77,8 @@ public: const char *getInventoryTextSelectItems(); const char *getInventoryTextReturnToGame(); + bool askForCommand(Common::String &commandText); + int16 figureOutAutomaticSaveGameSlot(const char *automaticSaveDescription); int16 figureOutAutomaticRestoreGameSlot(const char *automaticSaveDescription); @@ -130,6 +132,8 @@ private: const char *_textStatusSoundOn; const char *_textStatusSoundOff; + const char *_textEnterCommand; + const char *_textPause; const char *_textPauseButton; const char *_textRestart; diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index 18254d88f8..0cacce2421 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -20,6 +20,7 @@ * */ +#include "common/config-manager.h" #include "agi/agi.h" #include "agi/sprite.h" // for commit_both() #include "agi/graphics.h" @@ -74,6 +75,12 @@ TextMgr::TextMgr(AgiEngine *vm, Words *words, GfxMgr *gfx) { configureScreen(2); _messageBoxCancelled = false; + + _optionCommandPromptWindow = false; + + if (ConfMan.getBool("commandpromptwindow")) { + _optionCommandPromptWindow = true; + } } TextMgr::~TextMgr() { @@ -671,6 +678,30 @@ void TextMgr::promptKeyPress(uint16 newKey) { int16 maxChars = 0; int16 scriptsInputLen = _vm->getVar(VM_VAR_MAX_INPUT_CHARACTERS); + bool acceptableInput = false; + + // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.) + // In text-mode this sort of worked at least with the DOS interpreter + // but as soon as invalid characters were used in graphics mode they weren't properly shown + switch (_vm->getLanguage()) { + case Common::RU_RUS: + if (newKey >= 0x20) + acceptableInput = true; + break; + default: + if ((newKey >= 0x20) && (newKey <= 0x7f)) + acceptableInput = true; + break; + } + + if (_optionCommandPromptWindow) { + // Forward to command prompt window, using last command + if (acceptableInput) { + promptCommandWindow(false, newKey); + } + return; + } + if (_messageState.dialogue_Open) { maxChars = TEXT_STRING_MAX_SIZE - 4; } else { @@ -715,22 +746,6 @@ void TextMgr::promptKeyPress(uint16 newKey) { } default: if (maxChars > _promptCursorPos) { - bool acceptableInput = false; - - // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.) - // In text-mode this sort of worked at least with the DOS interpreter - // but as soon as invalid characters were used in graphics mode they weren't properly shown - switch (_vm->getLanguage()) { - case Common::RU_RUS: - if (newKey >= 0x20) - acceptableInput = true; - break; - default: - if ((newKey >= 0x20) && (newKey <= 0x7f)) - acceptableInput = true; - break; - } - if (acceptableInput) { _prompt[_promptCursorPos] = newKey; _promptCursorPos++; @@ -747,6 +762,11 @@ void TextMgr::promptKeyPress(uint16 newKey) { } void TextMgr::promptCancelLine() { + if (_optionCommandPromptWindow) { + // Abort, in case command prompt window is active + return; + } + while (_promptCursorPos) { promptKeyPress(0x08); // Backspace until prompt is empty } @@ -755,6 +775,12 @@ void TextMgr::promptCancelLine() { void TextMgr::promptEchoLine() { int16 previousLen = strlen((char *)_promptPrevious); + if (_optionCommandPromptWindow) { + // Forward to command prompt window, using last command + promptCommandWindow(true, 0); + return; + } + if (_promptCursorPos < previousLen) { inputEditOn(); @@ -771,6 +797,11 @@ void TextMgr::promptRedraw() { char *textPtr = nullptr; if (_promptEnabled) { + if (_optionCommandPromptWindow) { + // Abort, in case command prompt window is active + return; + } + inputEditOn(); clearLine(_promptRow, _textAttrib.background); charPos_Set(_promptRow, 0); @@ -788,6 +819,10 @@ void TextMgr::promptRedraw() { // for AGI1 void TextMgr::promptClear() { + if (_optionCommandPromptWindow) { + // Abort, in case command prompt window is active + return; + } clearLine(_promptRow, _textAttrib.background); } @@ -797,6 +832,35 @@ void TextMgr::promptRememberForAutoComplete(bool entered) { #endif } +void TextMgr::promptCommandWindow(bool recallLastCommand, uint16 newKey) { + Common::String commandText; + + if (recallLastCommand) { + commandText += Common::String((char *)_promptPrevious); + } + if (newKey) { + if (newKey != ' ') { + // Only add char, when it's not a space. + // Original AGI did not filter space, but it makes no sense to start with a space. + // Space would get filtered anyway during dictionary parsing. + commandText += newKey; + } + } + + if (_systemUI->askForCommand(commandText)) { + if (commandText.size()) { + // Something actually was entered? + strncpy((char *)&_prompt, commandText.c_str(), sizeof(_prompt)); + promptRememberForAutoComplete(true); + memcpy(&_promptPrevious, &_prompt, sizeof(_prompt)); + // parse text + _vm->_words->parseUsingDictionary((char *)&_prompt); + + _prompt[0] = 0; + } + } +} + bool TextMgr::stringWasEntered() { return _inputStringEntered; } diff --git a/engines/agi/text.h b/engines/agi/text.h index 7e9228e30a..f0aeab7762 100644 --- a/engines/agi/text.h +++ b/engines/agi/text.h @@ -163,6 +163,8 @@ public: bool _inputEditEnabled; byte _inputCursorChar; + bool _optionCommandPromptWindow; + bool _promptEnabled; int16 _promptRow; int16 _promptCursorPos; @@ -189,6 +191,8 @@ public: void promptClear(); // for AGI1 void promptRememberForAutoComplete(bool entered = false); // for auto-completion + void promptCommandWindow(bool recallLastCommand, uint16 newKey); + int16 _inputStringRow; int16 _inputStringColumn; bool _inputStringEntered; diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp index 32fa4cbff4..7072f003c2 100644 --- a/engines/agi/words.cpp +++ b/engines/agi/words.cpp @@ -293,7 +293,7 @@ int16 Words::findWordInDictionary(const Common::String &userInputLowcased, uint1 return wordId; } -void Words::parseUsingDictionary(char *rawUserInput) { +void Words::parseUsingDictionary(const char *rawUserInput) { Common::String userInput; Common::String userInputLowcased; const char *userInputPtr = nullptr; diff --git a/engines/agi/words.h b/engines/agi/words.h index c7bf4829c3..96dafae275 100644 --- a/engines/agi/words.h +++ b/engines/agi/words.h @@ -57,7 +57,7 @@ public: void unloadDictionary(); void clearEgoWords(); - void parseUsingDictionary(char *rawUserInput); + void parseUsingDictionary(const char *rawUserInput); private: void cleanUpInput(const char *userInput, Common::String &cleanInput); |