From 9b966daab244b084d18235c4f700c2c1f0e1b4e8 Mon Sep 17 00:00:00 2001 From: Tom M Date: Thu, 24 Dec 2020 16:03:39 +0000 Subject: [PATCH 1/7] Add basic eSpeak integration to SDL platform --- Makefile | 2 +- src/brogue/MainMenu.c | 2 ++ src/brogue/Rogue.h | 1 + src/platform/platform.h | 1 + src/platform/platformdependent.c | 6 ++++++ src/platform/sdl2-platform.c | 14 ++++++++++++++ 6 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 68a66054..2203c6af 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ ifeq ($(GRAPHICS),YES) sources += $(addprefix src/platform/,sdl2-platform.c tiles.c) cflags += $(shell $(SDL_CONFIG) --cflags) cppflags += -DBROGUE_SDL - libs += $(shell $(SDL_CONFIG) --libs) -lSDL2_image + libs += $(shell $(SDL_CONFIG) --libs) -lSDL2_image -lespeak-ng endif ifeq ($(WEBBROGUE),YES) diff --git a/src/brogue/MainMenu.c b/src/brogue/MainMenu.c index 81c9a9c7..d2e215cb 100644 --- a/src/brogue/MainMenu.c +++ b/src/brogue/MainMenu.c @@ -344,6 +344,8 @@ void titleMenu() { initializeMenuFlames(true, colors, colorStorage, colorSources, flames, mask); rogue.creaturesWillFlashThisTurn = false; // total unconscionable hack + playSpeech("Welcome to Brogue!"); + do { if (isApplicationActive()) { // Revert the display. diff --git a/src/brogue/Rogue.h b/src/brogue/Rogue.h index a11d996e..94385b56 100644 --- a/src/brogue/Rogue.h +++ b/src/brogue/Rogue.h @@ -2746,6 +2746,7 @@ extern "C" { void notifyEvent(short eventId, int data1, int data2, const char *str1, const char *str2); boolean takeScreenshot(); enum graphicsModes setGraphicsMode(enum graphicsModes mode); + void playSpeech(char *text); boolean controlKeyIsDown(); boolean shiftKeyIsDown(); short getHighScoresList(rogueHighScoresEntry returnList[HIGH_SCORES_COUNT]); diff --git a/src/platform/platform.h b/src/platform/platform.h index 8d42c2c3..440da196 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -83,6 +83,7 @@ struct brogueConsole { very start of the program, even before .gameLoop, to set the initial value. */ enum graphicsModes (*setGraphicsMode)(enum graphicsModes mode); + void (*playSpeech)(); }; // defined in platform diff --git a/src/platform/platformdependent.c b/src/platform/platformdependent.c index 6f1a1e6c..8a4b2040 100644 --- a/src/platform/platformdependent.c +++ b/src/platform/platformdependent.c @@ -267,6 +267,12 @@ enum graphicsModes setGraphicsMode(enum graphicsModes mode) { } } +void playSpeech(char *text) { + if (currentConsole.playSpeech) { + currentConsole.playSpeech(text); + } +} + // creates an empty high scores file void initScores() { short i; diff --git a/src/platform/sdl2-platform.c b/src/platform/sdl2-platform.c index cdcdbe4e..41472e10 100644 --- a/src/platform/sdl2-platform.c +++ b/src/platform/sdl2-platform.c @@ -4,6 +4,8 @@ #include #include +#include + #include "platform.h" #include "tiles.h" @@ -138,6 +140,16 @@ static char applyRemaps(char c) { } +static boolean audioInit() { + return espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0) != -1; +} + + +static void _playSpeech(char *text) { + espeak_Synth(text, strlen(text), 0, 0, 0, espeakCHARS_UTF8, NULL, NULL); +} + + /* If an event is available, returns true and updates returnEvent. Otherwise it returns false and an error event. This function also processes @@ -267,6 +279,7 @@ static void _gameLoop() { if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) imgfatal(__FILE__, __LINE__); initTiles(); + audioInit(); lastEvent.eventType = EVENT_ERROR; @@ -432,4 +445,5 @@ struct brogueConsole sdlConsole = { NULL, _takeScreenshot, _setGraphicsMode + .playSpeech = _playSpeech }; From 578dcd94c8af7d054dd9563b79cf8e82fe263c0f Mon Sep 17 00:00:00 2001 From: anderoonies Date: Sat, 31 Jul 2021 19:50:18 -0400 Subject: [PATCH 2/7] First work at TTS prompts in Brogue Speech --- Makefile | 7 ++++++- config.mk | 3 +++ src/brogue/Globals.c | 2 +- src/brogue/IO.c | 13 +++++++++++++ src/brogue/MainMenu.c | 4 ++++ src/brogue/Movement.c | 31 +++++++++++++++++++++++++++++++ src/platform/main.c | 4 ++++ src/platform/sdl2-platform.c | 4 +++- 8 files changed, 65 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 2203c6af..2fb718c8 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,12 @@ ifeq ($(GRAPHICS),YES) sources += $(addprefix src/platform/,sdl2-platform.c tiles.c) cflags += $(shell $(SDL_CONFIG) --cflags) cppflags += -DBROGUE_SDL - libs += $(shell $(SDL_CONFIG) --libs) -lSDL2_image -lespeak-ng + libs += $(shell $(SDL_CONFIG) --libs) -lSDL2_image +endif + +ifeq ($(SPEECH),YES) + cppflags += -DBROGUE_SPEECH + libs += -lespeak-ng endif ifeq ($(WEBBROGUE),YES) diff --git a/config.mk b/config.mk index b33967bf..871b0666 100644 --- a/config.mk +++ b/config.mk @@ -12,6 +12,9 @@ SDL_CONFIG := sdl2-config # Select web brogue mode. Requires POSIX system. WEBBROGUE := NO +# Add TTS. Requires GRAPHICS for now, just to add SDL. +SPEECH := YES + # Enable debugging mode. See top of Rogue.h for features DEBUG := NO diff --git a/src/brogue/Globals.c b/src/brogue/Globals.c index 9e543369..889dd6cd 100644 --- a/src/brogue/Globals.c +++ b/src/brogue/Globals.c @@ -189,7 +189,7 @@ const color fireForeColor = {70, 20, 0, 15, 10, const color lavaForeColor = {20, 20, 20, 100, 10, 0, 0, true}; const color brimstoneForeColor = {100, 50, 10, 0, 50, 40, 0, true}; const color brimstoneBackColor = {18, 12, 9, 0, 0, 5, 0, false}; - + //Red Green Blue RedRand GreenRand BlueRand Rand Dances const color lavaBackColor = {70, 20, 0, 15, 10, 0, 0, true}; const color acidBackColor = {15, 80, 25, 5, 15, 10, 0, true}; diff --git a/src/brogue/IO.c b/src/brogue/IO.c index 02de9d9c..2cb5294e 100644 --- a/src/brogue/IO.c +++ b/src/brogue/IO.c @@ -2974,6 +2974,11 @@ boolean confirm(char *prompt, boolean alsoDuringPlayback) { return true; // oh yes he did } +#ifdef BROGUE_SPEECH + playSpeech(prompt); + playSpeech("Yes... No"); +#endif + encodeMessageColor(whiteColorEscape, 0, &white); encodeMessageColor(yellowColorEscape, 0, KEYBOARD_LABELS ? &yellow : &white); @@ -3437,6 +3442,10 @@ void temporaryMessage(const char *msg, enum messageFlags flags) { updateMessageDisplay(); } restoreRNG; + + #ifdef BROGUE_SPEECH + playSpeech(msg); + #endif } void messageWithColor(char *msg, color *theColor, enum messageFlags flags) { @@ -3543,6 +3552,10 @@ void message(const char *msg, enum messageFlags flags) { } restoreRNG; + +#ifdef BROGUE_SPEECH + playSpeech(msg); +#endif } // Only used for the "you die..." message, to enable posthumous inventory viewing. diff --git a/src/brogue/MainMenu.c b/src/brogue/MainMenu.c index d2e215cb..1c284c9c 100644 --- a/src/brogue/MainMenu.c +++ b/src/brogue/MainMenu.c @@ -344,7 +344,11 @@ void titleMenu() { initializeMenuFlames(true, colors, colorStorage, colorSources, flames, mask); rogue.creaturesWillFlashThisTurn = false; // total unconscionable hack +#ifdef BROGUE_SPEECH playSpeech("Welcome to Brogue!"); +#else + playSpeech("Welcome to Brogue2!"); +#endif do { if (isApplicationActive()) { diff --git a/src/brogue/Movement.c b/src/brogue/Movement.c index f2620afd..61878a28 100644 --- a/src/brogue/Movement.c +++ b/src/brogue/Movement.c @@ -377,6 +377,37 @@ void describeLocation(char *buf, short x, short y) { sprintf(buf, "%s %s %s %s.", subject, verb, preposition, object); restoreRNG; + +// #ifdef BROGUE_SPEECH + static char lastMSG[DCOLS*3]; + char nowMSG[DCOLS*3]; + + if(strlen(buf) < 2) { + strcpy(nowMSG, "Blank."); + } else { + strcpy(nowMSG, buf); + } + + int Ty = player.yLoc; + char posX[20] = ""; + char posY[20] = ""; + + if(player.yLoc < y) { + sprintf(posY, " %d down.", abs(y-player.yLoc)); + } else if (player.yLoc > y) { + sprintf(posY, " %d up.", abs(y-player.yLoc)); + } + if(player.xLoc < x) { + sprintf(posX, " %d right.", abs(x-player.xLoc)); + } else if(player.xLoc > x) { + sprintf(posX, " %d left.", abs(x-player.xLoc)); + } + + strcat(nowMSG, posY); + strcat(nowMSG, posX); + + playSpeech(nowMSG); +// #endif } void printLocationDescription(short x, short y) { diff --git a/src/platform/main.c b/src/platform/main.c index 13495c02..7e2ec05b 100644 --- a/src/platform/main.c +++ b/src/platform/main.c @@ -252,6 +252,10 @@ int main(int argc, char *argv[]) continue; } +#ifdef BROGUE_SPEECH + rogue.trueColorMode = false; +#endif + if (strcmp(argv[i], "--wizard") == 0 || strcmp(argv[i], "-W") == 0) { rogue.wizard = true; continue; diff --git a/src/platform/sdl2-platform.c b/src/platform/sdl2-platform.c index 41472e10..f04e7d18 100644 --- a/src/platform/sdl2-platform.c +++ b/src/platform/sdl2-platform.c @@ -146,7 +146,9 @@ static boolean audioInit() { static void _playSpeech(char *text) { +#ifdef BROGUE_SPEECH espeak_Synth(text, strlen(text), 0, 0, 0, espeakCHARS_UTF8, NULL, NULL); +#endif } @@ -444,6 +446,6 @@ struct brogueConsole sdlConsole = { _modifierHeld, NULL, _takeScreenshot, - _setGraphicsMode + _setGraphicsMode, .playSpeech = _playSpeech }; From debcd07e2843d066f935e4b185ffc4013a5c5926 Mon Sep 17 00:00:00 2001 From: anderoonies Date: Sat, 31 Jul 2021 22:28:24 -0400 Subject: [PATCH 3/7] Remove ifdef guards for speech now, sanitize speech in one place --- src/brogue/IO.c | 6 ------ src/brogue/Items.c | 2 ++ src/brogue/MainMenu.c | 4 ---- src/brogue/Movement.c | 15 ++++++--------- src/platform/main.c | 4 +--- src/platform/sdl2-platform.c | 28 +++++++++++++++++++++++++--- 6 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/brogue/IO.c b/src/brogue/IO.c index 2cb5294e..4324a672 100644 --- a/src/brogue/IO.c +++ b/src/brogue/IO.c @@ -2974,10 +2974,8 @@ boolean confirm(char *prompt, boolean alsoDuringPlayback) { return true; // oh yes he did } -#ifdef BROGUE_SPEECH playSpeech(prompt); playSpeech("Yes... No"); -#endif encodeMessageColor(whiteColorEscape, 0, &white); encodeMessageColor(yellowColorEscape, 0, KEYBOARD_LABELS ? &yellow : &white); @@ -3443,9 +3441,7 @@ void temporaryMessage(const char *msg, enum messageFlags flags) { } restoreRNG; - #ifdef BROGUE_SPEECH playSpeech(msg); - #endif } void messageWithColor(char *msg, color *theColor, enum messageFlags flags) { @@ -3553,9 +3549,7 @@ void message(const char *msg, enum messageFlags flags) { restoreRNG; -#ifdef BROGUE_SPEECH playSpeech(msg); -#endif } // Only used for the "you die..." message, to enable posthumous inventory viewing. diff --git a/src/brogue/Items.c b/src/brogue/Items.c index 1a9a0b38..ab7bbec9 100644 --- a/src/brogue/Items.c +++ b/src/brogue/Items.c @@ -2957,6 +2957,8 @@ char displayInventory(unsigned short categoryMask, // Yes. Highlight the selected item. Do this by changing the button color and re-displaying it. overlayDisplayBuffer(dbuf, NULL); + + playSpeech(buttons[highlightItemLine].text); //buttons[highlightItemLine].buttonColor = interfaceBoxColor; drawButton(&(buttons[highlightItemLine]), BUTTON_PRESSED, NULL); diff --git a/src/brogue/MainMenu.c b/src/brogue/MainMenu.c index 1c284c9c..d2e215cb 100644 --- a/src/brogue/MainMenu.c +++ b/src/brogue/MainMenu.c @@ -344,11 +344,7 @@ void titleMenu() { initializeMenuFlames(true, colors, colorStorage, colorSources, flames, mask); rogue.creaturesWillFlashThisTurn = false; // total unconscionable hack -#ifdef BROGUE_SPEECH playSpeech("Welcome to Brogue!"); -#else - playSpeech("Welcome to Brogue2!"); -#endif do { if (isApplicationActive()) { diff --git a/src/brogue/Movement.c b/src/brogue/Movement.c index 61878a28..52d4b9d6 100644 --- a/src/brogue/Movement.c +++ b/src/brogue/Movement.c @@ -378,14 +378,12 @@ void describeLocation(char *buf, short x, short y) { sprintf(buf, "%s %s %s %s.", subject, verb, preposition, object); restoreRNG; -// #ifdef BROGUE_SPEECH - static char lastMSG[DCOLS*3]; - char nowMSG[DCOLS*3]; + char locationMessage[DCOLS*3]; if(strlen(buf) < 2) { - strcpy(nowMSG, "Blank."); + strcpy(locationMessage, "Blank."); } else { - strcpy(nowMSG, buf); + strcpy(locationMessage, buf); } int Ty = player.yLoc; @@ -403,11 +401,10 @@ void describeLocation(char *buf, short x, short y) { sprintf(posX, " %d left.", abs(x-player.xLoc)); } - strcat(nowMSG, posY); - strcat(nowMSG, posX); + strcat(locationMessage, posY); + strcat(locationMessage, posX); - playSpeech(nowMSG); -// #endif + playSpeech(locationMessage); } void printLocationDescription(short x, short y) { diff --git a/src/platform/main.c b/src/platform/main.c index 7e2ec05b..69921f8b 100644 --- a/src/platform/main.c +++ b/src/platform/main.c @@ -252,9 +252,7 @@ int main(int argc, char *argv[]) continue; } -#ifdef BROGUE_SPEECH - rogue.trueColorMode = false; -#endif + rogue.trueColorMode = false; if (strcmp(argv[i], "--wizard") == 0 || strcmp(argv[i], "-W") == 0) { rogue.wizard = true; diff --git a/src/platform/sdl2-platform.c b/src/platform/sdl2-platform.c index f04e7d18..9e3c1d7e 100644 --- a/src/platform/sdl2-platform.c +++ b/src/platform/sdl2-platform.c @@ -146,9 +146,31 @@ static boolean audioInit() { static void _playSpeech(char *text) { -#ifdef BROGUE_SPEECH - espeak_Synth(text, strlen(text), 0, 0, 0, espeakCHARS_UTF8, NULL, NULL); -#endif + // remove any escape codes from the text + int i, j; + char sanitizedMessage[90] = ""; + for(i = 0, j = 0; i < strlen(text); i++) + { + while (text[i] == COLOR_ESCAPE) { + i += 4; + } + + if(i >= strlen(text)) { + break; + } + + sanitizedMessage[j++]= text[i]; + } + espeak_Synth( + sanitizedMessage, + strlen(sanitizedMessage), + 0, + 0, + 0, + espeakCHARS_UTF8, + NULL, + NULL + ); } From 0b25910f340e236e3860a0445bf4f5692920a3c8 Mon Sep 17 00:00:00 2001 From: anderoonies Date: Sat, 31 Jul 2021 22:44:40 -0400 Subject: [PATCH 4/7] Speak location information in cursor mode --- src/brogue/Movement.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/brogue/Movement.c b/src/brogue/Movement.c index 52d4b9d6..0db70136 100644 --- a/src/brogue/Movement.c +++ b/src/brogue/Movement.c @@ -411,6 +411,8 @@ void printLocationDescription(short x, short y) { char buf[DCOLS*3]; describeLocation(buf, x, y); flavorMessage(buf); + // TODO: diff against previous message? + playSpeech(buf); } void useKeyAt(item *theItem, short x, short y) { From f428261d193e16a122c7902c09c8f3b10ec6c0ac Mon Sep 17 00:00:00 2001 From: anderoonies Date: Sun, 1 Aug 2021 09:25:09 -0400 Subject: [PATCH 5/7] Fuller location speech, groundwork for interrupting/interruptable messages --- .github/workflows/build.yml | 2 +- src/brogue/IO.c | 8 ++++---- src/brogue/Items.c | 2 +- src/brogue/MainMenu.c | 2 +- src/brogue/Movement.c | 33 ++++++++++++++++---------------- src/brogue/Rogue.h | 8 +++++++- src/platform/platformdependent.c | 4 ++-- src/platform/sdl2-platform.c | 20 ++++++++++++++++--- 8 files changed, 49 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index edfa06fd..75ce6349 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ jobs: - name: "Install dependencies" run: | sudo apt update -y - sudo apt install -y libsdl2-dev libsdl2-image-dev + sudo apt install -y libsdl2-dev libsdl2-image-dev espeak-ng - name: "Checkout sources" uses: actions/checkout@v2 diff --git a/src/brogue/IO.c b/src/brogue/IO.c index 4324a672..0ebe2325 100644 --- a/src/brogue/IO.c +++ b/src/brogue/IO.c @@ -2974,8 +2974,8 @@ boolean confirm(char *prompt, boolean alsoDuringPlayback) { return true; // oh yes he did } - playSpeech(prompt); - playSpeech("Yes... No"); + playSpeech(prompt, false, true); + playSpeech("Yes... No", false, false); encodeMessageColor(whiteColorEscape, 0, &white); encodeMessageColor(yellowColorEscape, 0, KEYBOARD_LABELS ? &yellow : &white); @@ -3441,7 +3441,7 @@ void temporaryMessage(const char *msg, enum messageFlags flags) { } restoreRNG; - playSpeech(msg); + playSpeech(msg, false, true); } void messageWithColor(char *msg, color *theColor, enum messageFlags flags) { @@ -3549,7 +3549,7 @@ void message(const char *msg, enum messageFlags flags) { restoreRNG; - playSpeech(msg); + playSpeech(msg, false, true); } // Only used for the "you die..." message, to enable posthumous inventory viewing. diff --git a/src/brogue/Items.c b/src/brogue/Items.c index ab7bbec9..a8f94a8e 100644 --- a/src/brogue/Items.c +++ b/src/brogue/Items.c @@ -2958,7 +2958,7 @@ char displayInventory(unsigned short categoryMask, overlayDisplayBuffer(dbuf, NULL); - playSpeech(buttons[highlightItemLine].text); + playSpeech(buttons[highlightItemLine].text, true, true); //buttons[highlightItemLine].buttonColor = interfaceBoxColor; drawButton(&(buttons[highlightItemLine]), BUTTON_PRESSED, NULL); diff --git a/src/brogue/MainMenu.c b/src/brogue/MainMenu.c index d2e215cb..7915be44 100644 --- a/src/brogue/MainMenu.c +++ b/src/brogue/MainMenu.c @@ -344,7 +344,7 @@ void titleMenu() { initializeMenuFlames(true, colors, colorStorage, colorSources, flames, mask); rogue.creaturesWillFlashThisTurn = false; // total unconscionable hack - playSpeech("Welcome to Brogue!"); + playSpeech("Welcome to Brogue!", false, false); do { if (isApplicationActive()) { diff --git a/src/brogue/Movement.c b/src/brogue/Movement.c index 0db70136..f65536f7 100644 --- a/src/brogue/Movement.c +++ b/src/brogue/Movement.c @@ -159,6 +159,7 @@ void describeLocation(char *buf, short x, short y) { strcpy(buf, tileFlavor(x, y)); } restoreRNG; + speakLocation(buf, x, y); return; } @@ -199,6 +200,7 @@ void describeLocation(char *buf, short x, short y) { } sprintf(buf, "you can detect the aura of %s here.", object); restoreRNG; + speakLocation(buf, x, y); return; } @@ -227,6 +229,7 @@ void describeLocation(char *buf, short x, short y) { sprintf(buf, "you can sense a %s psychic emanation %s%s.", adjective, preposition, object); restoreRNG; + speakLocation(buf, x, y); return; } @@ -249,10 +252,12 @@ void describeLocation(char *buf, short x, short y) { } sprintf(buf, "you remember seeing %s here.", object); restoreRNG; + speakLocation(buf, x, y); return; } else if (pmap[x][y].flags & MAGIC_MAPPED) { // magic mapped sprintf(buf, "you expect %s to be here.", tileCatalog[pmap[x][y].rememberedTerrain].description); restoreRNG; + speakLocation(buf, x, y); return; } strcpy(buf, ""); @@ -267,6 +272,7 @@ void describeLocation(char *buf, short x, short y) { if (pmap[x][y].layers[GAS] && monst->status[STATUS_INVISIBLE]) { // phantoms in gas sprintf(buf, "you can perceive the faint outline of %s in %s.", subject, tileCatalog[pmap[x][y].layers[GAS]].description); restoreRNG; + speakLocation(buf, x, y); return; } @@ -371,48 +377,41 @@ void describeLocation(char *buf, short x, short y) { } else { // no item sprintf(buf, "you %s %s.", (playerCanDirectlySee(x, y) ? "see" : "sense"), object); restoreRNG; + speakLocation(buf, x, y); return; } } sprintf(buf, "%s %s %s %s.", subject, verb, preposition, object); restoreRNG; + speakLocation(buf, x, y); +} - char locationMessage[DCOLS*3]; +void speakLocation(char *locationDescription, short x, short y) { + char locationMessage[DCOLS*3]; - if(strlen(buf) < 2) { + if(strlen(locationDescription) < 2) { strcpy(locationMessage, "Blank."); } else { - strcpy(locationMessage, buf); + strcpy(locationMessage, locationDescription); } - int Ty = player.yLoc; char posX[20] = ""; char posY[20] = ""; - if(player.yLoc < y) { - sprintf(posY, " %d down.", abs(y-player.yLoc)); - } else if (player.yLoc > y) { - sprintf(posY, " %d up.", abs(y-player.yLoc)); - } - if(player.xLoc < x) { - sprintf(posX, " %d right.", abs(x-player.xLoc)); - } else if(player.xLoc > x) { - sprintf(posX, " %d left.", abs(x-player.xLoc)); - } + sprintf(posY, " %d %s.", abs(y - player.yLoc), player.yLoc < y ? "down" : "up"); + sprintf(posX, " %d %s.", abs(x - player.xLoc), player.xLoc < x ? "right" : "left"); strcat(locationMessage, posY); strcat(locationMessage, posX); - playSpeech(locationMessage); + playSpeech(locationMessage, true, true); } void printLocationDescription(short x, short y) { char buf[DCOLS*3]; describeLocation(buf, x, y); flavorMessage(buf); - // TODO: diff against previous message? - playSpeech(buf); } void useKeyAt(item *theItem, short x, short y) { diff --git a/src/brogue/Rogue.h b/src/brogue/Rogue.h index 94385b56..6105029f 100644 --- a/src/brogue/Rogue.h +++ b/src/brogue/Rogue.h @@ -355,6 +355,11 @@ typedef struct rogueEvent { boolean shiftKey; } rogueEvent; +typedef struct speechData { + boolean interruptable; + char message[DCOLS]; +} speechData; + typedef struct rogueHighScoresEntry { signed long score; char date[100]; @@ -2746,7 +2751,7 @@ extern "C" { void notifyEvent(short eventId, int data1, int data2, const char *str1, const char *str2); boolean takeScreenshot(); enum graphicsModes setGraphicsMode(enum graphicsModes mode); - void playSpeech(char *text); + void playSpeech(char *text, boolean interruptable, boolean interruptPrevious); boolean controlKeyIsDown(); boolean shiftKeyIsDown(); short getHighScoresList(rogueHighScoresEntry returnList[HIGH_SCORES_COUNT]); @@ -2849,6 +2854,7 @@ extern "C" { char *tileText(short x, short y); void describedItemBasedOnParameters(short theCategory, short theKind, short theQuantity, short theItemOriginDepth, char *buf); void describeLocation(char buf[DCOLS], short x, short y); + void speakLocation(char *locationDescription, short x, short y); void printLocationDescription(short x, short y); void useKeyAt(item *theItem, short x, short y); void playerRuns(short direction); diff --git a/src/platform/platformdependent.c b/src/platform/platformdependent.c index 8a4b2040..f8184b3e 100644 --- a/src/platform/platformdependent.c +++ b/src/platform/platformdependent.c @@ -267,9 +267,9 @@ enum graphicsModes setGraphicsMode(enum graphicsModes mode) { } } -void playSpeech(char *text) { +void playSpeech(char *text, boolean interruptable, boolean interruptPrevious) { if (currentConsole.playSpeech) { - currentConsole.playSpeech(text); + currentConsole.playSpeech(text, interruptable, interruptPrevious); } } diff --git a/src/platform/sdl2-platform.c b/src/platform/sdl2-platform.c index 9e3c1d7e..48082523 100644 --- a/src/platform/sdl2-platform.c +++ b/src/platform/sdl2-platform.c @@ -22,7 +22,7 @@ static size_t nremaps = 0; static enum graphicsModes showGraphics = TEXT_GRAPHICS; static rogueEvent lastEvent; - +static speechData lastSpeech; static void sdlfatal(char *file, int line) { fprintf(stderr, "Fatal SDL error (%s:%d): %s\n", file, line, SDL_GetError()); @@ -140,12 +140,24 @@ static char applyRemaps(char c) { } +static void speechCallback(short *wav, int numsamples, espeak_EVENT *events) { + return; +} + + static boolean audioInit() { + espeak_SetSynthCallback(speechCallback); return espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0) != -1; } - -static void _playSpeech(char *text) { +static void _playSpeech( + char *text, + boolean interruptable, + boolean interruptPrevious +) { + if (interruptPrevious && lastSpeech.interruptable) { + espeak_Cancel(); + } // remove any escape codes from the text int i, j; char sanitizedMessage[90] = ""; @@ -161,6 +173,7 @@ static void _playSpeech(char *text) { sanitizedMessage[j++]= text[i]; } + printf(sanitizedMessage); espeak_Synth( sanitizedMessage, strlen(sanitizedMessage), @@ -171,6 +184,7 @@ static void _playSpeech(char *text) { NULL, NULL ); + // TODO: mark interruptable messages with unique_identifier } From a413c69d09f6ad57f489dc87240a9d4168a53080 Mon Sep 17 00:00:00 2001 From: anderoonies Date: Sun, 1 Aug 2021 12:38:39 -0400 Subject: [PATCH 6/7] First pass at speech message priority for interrupting/blocking --- .github/workflows/build.yml | 4 +- src/brogue/Architect.c | 2 +- src/brogue/Combat.c | 28 ++-- src/brogue/IO.c | 40 ++--- src/brogue/Items.c | 256 +++++++++++++++---------------- src/brogue/MainMenu.c | 2 +- src/brogue/Monsters.c | 20 +-- src/brogue/Movement.c | 54 +++---- src/brogue/Recordings.c | 36 ++--- src/brogue/Rogue.h | 8 +- src/brogue/RogueMain.c | 34 ++-- src/brogue/Time.c | 114 +++++++------- src/platform/platformdependent.c | 4 +- src/platform/sdl2-platform.c | 8 +- 14 files changed, 306 insertions(+), 304 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 75ce6349..a5fd42d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,7 +5,7 @@ on: jobs: linux: - runs-on: ubuntu-16.04 + runs-on: ubuntu-18.04 steps: - name: "Install dependencies" run: | @@ -55,7 +55,7 @@ jobs: brew install --build-from-source ./macos/sdl2.rb cp -r $(brew --cellar)/sdl2 sdl2-cellar fi - brew install sdl2_image dylibbundler + brew install sdl2_image dylibbundler espeak-ng - name: "Compile" run: | diff --git a/src/brogue/Architect.c b/src/brogue/Architect.c index 056b5cd7..121be33b 100644 --- a/src/brogue/Architect.c +++ b/src/brogue/Architect.c @@ -3338,7 +3338,7 @@ boolean spawnDungeonFeature(short x, short y, dungeonFeature *feat, boolean refr if (feat->description[0] && !feat->messageDisplayed && playerCanSee(x, y)) { feat->messageDisplayed = true; - message(feat->description, 0); + message(feat->description, 0, 0); } zeroOutGrid(blockingMap); diff --git a/src/brogue/Combat.c b/src/brogue/Combat.c index 28791799..c1e4871c 100644 --- a/src/brogue/Combat.c +++ b/src/brogue/Combat.c @@ -255,7 +255,7 @@ void splitMonster(creature *monst, short x, short y) { if (canDirectlySeeMonster(monst)) { sprintf(buf, "%s splits in two!", monstName); - message(buf, 0); + message(buf, 0, 2); } return; @@ -393,7 +393,7 @@ void specialHit(creature *attacker, creature *defender, short damage) { equipItem(rogue.armor, true, NULL); itemName(rogue.armor, buf2, false, false, NULL); sprintf(buf, "your %s weakens!", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 2); checkForDisenchantment(rogue.armor); } if (attacker->info.abilityFlags & MA_HIT_HALLUCINATE) { @@ -461,7 +461,7 @@ void specialHit(creature *attacker, creature *defender, short damage) { monsterName(buf2, attacker, true); itemName(theItem, buf3, false, true, NULL); sprintf(buf, "%s stole %s!", buf2, buf3); - messageWithColor(buf, &badMessageColor, 0); + messageWithColor(buf, &badMessageColor, 0, 2); } } } @@ -718,7 +718,7 @@ void magicWeaponHit(creature *defender, item *theItem, boolean backstabbed) { } updateVision(true); - message(buf, 0); + message(buf, 0, 2); autoID = true; break; case W_SLOWING: @@ -946,7 +946,7 @@ void applyArmorRunicEffect(char returnString[DCOLS], creature *attacker, short * case A_IMMOLATION: if (rand_percent(10)) { sprintf(returnString, "flames suddenly explode out of your %s!", armorName); - message(returnString, runicKnown ? 0 : REQUIRE_ACKNOWLEDGMENT); + message(returnString, runicKnown ? 0 : REQUIRE_ACKNOWLEDGMENT, 2); returnString[0] = '\0'; spawnDungeonFeature(player.xLoc, player.yLoc, &(dungeonFeatureCatalog[DF_ARMOR_IMMOLATION]), true, false); runicDiscovered = true; @@ -969,10 +969,10 @@ void decrementWeaponAutoIDTimer() { rogue.weapon->flags |= ITEM_IDENTIFIED; updateIdentifiableItems(); - messageWithColor("you are now familiar enough with your weapon to identify it.", &itemMessageColor, 0); + messageWithColor("you are now familiar enough with your weapon to identify it.", &itemMessageColor, 0, 2); itemName(rogue.weapon, buf2, true, true, NULL); sprintf(buf, "%s %s.", (rogue.weapon->quantity > 1 ? "they are" : "it is"), buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 2); } } @@ -1061,7 +1061,7 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) { defender->bookkeepingFlags |= MB_SEIZED; if (canSeeMonster(attacker) || canSeeMonster(defender)) { sprintf(buf, "%s seizes %s!", attackerName, (defender == &player ? "your legs" : defenderName)); - messageWithColor(buf, &white, 0); + messageWithColor(buf, &white, 0, 2); } return false; } @@ -1186,7 +1186,7 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) { specialHit(attacker, defender, (attacker->info.abilityFlags & MA_POISONS) ? poisonDamage : damage); } if (armorRunicString[0]) { - message(armorRunicString, 0); + message(armorRunicString, 0, 2); if (rogue.armor && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_BURDEN) { strengthCheck(rogue.armor, true); } @@ -1221,7 +1221,7 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) { equipItem(rogue.weapon, true, NULL); itemName(rogue.weapon, buf2, false, false, NULL); sprintf(buf, "your %s weakens!", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 2); checkForDisenchantment(rogue.weapon); } @@ -1311,12 +1311,12 @@ void displayCombatText() { for (end = start; *end != '\0'; end++) { if (*end == '\n') { *end = '\0'; - message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0)); + message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0), 2); start = end + 1; } } - message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0)); + message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0), 2); rogue.cautiousMode = false; } @@ -1647,7 +1647,7 @@ void killCreature(creature *decedent, boolean administrativeDeath) { monsterName(monstName, decedent, true); snprintf(buf, DCOLS * 3, "%s %s", monstName, monsterText[decedent->info.monsterID].DFMessage); resolvePronounEscapes(buf, decedent); - message(buf, 0); + message(buf, 0, 2); } } @@ -1661,7 +1661,7 @@ void killCreature(creature *decedent, boolean administrativeDeath) { && !(decedent->bookkeepingFlags & MB_BOUND_TO_LEADER) && !decedent->carriedMonster) { - messageWithColor("you feel a sense of loss.", &badMessageColor, 0); + messageWithColor("you feel a sense of loss.", &badMessageColor, 0, 2); } x = decedent->xLoc; y = decedent->yLoc; diff --git a/src/brogue/IO.c b/src/brogue/IO.c index 0ebe2325..59ec171c 100644 --- a/src/brogue/IO.c +++ b/src/brogue/IO.c @@ -2384,9 +2384,9 @@ void exploreKey(const boolean controlKey) { } if (tooDark) { - message("It's too dark to explore!", 0); + message("It's too dark to explore!", 0, 2); } else if (x == player.xLoc && y == player.yLoc) { - message("I see no path for further exploration.", 0); + message("I see no path for further exploration.", 0, 2); } else if (proposeOrConfirmLocation(finalX, finalY, "I see no path for further exploration.")) { explore(controlKey ? 1 : 20); // Do the exploring until interrupted. hideCursor(); @@ -2443,7 +2443,7 @@ void nextBrogueEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsD if (returnEvent->eventType == EVENT_ERROR) { rogue.playbackPaused = rogue.playbackMode; // pause if replaying - message("Event error!", REQUIRE_ACKNOWLEDGMENT); + message("Event error!", REQUIRE_ACKNOWLEDGMENT, 3); } } @@ -2598,10 +2598,10 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe refreshSideBar(-1, -1, false); if (rogue.trueColorMode) { messageWithColor(KEYBOARD_LABELS ? "Color effects disabled. Press '\\' again to enable." : "Color effects disabled.", - &teal, 0); + &teal, 0, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Color effects enabled. Press '\\' again to disable." : "Color effects enabled.", - &teal, 0); + &teal, 0, 0); } break; case AGGRO_DISPLAY_KEY: @@ -2610,10 +2610,10 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe refreshSideBar(-1, -1, false); if (rogue.displayAggroRangeMode) { messageWithColor(KEYBOARD_LABELS ? "Stealth range displayed. Press ']' again to hide." : "Stealth range displayed.", - &teal, 0); + &teal, 0, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Stealth range hidden. Press ']' again to display." : "Stealth range hidden.", - &teal, 0); + &teal, 0, 0); } break; case CALL_KEY: @@ -2649,7 +2649,7 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe rogue.nextGame = NG_VIEW_RECORDING; rogue.gameHasEnded = true; } else { - message("File not found.", 0); + message("File not found.", 0, 0); } } break; @@ -2665,7 +2665,7 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe rogue.nextGame = NG_OPEN_GAME; rogue.gameHasEnded = true; } else { - message("File not found.", 0); + message("File not found.", 0, 0); } } break; @@ -2697,17 +2697,17 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe case TEXT_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to text mode. Press 'G' again to enable tiles." - : "Switched to text mode.", &teal, 0); + : "Switched to text mode.", &teal, 0, 1); break; case TILES_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to graphical tiles. Press 'G' again to enable hybrid mode." - : "Switched to graphical tiles.", &teal, 0); + : "Switched to graphical tiles.", &teal, 0, 1); break; case HYBRID_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to hybrid mode. Press 'G' again to disable tiles." - : "Switched to hybrid mode.", &teal, 0); + : "Switched to hybrid mode.", &teal, 0, 1); break; } } @@ -2974,8 +2974,8 @@ boolean confirm(char *prompt, boolean alsoDuringPlayback) { return true; // oh yes he did } - playSpeech(prompt, false, true); - playSpeech("Yes... No", false, false); + playSpeech(prompt, 3); + playSpeech("Yes... No", 3); encodeMessageColor(whiteColorEscape, 0, &white); encodeMessageColor(yellowColorEscape, 0, KEYBOARD_LABELS ? &yellow : &white); @@ -3441,17 +3441,17 @@ void temporaryMessage(const char *msg, enum messageFlags flags) { } restoreRNG; - playSpeech(msg, false, true); + playSpeech(msg, 1); } -void messageWithColor(char *msg, color *theColor, enum messageFlags flags) { +void messageWithColor(char *msg, color *theColor, enum messageFlags flags, short speechPriority) { char buf[COLS*2] = ""; short i; i=0; i = encodeMessageColor(buf, i, theColor); strcpy(&(buf[i]), msg); - message(buf, flags); + message(buf, flags, speechPriority); } void flavorMessage(char *msg) { @@ -3479,7 +3479,7 @@ void flavorMessage(char *msg) { // arrived on the same turn, they may collapse. Alternately, they may collapse // if the older message is the latest one in the archive and the new one is not // semi-colon foldable (such as a combat message.) -void message(const char *msg, enum messageFlags flags) { +void message(const char *msg, enum messageFlags flags, short speechPriority) { short i; archivedMessage *archiveEntry; boolean newMessage; @@ -3549,7 +3549,7 @@ void message(const char *msg, enum messageFlags flags) { restoreRNG; - playSpeech(msg, false, true); + playSpeech(msg, speechPriority); } // Only used for the "you die..." message, to enable posthumous inventory viewing. @@ -4478,7 +4478,7 @@ void displayGrid(short **map) { void printSeed() { char buf[COLS]; snprintf(buf, COLS, "Dungeon seed #%llu; turn #%lu; version %s", (unsigned long long)rogue.seed, rogue.playerTurnNumber, BROGUE_VERSION_STRING); - message(buf, 0); + message(buf, 0, 0); } void printProgressBar(short x, short y, const char barLabel[COLS], long amtFilled, long amtMax, color *fillColor, boolean dim) { diff --git a/src/brogue/Items.c b/src/brogue/Items.c index a8f94a8e..c13f6697 100644 --- a/src/brogue/Items.c +++ b/src/brogue/Items.c @@ -331,7 +331,7 @@ item *makeItemInto(item *theItem, unsigned long itemCategory, short itemKind) { break; default: theEntry = NULL; - message("something has gone terribly wrong!", REQUIRE_ACKNOWLEDGMENT); + message("something has gone terribly wrong!", REQUIRE_ACKNOWLEDGMENT, 3); break; } if (theItem @@ -389,7 +389,7 @@ item *placeItem(item *theItem, short x, short y) { } itemName(theItem, theItemName, false, false, NULL); sprintf(buf, "a pressure plate clicks underneath the %s!", theItemName); - message(buf, REQUIRE_ACKNOWLEDGMENT); + message(buf, REQUIRE_ACKNOWLEDGMENT, 3); } for (layer = 0; layer < NUMBER_TERRAIN_LAYERS; layer++) { if (tileCatalog[pmap[x][y].layers[layer]].flags & T_IS_DF_TRAP) { @@ -755,7 +755,7 @@ void pickUpItemAt(short x, short y) { theItem = itemAtLoc(x, y); if (!theItem) { - message("Error: Expected item; item not found.", REQUIRE_ACKNOWLEDGMENT); + message("Error: Expected item; item not found.", REQUIRE_ACKNOWLEDGMENT, 3); return; } @@ -785,14 +785,14 @@ void pickUpItemAt(short x, short y) { rogue.gold += theItem->quantity; rogue.featRecord[FEAT_TONE] = false; sprintf(buf, "you found %i pieces of gold.", theItem->quantity); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); deleteItem(theItem); removeItemFrom(x, y); // triggers tiles with T_PROMOTES_ON_ITEM_PICKUP return; } if ((theItem->category & AMULET) && numberOfMatchingPackItems(AMULET, 0, 0, false)) { - message("you already have the Amulet of Yendor.", 0); + message("you already have the Amulet of Yendor.", 0, 3); deleteItem(theItem); return; } @@ -802,7 +802,7 @@ void pickUpItemAt(short x, short y) { itemName(theItem, buf2, true, true, NULL); // include suffix, article sprintf(buf, "you now have %s (%c).", buf2, theItem->inventoryLetter); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); removeItemFrom(x, y); // triggers tiles with T_PROMOTES_ON_ITEM_PICKUP @@ -829,7 +829,7 @@ void pickUpItemAt(short x, short y) { theItem->flags |= ITEM_PLAYER_AVOIDS; // explore shouldn't try to pick it up more than once. itemName(theItem, buf2, false, true, NULL); // include article sprintf(buf, "Your pack is too full to pick up %s.", buf2); - message(buf, 0); + message(buf, 0, 3); } } @@ -972,7 +972,7 @@ void checkForDisenchantment(item *theItem) { identify(theItem); itemName(theItem, buf2, false, false, NULL); sprintf(buf, "the runes fade from your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } } if (theItem->flags & ITEM_CURSED @@ -1012,7 +1012,7 @@ void swapItemToEnchantLevel(item *theItem, short newEnchant, boolean enchantment refreshDungeonCell(x, y); } if (playerCanSee(x, y)) { - messageWithColor(buf2, &itemMessageColor, 0); + messageWithColor(buf2, &itemMessageColor, 0, 3); } } else { if ((theItem->category & STAFF) @@ -1117,7 +1117,7 @@ void updateFloorItems() { if (playerCanSeeOrSense(x, y)) { itemName(theItem, buf, false, false, NULL); sprintf(buf2, "The %s plunge%s out of sight!", buf, (theItem->quantity > 1 ? "" : "s")); - messageWithColor(buf2, &itemMessageColor, 0); + messageWithColor(buf2, &itemMessageColor, 0, 3); } if (playerCanSee(x, y)) { discover(x, y); @@ -1210,7 +1210,7 @@ boolean inscribeItem(item *theItem) { confirmMessages(); itemName(theItem, nameOfItem, true, true, NULL); sprintf(buf, "%s %s.", (theItem->quantity > 1 ? "they're" : "it's"), nameOfItem); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); return true; } else { confirmMessages(); @@ -1272,7 +1272,7 @@ void call(item *theItem) { recordKeystroke(RETURN_KEY, false, false); } } else { - message("you already know what that is.", 0); + message("you already know what that is.", 0, 3); } return; } @@ -1317,10 +1317,10 @@ void call(item *theItem) { } confirmMessages(); itemName(theItem, buf, false, true, NULL); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } } else { - message("you already know what that is.", 0); + message("you already know what that is.", 0, 3); } } @@ -2724,7 +2724,7 @@ char displayInventory(unsigned short categoryMask, if (packItems->nextItem == NULL) { confirmMessages(); - message("Your pack is empty!", 0); + message("Your pack is empty!", 0, 3); restoreRNG; return 0; } @@ -2851,7 +2851,7 @@ char displayInventory(unsigned short categoryMask, itemCount = itemNumber; if (!itemNumber) { confirmMessages(); - message("Nothing of that type!", 0); + message("Nothing of that type!", 0, 3); restoreRNG; return 0; } @@ -2958,7 +2958,7 @@ char displayInventory(unsigned short categoryMask, overlayDisplayBuffer(dbuf, NULL); - playSpeech(buttons[highlightItemLine].text, true, true); + playSpeech(buttons[highlightItemLine].text, 3); //buttons[highlightItemLine].buttonColor = interfaceBoxColor; drawButton(&(buttons[highlightItemLine]), BUTTON_PRESSED, NULL); @@ -3045,7 +3045,7 @@ short numberOfMatchingPackItems(unsigned short categoryMask, if (packItems->nextItem == NULL) { if (displayErrors) { confirmMessages(); - message("Your pack is empty!", 0); + message("Your pack is empty!", 0, 3); } return 0; } @@ -3063,7 +3063,7 @@ short numberOfMatchingPackItems(unsigned short categoryMask, if (matchingItemCount == 0) { if (displayErrors) { confirmMessages(); - message("You have nothing suitable.", 0); + message("You have nothing suitable.", 0, 3); } return 0; } @@ -3111,7 +3111,7 @@ void strengthCheck(item *theItem, boolean noisy) { strcpy(buf1, ""); itemName(theItem, buf1, false, false, NULL); sprintf(buf2, "You can barely lift the %s; %i more strength would be ideal.", buf1, strengthDeficiency); - message(buf2, 0); + message(buf2, 0, 3); } if (theItem->category & ARMOR && theItem->strengthRequired > rogue.strength - player.weaknessAmount) { @@ -3120,7 +3120,7 @@ void strengthCheck(item *theItem, boolean noisy) { itemName(theItem, buf1, false, false, NULL); sprintf(buf2, "You stagger under the weight of the %s; %i more strength would be ideal.", buf1, strengthDeficiency); - message(buf2, 0); + message(buf2, 0, 3); } } } @@ -3151,7 +3151,7 @@ void equip(item *theItem) { if (theItem->category & RING) { if (theItem->flags & ITEM_EQUIPPED) { confirmMessages(); - message("you are already wearing that ring.", 0); + message("you are already wearing that ring.", 0, 3); return; } else if (rogue.ringLeft && rogue.ringRight) { confirmMessages(); @@ -3159,7 +3159,7 @@ void equip(item *theItem) { "You are already wearing two rings; remove which first?", true); if (!theItem2 || theItem2->category != RING || !(theItem2->flags & ITEM_EQUIPPED)) { if (theItem2) { // No message if canceled or did an inventory action instead. - message("Invalid entry.", 0); + message("Invalid entry.", 0, 3); } return; } else { @@ -3170,7 +3170,7 @@ void equip(item *theItem) { if (theItem->flags & ITEM_EQUIPPED) { confirmMessages(); - message("already equipped.", 0); + message("already equipped.", 0, 3); return; } @@ -3193,7 +3193,7 @@ void equip(item *theItem) { playerTurnEnded(); } else { confirmMessages(); - message("You can't equip that.", 0); + message("You can't equip that.", 0, 3); } } @@ -3303,7 +3303,7 @@ void aggravateMonsters(short distance, short x, short y, const color *flashColor discoverCell(x, y); colorFlash(flashColor, 0, (DISCOVERED | MAGIC_MAPPED), 10, distance, x, y); if (!playerCanSee(x, y)) { - message("You hear a piercing shriek; something must have triggered a nearby alarm.", 0); + message("You hear a piercing shriek; something must have triggered a nearby alarm.", 0, 3); } } @@ -3745,7 +3745,7 @@ void weaken(creature *monst, short maxDuration) { monst->status[STATUS_WEAKENED] = max(monst->status[STATUS_WEAKENED], maxDuration); monst->maxStatus[STATUS_WEAKENED] = max(monst->maxStatus[STATUS_WEAKENED], maxDuration); if (monst == &player) { - messageWithColor("your muscles weaken as an enervating toxin fills your veins.", &badMessageColor, 0); + messageWithColor("your muscles weaken as an enervating toxin fills your veins.", &badMessageColor, 0, 3); strengthCheck(rogue.weapon, true); strengthCheck(rogue.armor, true); } @@ -3836,7 +3836,7 @@ void slow(creature *monst, short turns) { monst->status[STATUS_HASTED] = 0; if (monst == &player) { updateEncumbrance(); - message("you feel yourself slow down.", 0); + message("you feel yourself slow down.", 0, 3); } else { monst->movementSpeed = monst->info.movementSpeed * 2; monst->attackSpeed = monst->info.attackSpeed * 2; @@ -3850,7 +3850,7 @@ void haste(creature *monst, short turns) { monst->status[STATUS_HASTED] = monst->maxStatus[STATUS_HASTED] = turns; if (monst == &player) { updateEncumbrance(); - message("you feel yourself speed up.", 0); + message("you feel yourself speed up.", 0, 3); } else { monst->movementSpeed = monst->info.movementSpeed / 2; monst->attackSpeed = monst->info.attackSpeed / 2; @@ -3908,9 +3908,9 @@ void makePlayerTelepathic(short duration) { refreshDungeonCell(monst->xLoc, monst->yLoc); } if (!hasNextCreature(iterateCreatures(monsters))) { - message("you can somehow tell that you are alone on this depth at the moment.", 0); + message("you can somehow tell that you are alone on this depth at the moment.", 0, 3); } else { - message("you can somehow feel the presence of other creatures' minds!", 0); + message("you can somehow feel the presence of other creatures' minds!", 0, 3); } } @@ -3963,9 +3963,9 @@ void rechargeItems(unsigned long categories) { strcat(buf, z == 1 ? "charm" : "charms"); } strcat(buf, "."); - message(buf, 0); + message(buf, 0, 3); } else { - message("a surge of energy courses through your pack, but nothing happens.", 0); + message("a surge of energy courses through your pack, but nothing happens.", 0, 3); } } @@ -4003,7 +4003,7 @@ void negationBlast(const char *emitterName, const short distance) { char buf[DCOLS]; sprintf(buf, "%s emits a numbing torrent of anti-magic!", emitterName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); colorFlash(&pink, 0, IN_FIELD_OF_VIEW, 3 + distance / 5, distance, player.xLoc, player.yLoc); negate(&player); flashMonster(&player, &pink, 100); @@ -4058,7 +4058,7 @@ void discordBlast(const char *emitterName, const short distance) { char buf[DCOLS]; sprintf(buf, "%s emits a wave of unsettling purple radiation!", emitterName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); colorFlash(&discordColor, 0, IN_FIELD_OF_VIEW, 3 + distance / 5, distance, player.xLoc, player.yLoc); for (creatureIterator it = iterateCreatures(monsters); hasNextCreature(it);) { creature *monst = nextCreature(&it); @@ -4450,7 +4450,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, *autoID = true; } sprintf(buf, "%s is bound to your will!", monstName); - message(buf, 0); + message(buf, 0, 3); if (boltCatalog[BOLT_DOMINATION].backColor) { flashMonster(monst, boltCatalog[BOLT_DOMINATION].backColor, 100); } @@ -4460,7 +4460,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, *autoID = true; } sprintf(buf, "%s resists the bolt of domination.", monstName); - message(buf, 0); + message(buf, 0, 3); } } break; @@ -4510,7 +4510,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, flashMonster(monst, &confusionGasColor, 100); monst->status[STATUS_CONFUSED] = staffEntrancementDuration(theBolt->magnitude * FP_FACTOR); monst->maxStatus[STATUS_CONFUSED] = max(monst->status[STATUS_CONFUSED], monst->maxStatus[STATUS_CONFUSED]); - message("the bolt hits you and you suddenly feel disoriented.", REQUIRE_ACKNOWLEDGMENT); + message("the bolt hits you and you suddenly feel disoriented.", REQUIRE_ACKNOWLEDGMENT, 3); if (autoID) { *autoID = true; } @@ -4525,7 +4525,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, *autoID = true; } sprintf(buf, "%s is entranced!", monstName); - message(buf, 0); + message(buf, 0, 3); } } break; @@ -5648,7 +5648,7 @@ void autoIdentify(item *theItem) { sprintf(buf, "(It must %s %s.)", ((theItem->category & (POTION | SCROLL)) ? "have been" : "be"), newName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } if ((theItem->category & (WEAPON | ARMOR)) @@ -5659,7 +5659,7 @@ void autoIdentify(item *theItem) { theItem->flags |= (ITEM_RUNIC_IDENTIFIED | ITEM_RUNIC_HINTED); itemName(theItem, newName, true, true, NULL); sprintf(buf, "(Your %s must be %s.)", oldName, newName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } } @@ -5719,23 +5719,23 @@ boolean hitMonsterWithProjectileWeapon(creature *thrower, creature *monst, item theItemName, (monst->info.flags & MONST_INANIMATE) ? "destroyed" : "killed", targetName); - messageWithColor(buf, messageColorFromVictim(monst), 0); + messageWithColor(buf, messageColorFromVictim(monst), 0, 3); } else { sprintf(buf, "the %s hit %s.", theItemName, targetName); if (theItem->flags & ITEM_RUNIC) { magicWeaponHit(monst, theItem, false); } - messageWithColor(buf, messageColorFromVictim(monst), 0); + messageWithColor(buf, messageColorFromVictim(monst), 0, 3); } moralAttack(thrower, monst); if (armorRunicString[0]) { - message(armorRunicString, 0); + message(armorRunicString, 0, 3); } return true; } else { theItem->flags &= ~ITEM_PLAYER_AVOIDS; // Don't avoid thrown weapons that missed. sprintf(buf, "the %s missed %s.", theItemName, targetName); - message(buf, 0); + message(buf, 0, 3); return false; } } @@ -5767,7 +5767,7 @@ void throwItem(item *theItem, creature *thrower, short targetLoc[2], short maxDi monsterName(buf2, thrower, true); itemName(theItem, buf3, false, true, NULL); sprintf(buf, "%s hurls %s.", buf2, buf3); - message(buf, 0); + message(buf, 0, 3); } for (i=0; ikind].flavor, buf2, tileText(x, y)); - message(buf, 0); + message(buf, 0, 3); if (theItem->kind == POTION_HALLUCINATION && (theItem->flags & ITEM_MAGIC_DETECTED)) { autoIdentify(theItem); } @@ -5982,7 +5982,7 @@ void throwCommand(item *theItem, boolean autoThrow) { } if (theItem->flags & ITEM_CURSED) { sprintf(buf, "You cannot unequip your %s; it appears to be cursed.", theName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); return; } } @@ -6095,19 +6095,19 @@ void relabel(item *theItem) { oldItem->inventoryLetter = theItem->inventoryLetter; itemName(oldItem, theName, true, true, NULL); sprintf(buf, "Relabeled %s as (%c);", theName, oldItem->inventoryLetter); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } theItem->inventoryLetter = newLabel; itemName(theItem, theName, true, true, NULL); sprintf(buf, "%selabeled %s as (%c).", oldItem ? " r" : "R", theName, newLabel); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } else { itemName(theItem, theName, true, true, NULL); sprintf(buf, "%s %s already labeled (%c).", theName, theItem->quantity == 1 ? "is" : "are", theItem->inventoryLetter); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } } } @@ -6120,7 +6120,7 @@ void swapLastEquipment() { if (rogue.swappedIn == NULL || rogue.swappedOut == NULL) { confirmMessages(); - message("You have nothing to swap.", 0); + message("You have nothing to swap.", 0, 3); return; } @@ -6195,7 +6195,7 @@ boolean playerCancelsBlinking(const short originLoc[2], const short targetLoc[2] } } if (possibleDeath && certainDeath) { - message("that would be certain death!", 0); + message("that would be certain death!", 0, 3); return true; } if (possibleDeath @@ -6220,7 +6220,7 @@ boolean useStaffOrWand(item *theItem, boolean *commandsRecorded) { if (theItem->charges <= 0 && (theItem->flags & ITEM_IDENTIFIED)) { itemName(theItem, buf2, false, false, NULL); sprintf(buf, "Your %s has no charges.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); return false; } temporaryMessage("Direction? (, mouse, or ; to confirm)", REFRESH_SIDEBAR); @@ -6299,7 +6299,7 @@ boolean useStaffOrWand(item *theItem, boolean *commandsRecorded) { itemName(theItem, buf2, false, true, NULL); strcat(buf, buf2); strcat(buf, ".)"); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } } } else { @@ -6309,7 +6309,7 @@ boolean useStaffOrWand(item *theItem, boolean *commandsRecorded) { } else { sprintf(buf, "Your %s fizzles; it must be depleted.", buf2); } - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); theItem->flags |= ITEM_MAX_CHARGES_KNOWN; playerTurnEnded(); return false; @@ -6346,7 +6346,7 @@ void useCharm(item *theItem) { switch (theItem->kind) { case CHARM_HEALTH: heal(&player, charmHealing(enchant), false); - message("You feel much healthier.", 0); + message("You feel much healthier.", 0, 3); break; case CHARM_PROTECTION: if (charmProtection(enchant) > player.status[STATUS_SHIELDED]) { @@ -6356,7 +6356,7 @@ void useCharm(item *theItem) { if (boltCatalog[BOLT_SHIELDING].backColor) { flashMonster(&player, boltCatalog[BOLT_SHIELDING].backColor, 100); } - message("A shimmering shield coalesces around you.", 0); + message("A shimmering shield coalesces around you.", 0, 3); break; case CHARM_HASTE: haste(&player, charmEffectDuration(theItem->kind, theItem->enchant1)); @@ -6366,11 +6366,11 @@ void useCharm(item *theItem) { if (player.status[STATUS_BURNING]) { extinguishFireOnCreature(&player); } - message("you no longer fear fire.", 0); + message("you no longer fear fire.", 0, 3); break; case CHARM_INVISIBILITY: imbueInvisibility(&player, charmEffectDuration(theItem->kind, theItem->enchant1)); - message("You shiver as a chill runs up your spine.", 0); + message("You shiver as a chill runs up your spine.", 0, 3); break; case CHARM_TELEPATHY: makePlayerTelepathic(charmEffectDuration(theItem->kind, theItem->enchant1)); @@ -6378,14 +6378,14 @@ void useCharm(item *theItem) { case CHARM_LEVITATION: player.status[STATUS_LEVITATING] = player.maxStatus[STATUS_LEVITATING] = charmEffectDuration(theItem->kind, theItem->enchant1); player.bookkeepingFlags &= ~MB_SEIZED; // break free of holding monsters - message("you float into the air!", 0); + message("you float into the air!", 0, 3); break; case CHARM_SHATTERING: - messageWithColor("your charm emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0); + messageWithColor("your charm emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0, 3); crystalize(charmShattering(enchant)); break; case CHARM_GUARDIAN: - messageWithColor("your charm flashes and the form of a mythical guardian coalesces!", &itemMessageColor, 0); + messageWithColor("your charm flashes and the form of a mythical guardian coalesces!", &itemMessageColor, 0, 3); summonGuardian(theItem); break; case CHARM_TELEPORTATION: @@ -6458,9 +6458,9 @@ void apply(item *theItem, boolean recordCommands) { } player.status[STATUS_NUTRITION] = min(foodTable[theItem->kind].strengthRequired + player.status[STATUS_NUTRITION], STOMACH_SIZE); if (theItem->kind == RATION) { - messageWithColor("That food tasted delicious!", &itemMessageColor, 0); + messageWithColor("That food tasted delicious!", &itemMessageColor, 0, 3); } else { - messageWithColor("My, what a yummy mango!", &itemMessageColor, 0); + messageWithColor("My, what a yummy mango!", &itemMessageColor, 0, 3); } rogue.featRecord[FEAT_ASCETIC] = false; break; @@ -6499,7 +6499,7 @@ void apply(item *theItem, boolean recordCommands) { if (theItem->charges > 0) { itemName(theItem, buf2, false, false, NULL); sprintf(buf, "Your %s hasn't finished recharging.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); return; } if (!commandsRecorded) { @@ -6512,7 +6512,7 @@ void apply(item *theItem, boolean recordCommands) { default: itemName(theItem, buf2, false, true, NULL); sprintf(buf, "you can't apply %s.", buf2); - message(buf, 0); + message(buf, 0, 3); return; } @@ -6706,9 +6706,9 @@ void readScroll(item *theItem) { case SCROLL_IDENTIFY: identify(theItem); updateIdentifiableItems(); - messageWithColor("this is a scroll of identify.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT); + messageWithColor("this is a scroll of identify.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 3); if (numberOfMatchingPackItems(ALL_ITEMS, ITEM_CAN_BE_IDENTIFIED, 0, false) == 0) { - message("everything in your pack is already identified.", 0); + message("everything in your pack is already identified.", 0, 3); break; } do { @@ -6722,7 +6722,7 @@ void readScroll(item *theItem) { confirmMessages(); itemName(theItem, buf2, true, true, NULL); sprintf(buf, "you already know %s %s.", (theItem->quantity > 1 ? "they're" : "it's"), buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } } while (theItem == NULL || !(theItem->flags & ITEM_CAN_BE_IDENTIFIED)); recordKeystroke(theItem->inventoryLetter, false, false); @@ -6730,7 +6730,7 @@ void readScroll(item *theItem) { identify(theItem); itemName(theItem, buf, true, true, NULL); sprintf(buf2, "%s %s.", (theItem->quantity == 1 ? "this is" : "these are"), buf); - messageWithColor(buf2, &itemMessageColor, 0); + messageWithColor(buf2, &itemMessageColor, 0, 3); break; case SCROLL_TELEPORT: teleport(&player, -1, -1, true); @@ -6743,17 +6743,17 @@ void readScroll(item *theItem) { } } if (hadEffect) { - message("your pack glows with a cleansing light, and a malevolent energy disperses.", 0); + message("your pack glows with a cleansing light, and a malevolent energy disperses.", 0, 3); } else { - message("your pack glows with a cleansing light, but nothing happens.", 0); + message("your pack glows with a cleansing light, but nothing happens.", 0, 3); } break; case SCROLL_ENCHANTING: identify(theItem); - messageWithColor("this is a scroll of enchanting.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT); + messageWithColor("this is a scroll of enchanting.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 3); if (!numberOfMatchingPackItems((WEAPON | ARMOR | RING | STAFF | WAND | CHARM), 0, 0, false)) { confirmMessages(); - message("you have nothing that can be enchanted.", 0); + message("you have nothing that can be enchanted.", 0, 3); break; } do { @@ -6762,7 +6762,7 @@ void readScroll(item *theItem) { false); confirmMessages(); if (theItem == NULL || !(theItem->category & (WEAPON | ARMOR | RING | STAFF | WAND | CHARM))) { - message("Can't enchant that.", REQUIRE_ACKNOWLEDGMENT); + message("Can't enchant that.", REQUIRE_ACKNOWLEDGMENT, 3); } if (rogue.gameHasEnded) { return; @@ -6820,10 +6820,10 @@ void readScroll(item *theItem) { } itemName(theItem, buf, false, false, NULL); sprintf(buf2, "your %s gleam%s briefly in the darkness.", buf, (theItem->quantity == 1 ? "s" : "")); - messageWithColor(buf2, &itemMessageColor, 0); + messageWithColor(buf2, &itemMessageColor, 0, 3); if (theItem->flags & ITEM_CURSED) { sprintf(buf2, "a malevolent force leaves your %s.", buf); - messageWithColor(buf2, &itemMessageColor, 0); + messageWithColor(buf2, &itemMessageColor, 0, 3); theItem->flags &= ~ITEM_CURSED; } createFlare(player.xLoc, player.yLoc, SCROLL_ENCHANTMENT_LIGHT); @@ -6837,14 +6837,14 @@ void readScroll(item *theItem) { tempItem->flags |= ITEM_PROTECTED; itemName(tempItem, buf2, false, false, NULL); sprintf(buf, "a protective golden light covers your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); if (tempItem->flags & ITEM_CURSED) { sprintf(buf, "a malevolent force leaves your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); tempItem->flags &= ~ITEM_CURSED; } } else { - message("a protective golden light surrounds you, but it quickly disperses.", 0); + message("a protective golden light surrounds you, but it quickly disperses.", 0, 3); } createFlare(player.xLoc, player.yLoc, SCROLL_PROTECTION_LIGHT); break; @@ -6854,27 +6854,27 @@ void readScroll(item *theItem) { tempItem->flags |= ITEM_PROTECTED; itemName(tempItem, buf2, false, false, NULL); sprintf(buf, "a protective golden light covers your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); if (tempItem->flags & ITEM_CURSED) { sprintf(buf, "a malevolent force leaves your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); tempItem->flags &= ~ITEM_CURSED; } if (rogue.weapon->quiverNumber) { rogue.weapon->quiverNumber = rand_range(1, 60000); } } else { - message("a protective golden light covers your empty hands, but it quickly disperses.", 0); + message("a protective golden light covers your empty hands, but it quickly disperses.", 0, 3); } createFlare(player.xLoc, player.yLoc, SCROLL_PROTECTION_LIGHT); break; case SCROLL_SANCTUARY: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_SACRED_GLYPHS], true, false); - messageWithColor("sprays of color arc to the ground, forming glyphs where they alight.", &itemMessageColor, 0); + messageWithColor("sprays of color arc to the ground, forming glyphs where they alight.", &itemMessageColor, 0, 3); break; case SCROLL_MAGIC_MAPPING: confirmMessages(); - messageWithColor("this scroll has a map on it!", &itemMessageColor, 0); + messageWithColor("this scroll has a map on it!", &itemMessageColor, 0, 3); for (i=0; i 1) { - message("the fabric of space ripples, and monsters appear!", 0); + message("the fabric of space ripples, and monsters appear!", 0, 3); } else if (numberOfMonsters == 1) { - message("the fabric of space ripples, and a monster appears!", 0); + message("the fabric of space ripples, and a monster appears!", 0, 3); } else { - message("the fabric of space boils violently around you, but nothing happens.", 0); + message("the fabric of space boils violently around you, but nothing happens.", 0, 3); } break; case SCROLL_NEGATION: negationBlast("the scroll", DCOLS); break; case SCROLL_SHATTERING: - messageWithColor("the scroll emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0); + messageWithColor("the scroll emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0, 3); crystalize(9); break; case SCROLL_DISCORD: @@ -6966,15 +6966,15 @@ void drinkPotion(item *theItem) { player.info.maxHP += 10; heal(&player, 100, true); updatePlayerRegenerationDelay(); - messageWithColor(buf, &advancementMessageColor, 0); + messageWithColor(buf, &advancementMessageColor, 0, 3); break; case POTION_HALLUCINATION: player.status[STATUS_HALLUCINATING] = player.maxStatus[STATUS_HALLUCINATING] = 300; - message("colors are everywhere! The walls are singing!", 0); + message("colors are everywhere! The walls are singing!", 0, 3); break; case POTION_INCINERATION: //colorFlash(&darkOrange, 0, IN_FIELD_OF_VIEW, 4, 4, player.xLoc, player.yLoc); - message("as you uncork the flask, it explodes in flame!", 0); + message("as you uncork the flask, it explodes in flame!", 0, 3); spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_INCINERATION_POTION], true, false); exposeCreatureToFire(&player); break; @@ -6983,11 +6983,11 @@ void drinkPotion(item *theItem) { player.maxStatus[STATUS_DARKNESS] = max(400, player.maxStatus[STATUS_DARKNESS]); updateMinersLightRadius(); updateVision(true); - message("your vision flickers as a cloak of darkness settles around you!", 0); + message("your vision flickers as a cloak of darkness settles around you!", 0, 3); break; case POTION_DESCENT: colorFlash(&darkBlue, 0, IN_FIELD_OF_VIEW, 3, 3, player.xLoc, player.yLoc); - message("vapor pours out of the flask and causes the floor to disappear!", 0); + message("vapor pours out of the flask and causes the floor to disappear!", 0, 3); spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_HOLE_POTION], true, false); if (!player.status[STATUS_LEVITATING]) { player.bookkeepingFlags |= MB_IS_FALLING; @@ -6999,16 +6999,16 @@ void drinkPotion(item *theItem) { player.status[STATUS_WEAKENED] = 1; } updateEncumbrance(); - messageWithColor("newfound strength surges through your body.", &advancementMessageColor, 0); + messageWithColor("newfound strength surges through your body.", &advancementMessageColor, 0, 3); createFlare(player.xLoc, player.yLoc, POTION_STRENGTH_LIGHT); break; case POTION_POISON: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_POISON_GAS_CLOUD_POTION], true, false); - message("caustic gas billows out of the open flask!", 0); + message("caustic gas billows out of the open flask!", 0, 3); break; case POTION_PARALYSIS: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_PARALYSIS_GAS_CLOUD_POTION], true, false); - message("your muscles stiffen as a cloud of pink gas bursts from the open flask!", 0); + message("your muscles stiffen as a cloud of pink gas bursts from the open flask!", 0, 3); break; case POTION_TELEPATHY: makePlayerTelepathic(300); @@ -7016,14 +7016,14 @@ void drinkPotion(item *theItem) { case POTION_LEVITATION: player.status[STATUS_LEVITATING] = player.maxStatus[STATUS_LEVITATING] = 100; player.bookkeepingFlags &= ~MB_SEIZED; // break free of holding monsters - message("you float into the air!", 0); + message("you float into the air!", 0, 3); break; case POTION_CONFUSION: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_CONFUSION_GAS_CLOUD_POTION], true, false); - message("a shimmering cloud of rainbow-colored gas billows out of the open flask!", 0); + message("a shimmering cloud of rainbow-colored gas billows out of the open flask!", 0, 3); break; case POTION_LICHEN: - message("a handful of tiny spores burst out of the open flask!", 0); + message("a handful of tiny spores burst out of the open flask!", 0, 3); spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_LICHEN_PLANTED], true, false); break; case POTION_DETECT_MAGIC: @@ -7061,14 +7061,14 @@ void drinkPotion(item *theItem) { } if (hadEffect || hadEffect2) { if (hadEffect && hadEffect2) { - message("you can somehow feel the presence of magic on the level and in your pack.", 0); + message("you can somehow feel the presence of magic on the level and in your pack.", 0, 3); } else if (hadEffect) { - message("you can somehow feel the presence of magic on the level.", 0); + message("you can somehow feel the presence of magic on the level.", 0, 3); } else { - message("you can somehow feel the presence of magic in your pack.", 0); + message("you can somehow feel the presence of magic in your pack.", 0, 3); } } else { - message("you can somehow feel the absence of magic on the level and in your pack.", 0); + message("you can somehow feel the absence of magic on the level and in your pack.", 0, 3); } break; case POTION_HASTE_SELF: @@ -7079,14 +7079,14 @@ void drinkPotion(item *theItem) { if (player.status[STATUS_BURNING]) { extinguishFireOnCreature(&player); } - message("a comforting breeze envelops you, and you no longer fear fire.", 0); + message("a comforting breeze envelops you, and you no longer fear fire.", 0, 3); break; case POTION_INVISIBILITY: player.status[STATUS_INVISIBLE] = player.maxStatus[STATUS_INVISIBLE] = 75; - message("you shiver as a chill runs up your spine.", 0); + message("you shiver as a chill runs up your spine.", 0, 3); break; default: - message("you feel very strange, as though your body doesn't know how to react!", REQUIRE_ACKNOWLEDGMENT); + message("you feel very strange, as though your body doesn't know how to react!", REQUIRE_ACKNOWLEDGMENT, 3); } } @@ -7227,7 +7227,7 @@ void unequip(item *theItem) { buf2, theItem->quantity == 1 ? "was" : "were"); confirmMessages(); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); return; } else { if (!unequipItem(theItem, false)) { @@ -7240,7 +7240,7 @@ void unequip(item *theItem) { } confirmMessages(); sprintf(buf, "you are no longer %s %s.", (theItem->category & WEAPON ? "wielding" : "wearing"), buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } playerTurnEnded(); } @@ -7272,7 +7272,7 @@ void drop(item *theItem) { itemName(theItem, buf2, false, false, NULL); sprintf(buf, "you can't; your %s appears to be cursed.", buf2); confirmMessages(); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); } else if (canDrop()) { recordKeystrokeSequence(command); if (theItem->flags & ITEM_EQUIPPED) { @@ -7282,11 +7282,11 @@ void drop(item *theItem) { theItem->flags |= ITEM_PLAYER_AVOIDS; // Try not to pick up stuff you've already dropped. itemName(theItem, buf2, true, true, NULL); sprintf(buf, "You dropped %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); playerTurnEnded(); } else { confirmMessages(); - message("There is already something there.", 0); + message("There is already something there.", 0, 3); } } @@ -7314,7 +7314,7 @@ item *promptForItemOfType(unsigned short category, if (keystroke < 'a' || keystroke > 'z') { confirmMessages(); if (keystroke != ESCAPE_KEY && keystroke != ACKNOWLEDGE_KEY) { - message("Invalid entry.", 0); + message("Invalid entry.", 0, 3); } return NULL; } @@ -7322,7 +7322,7 @@ item *promptForItemOfType(unsigned short category, theItem = itemOfPackLetter(keystroke); if (theItem == NULL) { confirmMessages(); - message("No such item.", 0); + message("No such item.", 0, 3); return NULL; } @@ -7350,7 +7350,7 @@ item *itemAtLoc(short x, short y) { pmap[x][y].flags &= ~HAS_ITEM; hiliteCell(x, y, &white, 75, true); rogue.automationActive = false; - message("ERROR: An item was supposed to be here, but I couldn't find it.", REQUIRE_ACKNOWLEDGMENT); + message("ERROR: An item was supposed to be here, but I couldn't find it.", REQUIRE_ACKNOWLEDGMENT, 3); refreshDungeonCell(x, y); } return theItem; @@ -7485,7 +7485,7 @@ boolean equipItem(item *theItem, boolean force, item *unequipHint) { } confirmMessages(); - messageWithColor(buf1, &itemMessageColor, false); + messageWithColor(buf1, &itemMessageColor, false, 3); if (theItem->flags & ITEM_CURSED) { itemName(theItem, buf2, false, false, NULL); @@ -7503,7 +7503,7 @@ boolean equipItem(item *theItem, boolean force, item *unequipHint) { sprintf(buf1, "your %s seizes you with a malevolent force.", buf2); break; } - messageWithColor(buf1, &itemMessageColor, 0); + messageWithColor(buf1, &itemMessageColor, 0, 3); } } @@ -7523,7 +7523,7 @@ boolean unequipItem(item *theItem, boolean force) { buf2, theItem->quantity == 1 ? "s" : ""); confirmMessages(); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 3); return false; } theItem->flags &= ~ITEM_EQUIPPED; diff --git a/src/brogue/MainMenu.c b/src/brogue/MainMenu.c index 7915be44..63cc546a 100644 --- a/src/brogue/MainMenu.c +++ b/src/brogue/MainMenu.c @@ -344,7 +344,7 @@ void titleMenu() { initializeMenuFlames(true, colors, colorStorage, colorSources, flames, mask); rogue.creaturesWillFlashThisTurn = false; // total unconscionable hack - playSpeech("Welcome to Brogue!", false, false); + playSpeech("Welcome to Brogue!", 1); do { if (isApplicationActive()) { diff --git a/src/brogue/Monsters.c b/src/brogue/Monsters.c index 40a6f39a..0390e769 100644 --- a/src/brogue/Monsters.c +++ b/src/brogue/Monsters.c @@ -572,7 +572,7 @@ creature *cloneMonster(creature *monst, boolean announce, boolean placeClone) { if (announce && canSeeMonster(newMonst)) { monsterName(monstName, newMonst, false); sprintf(buf, "another %s appears!", monstName); - message(buf, 0); + message(buf, 0, 2); } } @@ -1006,7 +1006,7 @@ boolean summonMinions(creature *summoner) { } else { sprintf(buf, "%s incants darkly!", monstName); } - message(buf, 0); + message(buf, 0, 2); } if (summoner->info.abilityFlags & MA_ENTER_SUMMONS) { @@ -1102,7 +1102,7 @@ void spawnPeriodicHorde() { // Instantally disentangles the player/creature. Useful for magical displacement like teleport and blink. void disentangle(creature *monst) { if (monst == &player && monst->status[STATUS_STUCK]) { - message("you break free!", false); + message("you break free!", false, 2); } monst->status[STATUS_STUCK] = 0; } @@ -1842,7 +1842,7 @@ void decrementMonsterStatus(creature *monst) { sprintf(buf2, "%s burns %s.", buf, (monst->info.flags & MONST_INANIMATE) ? "up" : "to death"); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); } return; } @@ -1859,7 +1859,7 @@ void decrementMonsterStatus(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s dissipates into thin air.", buf); - messageWithColor(buf2, &white, 0); + messageWithColor(buf2, &white, 0, 2); } return; } @@ -1872,7 +1872,7 @@ void decrementMonsterStatus(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s dies of poison.", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); } return; } @@ -2244,7 +2244,7 @@ void perimeterCoords(short returnCoords[2], short n) { returnCoords[0] = 5; returnCoords[1] = (n - 31) - 4; } else { - message("ERROR! Bad perimeter coordinate request!", REQUIRE_ACKNOWLEDGMENT); + message("ERROR! Bad perimeter coordinate request!", REQUIRE_ACKNOWLEDGMENT, 0); returnCoords[0] = returnCoords[1] = 0; // garbage in, garbage out } } @@ -3088,7 +3088,7 @@ void moveAlly(creature *monst) { if (canSeeMonster(monst)) { monsterName(monstName, monst, true); sprintf(buf, "%s begins %s the fallen %s.", monstName, monsterText[monst->info.monsterID].absorbing, monst->targetCorpseName); - messageWithColor(buf, &goodMessageColor, 0); + messageWithColor(buf, &goodMessageColor, 0, 2); } monst->corpseAbsorptionCounter = 20; monst->bookkeepingFlags |= MB_ABSORBING; @@ -3157,7 +3157,7 @@ boolean updateMonsterCorpseAbsorption(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf2, monst, true); sprintf(buf, "%s finished %s the %s.", buf2, monsterText[monst->info.monsterID].absorbing, monst->targetCorpseName); - messageWithColor(buf, &goodMessageColor, 0); + messageWithColor(buf, &goodMessageColor, 0, 2); if (monst->absorptionBolt != BOLT_NONE) { sprintf(buf, "%s %s!", buf2, boltCatalog[monst->absorptionBolt].abilityDescription); } else if (monst->absorbBehavior) { @@ -3166,7 +3166,7 @@ boolean updateMonsterCorpseAbsorption(creature *monst) { sprintf(buf, "%s now %s!", buf2, monsterAbilityFlagDescriptions[unflag(monst->absorptionFlags)]); } resolvePronounEscapes(buf, monst); - messageWithColor(buf, &advancementMessageColor, 0); + messageWithColor(buf, &advancementMessageColor, 0, 2); } monst->absorptionFlags = 0; monst->absorptionBolt = BOLT_NONE; diff --git a/src/brogue/Movement.c b/src/brogue/Movement.c index f65536f7..998c8036 100644 --- a/src/brogue/Movement.c +++ b/src/brogue/Movement.c @@ -405,7 +405,7 @@ void speakLocation(char *locationDescription, short x, short y) { strcat(locationMessage, posY); strcat(locationMessage, posX); - playSpeech(locationMessage, true, true); + playSpeech(locationMessage, 0); } void printLocationDescription(short x, short y) { @@ -454,7 +454,7 @@ void useKeyAt(item *theItem, short x, short y) { buf2, preposition, terrainName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 1); deleteItem(theItem); } else if (removeItemFromChain(theItem, floorItems)) { deleteItem(theItem); @@ -551,7 +551,7 @@ void freeCaptive(creature *monst) { becomeAllyWith(monst); monsterName(monstName, monst, false); sprintf(buf, "you free the grateful %s and gain a faithful ally.", monstName); - message(buf, 0); + message(buf, 0, 2); } boolean freeCaptivesEmbeddedAt(short x, short y) { @@ -872,7 +872,7 @@ boolean playerMoves(short direction) { layer = layerWithTMFlag(newX, newY, TM_PROMOTES_ON_PLAYER_ENTRY); if (tileCatalog[pmap[newX][newY].layers[layer]].flags & T_OBSTRUCTS_PASSABILITY) { committed = true; - message(tileCatalog[pmap[newX][newY].layers[layer]].flavorText, 0); + message(tileCatalog[pmap[newX][newY].layers[layer]].flavorText, 0, 1); promoteTile(newX, newY, layer, false); playerTurnEnded(); return true; @@ -984,12 +984,12 @@ boolean playerMoves(short direction) { committed = true; sprintf(buf, "you struggle but %s is holding your legs!", monstName); moveEntrancedMonsters(direction); - message(buf, 0); + message(buf, 0, 2); playerTurnEnded(); return true; } else { sprintf(buf, "you cannot move; %s is holding your legs!", monstName); - message(buf, 0); + message(buf, 0, 2); cancelKeystroke(); return false; } @@ -1005,7 +1005,7 @@ boolean playerMoves(short direction) { && player.status[STATUS_IMMUNE_TO_FIRE] <= 1 && !cellHasTerrainFlag(newX, newY, T_ENTANGLES) && !cellHasTMFlag(newX, newY, TM_IS_SECRET)) { - message("that would be certain death!", 0); + message("that would be certain death!", 0, 2); brogueAssert(!committed); cancelKeystroke(); return false; // player won't willingly step into lava @@ -1098,7 +1098,7 @@ boolean playerMoves(short direction) { // Don't interrupt exploration with this message. if (--player.status[STATUS_STUCK]) { if (!rogue.automationActive) { - message("you struggle but cannot free yourself.", 0); + message("you struggle but cannot free yourself.", 0, 2); } moveEntrancedMonsters(direction); committed = true; @@ -1106,7 +1106,7 @@ boolean playerMoves(short direction) { return true; } else { if (!rogue.automationActive) { - message("you break free!", 0); + message("you break free!", 0, 2); } if (tileCatalog[pmap[x][y].layers[SURFACE]].flags & T_ENTANGLES) { pmap[x][y].layers[SURFACE] = NOTHING; @@ -1191,7 +1191,7 @@ boolean playerMoves(short direction) { refreshDungeonCell(newX, newY); } - messageWithColor(tileCatalog[i].flavorText, &backgroundMessageColor, 0); + messageWithColor(tileCatalog[i].flavorText, &backgroundMessageColor, 0, 2); } } return playerMoved; @@ -1633,7 +1633,7 @@ void travel(short x, short y, boolean autoConfirm) { } if (!(pmap[x][y].flags & (DISCOVERED | MAGIC_MAPPED))) { - message("You have not explored that location.", 0); + message("You have not explored that location.", 0, 2); return; } @@ -1653,7 +1653,7 @@ void travel(short x, short y, boolean autoConfirm) { staircaseConfirmKey = 0; } displayRoute(distanceMap, false); - message("Travel this route? (y/n)", 0); + message("Travel this route? (y/n)", 0, 2); do { nextBrogueEvent(&theEvent, true, false, false); @@ -1682,7 +1682,7 @@ void travel(short x, short y, boolean autoConfirm) { // } } else { rogue.cursorLoc[0] = rogue.cursorLoc[1] = -1; - message("No path is available.", 0); + message("No path is available.", 0, 2); } freeGrid(distanceMap); } @@ -1915,11 +1915,11 @@ boolean explore(short frameDelay) { headingToStairs = false; if (player.status[STATUS_CONFUSED]) { - message("Not while you're confused.", 0); + message("Not while you're confused.", 0, 2); return false; } if (cellHasTerrainFlag(player.xLoc, player.yLoc, T_OBSTRUCTS_PASSABILITY)) { - message("Not while you're trapped.", 0); + message("Not while you're trapped.", 0, 2); return false; } @@ -1942,7 +1942,7 @@ boolean explore(short frameDelay) { if (!rogue.autoPlayingLevel) { message(KEYBOARD_LABELS ? "Exploring... press any key to stop." : "Exploring... touch anywhere to stop.", - 0); + 0, 0); // A little hack so the exploring message remains bright while exploring and then auto-dims when // another message is displayed: confirmMessages(); @@ -2009,7 +2009,7 @@ void autoPlayLevel(boolean fastForward) { rogue.autoPlayingLevel = true; confirmMessages(); - message(KEYBOARD_LABELS ? "Playing... press any key to stop." : "Playing... touch anywhere to stop.", 0); + message(KEYBOARD_LABELS ? "Playing... press any key to stop." : "Playing... touch anywhere to stop.", 0, 0); // explore until we are not making progress do { @@ -2168,7 +2168,7 @@ boolean search(short searchStrength) { boolean proposeOrConfirmLocation(short x, short y, char *failureMessage) { boolean retval = false; if (player.xLoc == x && player.yLoc == y) { - message("you are already there.", 0); + message("you are already there.", 0, 0); } else if (pmap[x][y].flags & (DISCOVERED | MAGIC_MAPPED)) { if (rogue.cursorLoc[0] == x && rogue.cursorLoc[1] == y) { retval = true; @@ -2177,7 +2177,7 @@ boolean proposeOrConfirmLocation(short x, short y, char *failureMessage) { rogue.cursorLoc[1] = y; } } else { - message(failureMessage, 0); + message(failureMessage, 0, 0); } return retval; } @@ -2191,7 +2191,7 @@ boolean useStairs(short stairDirection) { //copyDisplayBuffer(fromBuf, displayBuffer); rogue.cursorLoc[0] = rogue.cursorLoc[1] = -1; rogue.depthLevel++; - message("You descend.", 0); + message("You descend.", 0, 1); startLevel(rogue.depthLevel - 1, stairDirection); if (rogue.depthLevel > rogue.deepestLevel) { rogue.deepestLevel = rogue.depthLevel; @@ -2202,8 +2202,8 @@ boolean useStairs(short stairDirection) { victory(true); } else { confirmMessages(); - messageWithColor("the crystal archway repels you with a mysterious force!", &lightBlue, 0); - messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0); + messageWithColor("the crystal archway repels you with a mysterious force!", &lightBlue, 0, 1); + messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0, 1); } succeeded = true; } else { @@ -2214,7 +2214,7 @@ boolean useStairs(short stairDirection) { victory(false); } else { //copyDisplayBuffer(fromBuf, displayBuffer); - message("You ascend.", 0); + message("You ascend.", 0, 1); startLevel(rogue.depthLevel + 1, stairDirection); //copyDisplayBuffer(toBuf, displayBuffer); //irisFadeBetweenBuffers(fromBuf, toBuf, mapToWindowX(player.xLoc), mapToWindowY(player.yLoc), 20, true); @@ -2222,8 +2222,8 @@ boolean useStairs(short stairDirection) { succeeded = true; } else { confirmMessages(); - messageWithColor("The dungeon exit is magically sealed!", &lightBlue, 0); - messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0); + messageWithColor("The dungeon exit is magically sealed!", &lightBlue, 0, 1); + messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0, 1); } } @@ -2266,7 +2266,7 @@ void updateFieldOfViewDisplay(boolean updateDancingTerrain, boolean refreshDispl if (theItem && (theItem->category & KEY)) { itemName(theItem, name, false, true, NULL); sprintf(buf, "you see %s.", name); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 1); } } if (!(pmap[i][j].flags & MAGIC_MAPPED) @@ -2274,7 +2274,7 @@ void updateFieldOfViewDisplay(boolean updateDancingTerrain, boolean refreshDispl strcpy(name, tileCatalog[pmap[i][j].layers[layerWithTMFlag(i, j, TM_INTERRUPT_EXPLORATION_WHEN_SEEN)]].description); sprintf(buf, "you see %s.", name); - messageWithColor(buf, &backgroundMessageColor, 0); + messageWithColor(buf, &backgroundMessageColor, 0, 1); } } discoverCell(i, j); diff --git a/src/brogue/Recordings.c b/src/brogue/Recordings.c index 069325a9..255fb8e4 100644 --- a/src/brogue/Recordings.c +++ b/src/brogue/Recordings.c @@ -312,7 +312,7 @@ void playbackPanic() { refreshSideBar(-1, -1, false); confirmMessages(); - message("Playback is out of sync.", 0); + message("Playback is out of sync.", 0, 0); printTextBox(OOS_APOLOGY, 0, 0, 0, &white, &black, rbuf, NULL, 0); @@ -360,7 +360,7 @@ void recallEvent(rogueEvent *event) { case END_OF_RECORDING: case EVENT_ERROR: default: - message("Unrecognized event type in playback.", REQUIRE_ACKNOWLEDGMENT); + message("Unrecognized event type in playback.", REQUIRE_ACKNOWLEDGMENT, 0); printf("Unrecognized event type in playback: event ID %i", c); tryAgain = true; playbackPanic(); @@ -817,13 +817,13 @@ void pausePlayback() { if (!rogue.playbackPaused) { rogue.playbackPaused = true; messageWithColor(KEYBOARD_LABELS ? "recording paused. Press space to play." : "recording paused.", - &teal, 0); + &teal, 0, 0); refreshSideBar(-1, -1, false); //oldRNG = rogue.RNG; //rogue.RNG = RNG_SUBSTANTIVE; mainInputLoop(); //rogue.RNG = oldRNG; - messageWithColor("recording unpaused.", &teal, 0); + messageWithColor("recording unpaused.", &teal, 0, 0); rogue.playbackPaused = false; refreshSideBar(-1, -1, false); rogue.playbackDelayThisTurn = DEFAULT_PLAYBACK_DELAY; @@ -877,9 +877,9 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { displayLevel(); refreshSideBar(-1, -1, false); if (rogue.playbackOmniscience) { - messageWithColor("Omniscience enabled.", &teal, 0); + messageWithColor("Omniscience enabled.", &teal, 0, 0); } else { - messageWithColor("Omniscience disabled.", &teal, 0); + messageWithColor("Omniscience disabled.", &teal, 0, 0); } return true; case ASCEND_KEY: @@ -959,7 +959,7 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { rogue.nextGame = NG_VIEW_RECORDING; rogue.gameHasEnded = true; } else { - message("File not found.", 0); + message("File not found.", 0, 0); } } rogue.playbackMode = true; @@ -973,7 +973,7 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { rogue.nextGame = NG_OPEN_GAME; rogue.gameHasEnded = true; } else { - message("File not found.", 0); + message("File not found.", 0, 0); } } rogue.playbackMode = true; @@ -999,10 +999,10 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { refreshSideBar(-1, -1, false); if (rogue.trueColorMode) { messageWithColor(KEYBOARD_LABELS ? "Color effects disabled. Press '\\' again to enable." : "Color effects disabled.", - &teal, 0); + &teal, 0, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Color effects enabled. Press '\\' again to disable." : "Color effects enabled.", - &teal, 0); + &teal, 0, 0); } return true; case AGGRO_DISPLAY_KEY: @@ -1011,10 +1011,10 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { refreshSideBar(-1, -1, false); if (rogue.displayAggroRangeMode) { messageWithColor(KEYBOARD_LABELS ? "Stealth range displayed. Press ']' again to hide." : "Stealth range displayed.", - &teal, 0); + &teal, 0, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Stealth range hidden. Press ']' again to display." : "Stealth range hidden.", - &teal, 0); + &teal, 0, 0); } return true; case GRAPHICS_KEY: @@ -1024,17 +1024,17 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { case TEXT_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to text mode. Press 'G' again to enable tiles." - : "Switched to text mode.", &teal, 0); + : "Switched to text mode.", &teal, 0, 0); break; case TILES_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to graphical tiles. Press 'G' again to enable hybrid mode." - : "Switched to graphical tiles.", &teal, 0); + : "Switched to graphical tiles.", &teal, 0, 0); break; case HYBRID_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to hybrid mode. Press 'G' again to disable tiles." - : "Switched to hybrid mode.", &teal, 0); + : "Switched to hybrid mode.", &teal, 0, 0); break; } } @@ -1189,7 +1189,7 @@ void saveGame() { rename(currentFilePath, filePath); strcpy(currentFilePath, filePath); rogue.recording = false; - message("Saved.", REQUIRE_ACKNOWLEDGMENT); + message("Saved.", REQUIRE_ACKNOWLEDGMENT, 0); rogue.gameHasEnded = true; } else { askAgain = true; @@ -1415,7 +1415,7 @@ boolean selectFile(char *prompt, char *defaultName, char *suffix) { retval = true; } else { confirmMessages(); - message("File not found.", 0); + message("File not found.", 0, 0); retval = false; } } @@ -1496,7 +1496,7 @@ void parseFile() { recordingLocation = oldRecLoc; lengthOfPlaybackFile = oldLength; locationInRecordingBuffer = oldBufLoc; - message("File parsed.", 0); + message("File parsed.", 0, 0); } else { confirmMessages(); } diff --git a/src/brogue/Rogue.h b/src/brogue/Rogue.h index 6105029f..fd7c1995 100644 --- a/src/brogue/Rogue.h +++ b/src/brogue/Rogue.h @@ -356,7 +356,7 @@ typedef struct rogueEvent { } rogueEvent; typedef struct speechData { - boolean interruptable; + short priority; char message[DCOLS]; } speechData; @@ -2751,7 +2751,7 @@ extern "C" { void notifyEvent(short eventId, int data1, int data2, const char *str1, const char *str2); boolean takeScreenshot(); enum graphicsModes setGraphicsMode(enum graphicsModes mode); - void playSpeech(char *text, boolean interruptable, boolean interruptPrevious); + void playSpeech(char *text, short priority); boolean controlKeyIsDown(); boolean shiftKeyIsDown(); short getHighScoresList(rogueHighScoresEntry returnList[HIGH_SCORES_COUNT]); @@ -2924,9 +2924,9 @@ extern "C" { void displayRecentMessages(); void displayMessageArchive(); void temporaryMessage(const char *msg1, enum messageFlags flags); - void messageWithColor(char *msg, color *theColor, enum messageFlags flags); + void messageWithColor(char *msg, color *theColor, enum messageFlags flags, short speechPriority); void flavorMessage(char *msg); - void message(const char *msg, enum messageFlags flags); + void message(const char *msg, enum messageFlags flags, short speechPriority); void displayMoreSignWithoutWaitingForAcknowledgment(); void displayMoreSign(); short encodeMessageColor(char *msg, short i, const color *theColor); diff --git a/src/brogue/RogueMain.c b/src/brogue/RogueMain.c index 66ac6e4e..6248968d 100644 --- a/src/brogue/RogueMain.c +++ b/src/brogue/RogueMain.c @@ -123,16 +123,16 @@ void benchmark() { void welcome() { char buf[DCOLS*3], buf2[DCOLS*3]; - message("Hello and welcome, adventurer, to the Dungeons of Doom!", 0); + message("Hello and welcome, adventurer, to the Dungeons of Doom!", 0, 1); strcpy(buf, "Retrieve the "); encodeMessageColor(buf, strlen(buf), &itemMessageColor); strcat(buf, "Amulet of Yendor"); encodeMessageColor(buf, strlen(buf), &white); sprintf(buf2, " from the %ith floor and escape with it!", AMULET_LEVEL); strcat(buf, buf2); - message(buf, 0); + message(buf, 0, 1); if (KEYBOARD_LABELS) { - messageWithColor("Press for help at any time.", &backgroundMessageColor, 0); + messageWithColor("Press for help at any time.", &backgroundMessageColor, 0, 1); } flavorMessage("The doors to the dungeon slam shut behind you."); } @@ -744,9 +744,9 @@ void startLevel(short oldLevelNumber, short stairDirection) { if (!levels[rogue.depthLevel-1].visited) { levels[rogue.depthLevel-1].visited = true; if (rogue.depthLevel == AMULET_LEVEL) { - messageWithColor("An alien energy permeates the area. The Amulet of Yendor must be nearby!", &itemMessageColor, 0); + messageWithColor("An alien energy permeates the area. The Amulet of Yendor must be nearby!", &itemMessageColor, 0, 2); } else if (rogue.depthLevel == DEEPEST_LEVEL) { - messageWithColor("An overwhelming sense of peace and tranquility settles upon you.", &lightBlue, 0); + messageWithColor("An overwhelming sense of peace and tranquility settles upon you.", &lightBlue, 0, 2); } } @@ -972,7 +972,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { if (rogue.playbackMode) { playback = rogue.playbackMode; rogue.playbackMode = false; - message("(The player quit at this point.)", REQUIRE_ACKNOWLEDGMENT); + message("(The player quit at this point.)", REQUIRE_ACKNOWLEDGMENT, 2); rogue.playbackMode = playback; } } else { @@ -987,7 +987,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { } player.currentHP = 0; // So it shows up empty in the side bar. refreshSideBar(-1, -1, false); - messageWithColor(buf, &badMessageColor, 0); + messageWithColor(buf, &badMessageColor, 0, 3); displayMoreSignWithoutWaitingForAcknowledgment(); do { @@ -1017,7 +1017,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { rogue.creaturesWillFlashThisTurn = false; if (D_IMMORTAL && !rogue.quit) { - message("...but then you get better.", 0); + message("...but then you get better.", 0, 3); player.currentHP = player.info.maxHP; if (player.status[STATUS_NUTRITION] < 10) { player.status[STATUS_NUTRITION] = STOMACH_SIZE; @@ -1126,7 +1126,7 @@ void victory(boolean superVictory) { // First screen - Congratulations... // if (superVictory) { - message( "Light streams through the portal, and you are teleported out of the dungeon.", 0); + message( "Light streams through the portal, and you are teleported out of the dungeon.", 0, 3); copyDisplayBuffer(dbuf, displayBuffer); funkyFade(dbuf, &superVictoryColor, 0, 240, mapToWindowX(player.xLoc), mapToWindowY(player.yLoc), false); displayMoreSign(); @@ -1136,7 +1136,7 @@ void victory(boolean superVictory) { deleteMessages(); strcpy(displayedMessage[0], "You retire in splendor, forever renowned for your remarkable triumph. "); } else { - message( "You are bathed in sunlight as you throw open the heavy doors.", 0); + message( "You are bathed in sunlight as you throw open the heavy doors.", 0, 3); copyDisplayBuffer(dbuf, displayBuffer); funkyFade(dbuf, &white, 0, 240, mapToWindowX(player.xLoc), mapToWindowY(player.yLoc), false); displayMoreSign(); @@ -1260,22 +1260,22 @@ void victory(boolean superVictory) { void enableEasyMode() { if (rogue.easyMode) { - message("Alas, all hope of salvation is lost. You shed scalding tears at your plight.", 0); + message("Alas, all hope of salvation is lost. You shed scalding tears at your plight.", 0, 3); return; } - message("A dark presence surrounds you, whispering promises of stolen power.", REQUIRE_ACKNOWLEDGMENT); + message("A dark presence surrounds you, whispering promises of stolen power.", REQUIRE_ACKNOWLEDGMENT, 3); if (confirm("Succumb to demonic temptation (i.e. enable Easy Mode)?", false)) { recordKeystroke(EASY_MODE_KEY, false, true); - message("An ancient and terrible evil burrows into your willing flesh!", REQUIRE_ACKNOWLEDGMENT); + message("An ancient and terrible evil burrows into your willing flesh!", REQUIRE_ACKNOWLEDGMENT, 3); player.info.displayChar = '&'; rogue.easyMode = true; refreshDungeonCell(player.xLoc, player.yLoc); refreshSideBar(-1, -1, false); - message("Wracked by spasms, your body contorts into an ALL-POWERFUL AMPERSAND!!!", 0); - message("You have a feeling that you will take 20% as much damage from now on.", 0); - message("But great power comes at a great price -- specifically, a 90% income tax rate.", 0); + message("Wracked by spasms, your body contorts into an ALL-POWERFUL AMPERSAND!!!", 0, 3); + message("You have a feeling that you will take 20% as much damage from now on.", 0, 3); + message("But great power comes at a great price -- specifically, a 90% income tax rate.", 0, 3); } else { - message("The evil dissipates, hissing, from the air around you.", 0); + message("The evil dissipates, hissing, from the air around you.", 0, 3); } } diff --git a/src/brogue/Time.c b/src/brogue/Time.c index c8fa0a73..82bc8742 100644 --- a/src/brogue/Time.c +++ b/src/brogue/Time.c @@ -170,7 +170,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { if (monst == &player) { sprintf(buf, "you plunge into %s!", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_LAVA_INSTA_DEATH)]].description); - message(buf, REQUIRE_ACKNOWLEDGMENT); + message(buf, REQUIRE_ACKNOWLEDGMENT, 2); sprintf(buf, "Killed by %s", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_LAVA_INSTA_DEATH)]].description); gameOver(buf, true); @@ -186,7 +186,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { s += 3; } sprintf(buf2, "%s is consumed by the %s instantly!", buf, s); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); } killCreature(monst, false); spawnDungeonFeature(*x, *y, &(dungeonFeatureCatalog[DF_CREATURE_FIRE]), true, false); @@ -226,10 +226,10 @@ void applyInstantTileEffectsToCreature(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "a pressure plate clicks underneath %s!", buf); - message(buf2, REQUIRE_ACKNOWLEDGMENT); + message(buf2, REQUIRE_ACKNOWLEDGMENT, 2); } else if (playerCanSee(*x, *y)) { // usually means an invisible monster - message("a pressure plate clicks!", 0); + message("a pressure plate clicks!", 0, 2); } for (layer = 0; layer < NUMBER_TERRAIN_LAYERS; layer++) { if (tileCatalog[pmap[*x][*y].layers[layer]].flags & T_IS_DF_TRAP) { @@ -284,14 +284,14 @@ void applyInstantTileEffectsToCreature(creature *monst) { // Don't interrupt exploration with this message. sprintf(buf2, "you are stuck fast in %s!", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_ENTANGLES)]].description); - message(buf2, 0); + message(buf2, 0, 2); } } else if (canDirectlySeeMonster(monst)) { // it's a monster if (!rogue.automationActive) { monsterName(buf, monst, true); sprintf(buf2, "%s is stuck fast in %s!", buf, tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_ENTANGLES)]].description); - message(buf2, 0); + message(buf2, 0, 2); } } } @@ -305,11 +305,11 @@ void applyInstantTileEffectsToCreature(creature *monst) { if (monst == &player) { rogue.disturbed = true; for (layer = 0; layer < NUMBER_TERRAIN_LAYERS && !(tileCatalog[pmap[*x][*y].layers[layer]].flags & T_CAUSES_EXPLOSIVE_DAMAGE); layer++); - message(tileCatalog[pmap[*x][*y].layers[layer]].flavorText, 0); + message(tileCatalog[pmap[*x][*y].layers[layer]].flavorText, 0, 2); if (rogue.armor && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_DAMPENING) { itemName(rogue.armor, buf2, false, false, NULL); sprintf(buf, "Your %s pulses and absorbs the damage.", buf2); - messageWithColor(buf, &goodMessageColor, 0); + messageWithColor(buf, &goodMessageColor, 0, 2); autoIdentify(rogue.armor); } else if (inflictDamage(NULL, &player, damage, &yellow, false)) { strcpy(buf2, tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_CAUSES_EXPLOSIVE_DAMAGE)]].description); @@ -330,14 +330,14 @@ void applyInstantTileEffectsToCreature(creature *monst) { sprintf(buf2, "%s %s %s.", buf, (monst->info.flags & MONST_INANIMATE) ? "is destroyed by" : "dies in", buf3); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); refreshDungeonCell(*x, *y); return; } else { // if survived sprintf(buf2, "%s engulfs %s.", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_CAUSES_EXPLOSIVE_DAMAGE)]].description, buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); } } } @@ -350,7 +350,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_RESPIRATION) { if (!(rogue.armor->flags & ITEM_RUNIC_IDENTIFIED)) { - message("Your armor trembles and a pocket of clean air swirls around you.", 0); + message("Your armor trembles and a pocket of clean air swirls around you.", 0, 2); autoIdentify(rogue.armor); } } else { @@ -370,7 +370,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { monsterName(buf, monst, true); sprintf(buf2, "%s choke%s and gag%s on the overpowering stench of decay.", buf, (monst == &player ? "": "s"), (monst == &player ? "": "s")); - message(buf2, 0); + message(buf2, 0, 2); } monst->status[STATUS_NAUSEOUS] = monst->maxStatus[STATUS_NAUSEOUS] = max(monst->status[STATUS_NAUSEOUS], 20); } @@ -387,7 +387,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { flashMonster(monst, &confusionGasColor, 100); monsterName(buf, monst, true); sprintf(buf2, "%s %s very confused!", buf, (monst == &player ? "feel": "looks")); - message(buf2, 0); + message(buf2, 0, 2); } monst->status[STATUS_CONFUSED] = monst->maxStatus[STATUS_CONFUSED] = max(monst->status[STATUS_CONFUSED], 25); } @@ -401,7 +401,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { flashMonster(monst, &pink, 100); monsterName(buf, monst, true); sprintf(buf2, "%s %s paralyzed!", buf, (monst == &player ? "are": "is")); - message(buf2, (monst == &player) ? REQUIRE_ACKNOWLEDGMENT : 0); + message(buf2, (monst == &player) ? REQUIRE_ACKNOWLEDGMENT : 0, 2); } monst->status[STATUS_PARALYZED] = monst->maxStatus[STATUS_PARALYZED] = max(monst->status[STATUS_PARALYZED], 20); if (monst == &player) { @@ -425,7 +425,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { flashMonster(monst, &green, 100); monsterName(buf, monst, true); sprintf(buf2, "the lichen's grasping tendrils poison %s.", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); } damage = max(0, 5 - monst->status[STATUS_POISONED]); addPoison(monst, damage, 0); // Lichen doesn't increase poison concentration above 1. @@ -482,7 +482,7 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { sprintf(buf, "%s float%s away in the current!", buf2, (theItem->quantity == 1 ? "s" : "")); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 2); } } } @@ -501,12 +501,12 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { if (monst == &player) { if (rogue.armor && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_RESPIRATION) { if (!(rogue.armor->flags & ITEM_RUNIC_IDENTIFIED)) { - message("Your armor trembles and a pocket of clean air swirls around you.", 0); + message("Your armor trembles and a pocket of clean air swirls around you.", 0, 2); autoIdentify(rogue.armor); } } else { rogue.disturbed = true; - messageWithColor(tileCatalog[pmap[x][y].layers[layer]].flavorText, &badMessageColor, 0); + messageWithColor(tileCatalog[pmap[x][y].layers[layer]].flavorText, &badMessageColor, 0, 2); if (inflictDamage(NULL, &player, damage, tileCatalog[pmap[x][y].layers[layer]].backColor, true)) { sprintf(buf, "Killed by %s", tileCatalog[pmap[x][y].layers[layer]].description); gameOver(buf, true); @@ -521,7 +521,7 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s dies.", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); } refreshDungeonCell(x, y); return; @@ -538,7 +538,7 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { if (monst->currentHP < monst->info.maxHP) { monst->currentHP = min(monst->currentHP + damage, monst->info.maxHP); if (monst == &player) { - messageWithColor("you feel much better.", &goodMessageColor, 0); + messageWithColor("you feel much better.", &goodMessageColor, 0, 2); } } } @@ -809,21 +809,21 @@ void checkNutrition() { if (player.status[STATUS_NUTRITION] == HUNGER_THRESHOLD) { player.status[STATUS_NUTRITION]--; sprintf(buf, "you are hungry%s.", foodWarning); - message(buf, foodWarning[0] ? REQUIRE_ACKNOWLEDGMENT : 0); + message(buf, foodWarning[0] ? REQUIRE_ACKNOWLEDGMENT : 0, 2); } else if (player.status[STATUS_NUTRITION] == WEAK_THRESHOLD) { player.status[STATUS_NUTRITION]--; sprintf(buf, "you feel weak with hunger%s.", foodWarning); - message(buf, REQUIRE_ACKNOWLEDGMENT); + message(buf, REQUIRE_ACKNOWLEDGMENT, 2); } else if (player.status[STATUS_NUTRITION] == FAINT_THRESHOLD) { player.status[STATUS_NUTRITION]--; sprintf(buf, "you feel faint with hunger%s.", foodWarning); - message(buf, REQUIRE_ACKNOWLEDGMENT); + message(buf, REQUIRE_ACKNOWLEDGMENT, 2); } else if (player.status[STATUS_NUTRITION] <= 1) { // Force the player to eat something if he has it for (theItem = packItems->nextItem; theItem != NULL; theItem = theItem->nextItem) { if (theItem->category == FOOD) { sprintf(buf, "unable to control your hunger, you eat a %s.", (theItem->kind == FRUIT ? "mango" : "ration of food")); - messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT); + messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 2); apply(theItem, false); break; } @@ -832,7 +832,7 @@ void checkNutrition() { if (player.status[STATUS_NUTRITION] == 1) { // Didn't manage to eat any food above. player.status[STATUS_NUTRITION] = 0; // So the status bar changes in time for the message: - message("you are starving to death!", REQUIRE_ACKNOWLEDGMENT); + message("you are starving to death!", REQUIRE_ACKNOWLEDGMENT, 2); } } @@ -852,7 +852,7 @@ void burnItem(item *theItem) { refreshDungeonCell(x, y); } if (playerCanSee(x, y)) { - messageWithColor(buf2, &itemMessageColor, 0); + messageWithColor(buf2, &itemMessageColor, 0, 2); } spawnDungeonFeature(x, y, &(dungeonFeatureCatalog[DF_ITEM_FIRE]), true, false); } @@ -935,7 +935,7 @@ void addXPXPToAlly(short XPXP, creature *monst) { updateVision(true); monsterName(theMonsterName, monst, false); sprintf(buf, "you have developed a telepathic bond with your %s.", theMonsterName); - messageWithColor(buf, &advancementMessageColor, 0); + messageWithColor(buf, &advancementMessageColor, 0, 2); } if (monst->xpxp > 1500 * 20) { rogue.featRecord[FEAT_COMPANION] = true; @@ -980,9 +980,9 @@ void playerFalls() { layer = layerWithFlag(player.xLoc, player.yLoc, T_AUTO_DESCENT); if (layer >= 0) { - message(tileCatalog[pmap[player.xLoc][player.yLoc].layers[layer]].flavorText, REQUIRE_ACKNOWLEDGMENT); + message(tileCatalog[pmap[player.xLoc][player.yLoc].layers[layer]].flavorText, REQUIRE_ACKNOWLEDGMENT, 2); } else if (layer == -1) { - message("You plunge downward!", REQUIRE_ACKNOWLEDGMENT); + message("You plunge downward!", REQUIRE_ACKNOWLEDGMENT, 2); } player.bookkeepingFlags &= ~(MB_IS_FALLING | MB_SEIZED | MB_SEIZING); @@ -994,12 +994,12 @@ void playerFalls() { damage = randClumpedRange(FALL_DAMAGE_MIN, FALL_DAMAGE_MAX, 2); boolean killed = false; if (terrainFlags(player.xLoc, player.yLoc) & T_IS_DEEP_WATER) { - messageWithColor("You fall into deep water, unharmed.", &badMessageColor, 0); + messageWithColor("You fall into deep water, unharmed.", &badMessageColor, 0, 2); } else { if (cellHasTMFlag(player.xLoc, player.yLoc, TM_ALLOWS_SUBMERGING)) { damage /= 2; // falling into liquid (shallow water, bog, etc.) hurts less than hitting hard floor } - messageWithColor("You are injured by the fall.", &badMessageColor, 0); + messageWithColor("You are injured by the fall.", &badMessageColor, 0, 2); if (inflictDamage(NULL, &player, damage, &red, false)) { gameOver("Killed by a fall", true); killed = true; @@ -1009,7 +1009,7 @@ void playerFalls() { rogue.deepestLevel = rogue.depthLevel; } } else { - message("A strange force seizes you as you fall.", 0); + message("A strange force seizes you as you fall.", 0, 2); teleport(&player, -1, -1, true); } createFlare(player.xLoc, player.yLoc, GENERIC_FLASH_LIGHT); @@ -1364,7 +1364,7 @@ void monstersFall() { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s plunges out of sight!", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0); + messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); } if (monst->info.flags & MONST_GETS_TURN_ON_ACTIVATION) { @@ -1772,7 +1772,7 @@ void processIncrementalAutoID() { if (theItem->charges <= 0) { itemName(theItem, theItemName, false, false, NULL); sprintf(buf, "you are now familiar enough with your %s to identify it.", theItemName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 2); if (theItem->category & ARMOR) { // Don't necessarily reveal the armor's runic specifically, just that it has one. @@ -1784,7 +1784,7 @@ void processIncrementalAutoID() { itemName(theItem, theItemName, true, true, NULL); sprintf(buf, "%s %s.", (theItem->quantity > 1 ? "they are" : "it is"), theItemName); - messageWithColor(buf, &itemMessageColor, 0); + messageWithColor(buf, &itemMessageColor, 0, 2); } } } @@ -1837,7 +1837,7 @@ void rechargeItemsIncrementally(short multiplier) { if (theItem->charges == 0) { itemName(theItem, theItemName, false, false, NULL); sprintf(buf, "your %s has recharged.", theItemName); - message(buf, 0); + message(buf, 0, 2); } } } @@ -1851,7 +1851,7 @@ void extinguishFireOnCreature(creature *monst) { rogue.minersLight.lightColor = &minersLightColor; refreshDungeonCell(player.xLoc, player.yLoc); updateVision(true); - message("you are no longer on fire.", 0); + message("you are no longer on fire.", 0, 2); } } @@ -1918,17 +1918,17 @@ void monsterEntersLevel(creature *monst, short n) { if (inflictDamage(NULL, monst, randClumpedRange(6, 12, 2), &red, false)) { if (canSeeMonster(monst)) { sprintf(buf, "%s plummets from above and splatters against the ground!", monstName); - messageWithColor(buf, messageColorFromVictim(monst), 0); + messageWithColor(buf, messageColorFromVictim(monst), 0, 2); } } else { if (canSeeMonster(monst)) { sprintf(buf, "%s falls from above and crashes to the ground!", monstName); - message(buf, 0); + message(buf, 0, 2); } } } else if (canSeeMonster(monst)) { sprintf(buf, "%s swoops into the cavern from above.", monstName); - message(buf, 0); + message(buf, 0, 2); } } } @@ -1970,7 +1970,7 @@ void decrementPlayerStatus() { if (player.status[STATUS_TELEPATHIC] > 0 && !--player.status[STATUS_TELEPATHIC]) { updateVision(true); - message("your preternatural mental sensitivity fades.", 0); + message("your preternatural mental sensitivity fades.", 0, 2); } if (player.status[STATUS_DARKNESS] > 0) { @@ -1981,42 +1981,42 @@ void decrementPlayerStatus() { if (player.status[STATUS_HALLUCINATING] > 0 && !--player.status[STATUS_HALLUCINATING]) { displayLevel(); - message("your hallucinations fade.", 0); + message("your hallucinations fade.", 0, 2); } if (player.status[STATUS_LEVITATING] > 0 && !--player.status[STATUS_LEVITATING]) { - message("you are no longer levitating.", 0); + message("you are no longer levitating.", 0, 2); } if (player.status[STATUS_CONFUSED] > 0 && !--player.status[STATUS_CONFUSED]) { - message("you no longer feel confused.", 0); + message("you no longer feel confused.", 0, 2); } if (player.status[STATUS_NAUSEOUS] > 0 && !--player.status[STATUS_NAUSEOUS]) { - message("you feel less nauseous.", 0); + message("you feel less nauseous.", 0, 2); } if (player.status[STATUS_PARALYZED] > 0 && !--player.status[STATUS_PARALYZED]) { - message("you can move again.", 0); + message("you can move again.", 0, 2); } if (player.status[STATUS_HASTED] > 0 && !--player.status[STATUS_HASTED]) { player.movementSpeed = player.info.movementSpeed; player.attackSpeed = player.info.attackSpeed; synchronizePlayerTimeState(); - message("your supernatural speed fades.", 0); + message("your supernatural speed fades.", 0, 2); } if (player.status[STATUS_SLOWED] > 0 && !--player.status[STATUS_SLOWED]) { player.movementSpeed = player.info.movementSpeed; player.attackSpeed = player.info.attackSpeed; synchronizePlayerTimeState(); - message("your normal speed resumes.", 0); + message("your normal speed resumes.", 0, 2); } if (player.status[STATUS_WEAKENED] > 0 && !--player.status[STATUS_WEAKENED]) { player.weaknessAmount = 0; - message("strength returns to your muscles as the weakening toxin wears off.", 0); + message("strength returns to your muscles as the weakening toxin wears off.", 0, 2); updateEncumbrance(); } @@ -2026,7 +2026,7 @@ void decrementPlayerStatus() { } if (player.status[STATUS_IMMUNE_TO_FIRE] > 0 && !--player.status[STATUS_IMMUNE_TO_FIRE]) { - message("you no longer feel immune to fire.", 0); + message("you no longer feel immune to fire.", 0, 2); } if (player.status[STATUS_STUCK] && !cellHasTerrainFlag(player.xLoc, player.yLoc, T_ENTANGLES)) { @@ -2053,7 +2053,7 @@ void decrementPlayerStatus() { } if (player.status[STATUS_INVISIBLE] > 0 && !--player.status[STATUS_INVISIBLE]) { - message("you are no longer invisible.", 0); + message("you are no longer invisible.", 0, 2); } if (rogue.monsterSpawnFuse <= 0) { @@ -2159,7 +2159,7 @@ void manualSearch() { } else { // Do a final, larger-radius search on the fifth search in a row searchStrength = 160; - message("you finish your detailed search of the area.", 0); + message("you finish your detailed search of the area.", 0, 2); player.status[STATUS_SEARCHING] = 0; } @@ -2482,7 +2482,7 @@ void playerTurnEnded() { buf2); if (rogue.cautiousMode) { strcat(buf, "."); - message(buf, REQUIRE_ACKNOWLEDGMENT); + message(buf, REQUIRE_ACKNOWLEDGMENT, 2); } else { combatMessage(buf, 0); } @@ -2507,7 +2507,7 @@ void playerTurnEnded() { rogue.weapon->flags |= ITEM_RUNIC_HINTED; itemName(rogue.weapon, buf2, false, false, NULL); sprintf(buf, "the runes on your %s gleam balefully.", buf2); - messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT); + messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 2); } if (rogue.armor && rogue.armor->flags & ITEM_RUNIC && rogue.armor->enchant2 == A_IMMUNITY @@ -2517,7 +2517,7 @@ void playerTurnEnded() { rogue.armor->flags |= ITEM_RUNIC_HINTED; itemName(rogue.armor, buf2, false, false, NULL); sprintf(buf, "the runes on your %s glow protectively.", buf2); - messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT); + messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 2); } } } @@ -2585,11 +2585,11 @@ void playerTurnEnded() { turnsToShore = player.status[STATUS_LEVITATING] * 100 / player.movementSpeed; } if (turnsRequiredToShore == turnsToShore || turnsRequiredToShore + 1 == turnsToShore) { - message("better head back to solid ground!", REQUIRE_ACKNOWLEDGMENT); + message("better head back to solid ground!", REQUIRE_ACKNOWLEDGMENT, 2); rogue.receivedLevitationWarning = true; } else if (turnsRequiredToShore > turnsToShore && turnsRequiredToShore < 10000) { - message("you're past the point of no return!", REQUIRE_ACKNOWLEDGMENT); + message("you're past the point of no return!", REQUIRE_ACKNOWLEDGMENT, 2); rogue.receivedLevitationWarning = true; } } diff --git a/src/platform/platformdependent.c b/src/platform/platformdependent.c index f8184b3e..b36243fb 100644 --- a/src/platform/platformdependent.c +++ b/src/platform/platformdependent.c @@ -267,9 +267,9 @@ enum graphicsModes setGraphicsMode(enum graphicsModes mode) { } } -void playSpeech(char *text, boolean interruptable, boolean interruptPrevious) { +void playSpeech(char *text, short priority) { if (currentConsole.playSpeech) { - currentConsole.playSpeech(text, interruptable, interruptPrevious); + currentConsole.playSpeech(text, priority); } } diff --git a/src/platform/sdl2-platform.c b/src/platform/sdl2-platform.c index 48082523..d60bcf6d 100644 --- a/src/platform/sdl2-platform.c +++ b/src/platform/sdl2-platform.c @@ -152,11 +152,12 @@ static boolean audioInit() { static void _playSpeech( char *text, - boolean interruptable, - boolean interruptPrevious + short priority ) { - if (interruptPrevious && lastSpeech.interruptable) { + if (priority >= lastSpeech.priority) { espeak_Cancel(); + } else { + espeak_Synchronize(); } // remove any escape codes from the text int i, j; @@ -185,6 +186,7 @@ static void _playSpeech( NULL ); // TODO: mark interruptable messages with unique_identifier + lastSpeech.priority = priority; } From 748f54ec8255b1583c85cdcdde9bb397a17a13d7 Mon Sep 17 00:00:00 2001 From: anderoonies Date: Sun, 8 Aug 2021 17:19:34 -0400 Subject: [PATCH 7/7] enum for speech priority and flags for blocking speech --- Makefile | 3 +- config.mk | 4 +- src/brogue/Architect.c | 2 +- src/brogue/Combat.c | 28 ++-- src/brogue/IO.c | 44 +++--- src/brogue/Items.c | 256 +++++++++++++++---------------- src/brogue/MainMenu.c | 2 +- src/brogue/Monsters.c | 20 +-- src/brogue/Movement.c | 54 +++---- src/brogue/Recordings.c | 36 ++--- src/brogue/Rogue.h | 15 +- src/brogue/RogueMain.c | 34 ++-- src/brogue/Time.c | 114 +++++++------- src/platform/platform.h | 1 + src/platform/platformdependent.c | 10 +- src/platform/sdl2-platform.c | 54 +++++-- 16 files changed, 359 insertions(+), 318 deletions(-) diff --git a/Makefile b/Makefile index 2fb718c8..351c33a9 100644 --- a/Makefile +++ b/Makefile @@ -24,12 +24,11 @@ ifeq ($(GRAPHICS),YES) sources += $(addprefix src/platform/,sdl2-platform.c tiles.c) cflags += $(shell $(SDL_CONFIG) --cflags) cppflags += -DBROGUE_SDL - libs += $(shell $(SDL_CONFIG) --libs) -lSDL2_image + libs += $(shell $(SDL_CONFIG) --libs) -lSDL2_image -lespeak-ng endif ifeq ($(SPEECH),YES) cppflags += -DBROGUE_SPEECH - libs += -lespeak-ng endif ifeq ($(WEBBROGUE),YES) diff --git a/config.mk b/config.mk index 871b0666..2e662781 100644 --- a/config.mk +++ b/config.mk @@ -13,10 +13,10 @@ SDL_CONFIG := sdl2-config WEBBROGUE := NO # Add TTS. Requires GRAPHICS for now, just to add SDL. -SPEECH := YES +SPEECH := NO # Enable debugging mode. See top of Rogue.h for features -DEBUG := NO +DEBUG := YES # Declare this is a release build RELEASE := NO diff --git a/src/brogue/Architect.c b/src/brogue/Architect.c index 121be33b..056b5cd7 100644 --- a/src/brogue/Architect.c +++ b/src/brogue/Architect.c @@ -3338,7 +3338,7 @@ boolean spawnDungeonFeature(short x, short y, dungeonFeature *feat, boolean refr if (feat->description[0] && !feat->messageDisplayed && playerCanSee(x, y)) { feat->messageDisplayed = true; - message(feat->description, 0, 0); + message(feat->description, 0); } zeroOutGrid(blockingMap); diff --git a/src/brogue/Combat.c b/src/brogue/Combat.c index c1e4871c..c3432fc3 100644 --- a/src/brogue/Combat.c +++ b/src/brogue/Combat.c @@ -255,7 +255,7 @@ void splitMonster(creature *monst, short x, short y) { if (canDirectlySeeMonster(monst)) { sprintf(buf, "%s splits in two!", monstName); - message(buf, 0, 2); + message(buf, TWO_SPEECH); } return; @@ -393,7 +393,7 @@ void specialHit(creature *attacker, creature *defender, short damage) { equipItem(rogue.armor, true, NULL); itemName(rogue.armor, buf2, false, false, NULL); sprintf(buf, "your %s weakens!", buf2); - messageWithColor(buf, &itemMessageColor, 0, 2); + messageWithColor(buf, &itemMessageColor, TWO_SPEECH); checkForDisenchantment(rogue.armor); } if (attacker->info.abilityFlags & MA_HIT_HALLUCINATE) { @@ -461,7 +461,7 @@ void specialHit(creature *attacker, creature *defender, short damage) { monsterName(buf2, attacker, true); itemName(theItem, buf3, false, true, NULL); sprintf(buf, "%s stole %s!", buf2, buf3); - messageWithColor(buf, &badMessageColor, 0, 2); + messageWithColor(buf, &badMessageColor, TWO_SPEECH); } } } @@ -718,7 +718,7 @@ void magicWeaponHit(creature *defender, item *theItem, boolean backstabbed) { } updateVision(true); - message(buf, 0, 2); + message(buf, TWO_SPEECH); autoID = true; break; case W_SLOWING: @@ -946,7 +946,7 @@ void applyArmorRunicEffect(char returnString[DCOLS], creature *attacker, short * case A_IMMOLATION: if (rand_percent(10)) { sprintf(returnString, "flames suddenly explode out of your %s!", armorName); - message(returnString, runicKnown ? 0 : REQUIRE_ACKNOWLEDGMENT, 2); + message(returnString, runicKnown ? 0 : REQUIRE_ACKNOWLEDGMENT | TWO_SPEECH); returnString[0] = '\0'; spawnDungeonFeature(player.xLoc, player.yLoc, &(dungeonFeatureCatalog[DF_ARMOR_IMMOLATION]), true, false); runicDiscovered = true; @@ -969,10 +969,10 @@ void decrementWeaponAutoIDTimer() { rogue.weapon->flags |= ITEM_IDENTIFIED; updateIdentifiableItems(); - messageWithColor("you are now familiar enough with your weapon to identify it.", &itemMessageColor, 0, 2); + messageWithColor("you are now familiar enough with your weapon to identify it.", &itemMessageColor, TWO_SPEECH); itemName(rogue.weapon, buf2, true, true, NULL); sprintf(buf, "%s %s.", (rogue.weapon->quantity > 1 ? "they are" : "it is"), buf2); - messageWithColor(buf, &itemMessageColor, 0, 2); + messageWithColor(buf, &itemMessageColor, TWO_SPEECH); } } @@ -1061,7 +1061,7 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) { defender->bookkeepingFlags |= MB_SEIZED; if (canSeeMonster(attacker) || canSeeMonster(defender)) { sprintf(buf, "%s seizes %s!", attackerName, (defender == &player ? "your legs" : defenderName)); - messageWithColor(buf, &white, 0, 2); + messageWithColor(buf, &white, TWO_SPEECH); } return false; } @@ -1186,7 +1186,7 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) { specialHit(attacker, defender, (attacker->info.abilityFlags & MA_POISONS) ? poisonDamage : damage); } if (armorRunicString[0]) { - message(armorRunicString, 0, 2); + message(armorRunicString, TWO_SPEECH); if (rogue.armor && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_BURDEN) { strengthCheck(rogue.armor, true); } @@ -1221,7 +1221,7 @@ boolean attack(creature *attacker, creature *defender, boolean lungeAttack) { equipItem(rogue.weapon, true, NULL); itemName(rogue.weapon, buf2, false, false, NULL); sprintf(buf, "your %s weakens!", buf2); - messageWithColor(buf, &itemMessageColor, 0, 2); + messageWithColor(buf, &itemMessageColor, TWO_SPEECH); checkForDisenchantment(rogue.weapon); } @@ -1311,12 +1311,12 @@ void displayCombatText() { for (end = start; *end != '\0'; end++) { if (*end == '\n') { *end = '\0'; - message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0), 2); + message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0) | TWO_SPEECH | SPEECH_BLOCKS); start = end + 1; } } - message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0), 2); + message(start, FOLDABLE | (rogue.cautiousMode ? REQUIRE_ACKNOWLEDGMENT : 0) | TWO_SPEECH | SPEECH_BLOCKS); rogue.cautiousMode = false; } @@ -1647,7 +1647,7 @@ void killCreature(creature *decedent, boolean administrativeDeath) { monsterName(monstName, decedent, true); snprintf(buf, DCOLS * 3, "%s %s", monstName, monsterText[decedent->info.monsterID].DFMessage); resolvePronounEscapes(buf, decedent); - message(buf, 0, 2); + message(buf, TWO_SPEECH); } } @@ -1661,7 +1661,7 @@ void killCreature(creature *decedent, boolean administrativeDeath) { && !(decedent->bookkeepingFlags & MB_BOUND_TO_LEADER) && !decedent->carriedMonster) { - messageWithColor("you feel a sense of loss.", &badMessageColor, 0, 2); + messageWithColor("you feel a sense of loss.", &badMessageColor, TWO_SPEECH); } x = decedent->xLoc; y = decedent->yLoc; diff --git a/src/brogue/IO.c b/src/brogue/IO.c index 59ec171c..b982b536 100644 --- a/src/brogue/IO.c +++ b/src/brogue/IO.c @@ -2381,12 +2381,13 @@ void exploreKey(const boolean controlKey) { } else { x = finalX = player.xLoc + nbDirs[dir][0]; y = finalY = player.yLoc + nbDirs[dir][1]; + hideCursor(); } if (tooDark) { - message("It's too dark to explore!", 0, 2); + message("It's too dark to explore!", 0); } else if (x == player.xLoc && y == player.yLoc) { - message("I see no path for further exploration.", 0, 2); + message("I see no path for further exploration.", 0); } else if (proposeOrConfirmLocation(finalX, finalY, "I see no path for further exploration.")) { explore(controlKey ? 1 : 20); // Do the exploring until interrupted. hideCursor(); @@ -2443,7 +2444,7 @@ void nextBrogueEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsD if (returnEvent->eventType == EVENT_ERROR) { rogue.playbackPaused = rogue.playbackMode; // pause if replaying - message("Event error!", REQUIRE_ACKNOWLEDGMENT, 3); + message("Event error!", REQUIRE_ACKNOWLEDGMENT | THREE_SPEECH); } } @@ -2598,10 +2599,10 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe refreshSideBar(-1, -1, false); if (rogue.trueColorMode) { messageWithColor(KEYBOARD_LABELS ? "Color effects disabled. Press '\\' again to enable." : "Color effects disabled.", - &teal, 0, 0); + &teal, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Color effects enabled. Press '\\' again to disable." : "Color effects enabled.", - &teal, 0, 0); + &teal, 0); } break; case AGGRO_DISPLAY_KEY: @@ -2610,10 +2611,10 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe refreshSideBar(-1, -1, false); if (rogue.displayAggroRangeMode) { messageWithColor(KEYBOARD_LABELS ? "Stealth range displayed. Press ']' again to hide." : "Stealth range displayed.", - &teal, 0, 0); + &teal, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Stealth range hidden. Press ']' again to display." : "Stealth range hidden.", - &teal, 0, 0); + &teal, 0); } break; case CALL_KEY: @@ -2649,7 +2650,7 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe rogue.nextGame = NG_VIEW_RECORDING; rogue.gameHasEnded = true; } else { - message("File not found.", 0, 0); + message("File not found.", 0); } } break; @@ -2665,7 +2666,7 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe rogue.nextGame = NG_OPEN_GAME; rogue.gameHasEnded = true; } else { - message("File not found.", 0, 0); + message("File not found.", 0); } } break; @@ -2690,6 +2691,9 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe gameOver("Quit", true); } break; + case TTS_TOGGLE_KEY: + toggleTTS(); + break; case GRAPHICS_KEY: if (hasGraphics) { graphicsMode = setGraphicsMode((graphicsMode + 1) % 3); @@ -2697,17 +2701,17 @@ void executeKeystroke(signed long keystroke, boolean controlKey, boolean shiftKe case TEXT_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to text mode. Press 'G' again to enable tiles." - : "Switched to text mode.", &teal, 0, 1); + : "Switched to text mode.", &teal, 0); break; case TILES_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to graphical tiles. Press 'G' again to enable hybrid mode." - : "Switched to graphical tiles.", &teal, 0, 1); + : "Switched to graphical tiles.", &teal, 0); break; case HYBRID_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to hybrid mode. Press 'G' again to disable tiles." - : "Switched to hybrid mode.", &teal, 0, 1); + : "Switched to hybrid mode.", &teal, 0); break; } } @@ -2974,8 +2978,8 @@ boolean confirm(char *prompt, boolean alsoDuringPlayback) { return true; // oh yes he did } - playSpeech(prompt, 3); - playSpeech("Yes... No", 3); + playSpeech(prompt, THREE_SPEECH | SPEECH_BLOCKS); + playSpeech("Yes... No", THREE_SPEECH); encodeMessageColor(whiteColorEscape, 0, &white); encodeMessageColor(yellowColorEscape, 0, KEYBOARD_LABELS ? &yellow : &white); @@ -3441,17 +3445,17 @@ void temporaryMessage(const char *msg, enum messageFlags flags) { } restoreRNG; - playSpeech(msg, 1); + playSpeech(msg, ONE_SPEECH); } -void messageWithColor(char *msg, color *theColor, enum messageFlags flags, short speechPriority) { +void messageWithColor(char *msg, color *theColor, enum messageFlags flags) { char buf[COLS*2] = ""; short i; i=0; i = encodeMessageColor(buf, i, theColor); strcpy(&(buf[i]), msg); - message(buf, flags, speechPriority); + message(buf, flags); } void flavorMessage(char *msg) { @@ -3479,7 +3483,7 @@ void flavorMessage(char *msg) { // arrived on the same turn, they may collapse. Alternately, they may collapse // if the older message is the latest one in the archive and the new one is not // semi-colon foldable (such as a combat message.) -void message(const char *msg, enum messageFlags flags, short speechPriority) { +void message(const char *msg, enum messageFlags flags) { short i; archivedMessage *archiveEntry; boolean newMessage; @@ -3549,7 +3553,7 @@ void message(const char *msg, enum messageFlags flags, short speechPriority) { restoreRNG; - playSpeech(msg, speechPriority); + playSpeech(msg, 0); } // Only used for the "you die..." message, to enable posthumous inventory viewing. @@ -4478,7 +4482,7 @@ void displayGrid(short **map) { void printSeed() { char buf[COLS]; snprintf(buf, COLS, "Dungeon seed #%llu; turn #%lu; version %s", (unsigned long long)rogue.seed, rogue.playerTurnNumber, BROGUE_VERSION_STRING); - message(buf, 0, 0); + message(buf, 0); } void printProgressBar(short x, short y, const char barLabel[COLS], long amtFilled, long amtMax, color *fillColor, boolean dim) { diff --git a/src/brogue/Items.c b/src/brogue/Items.c index c13f6697..00862082 100644 --- a/src/brogue/Items.c +++ b/src/brogue/Items.c @@ -331,7 +331,7 @@ item *makeItemInto(item *theItem, unsigned long itemCategory, short itemKind) { break; default: theEntry = NULL; - message("something has gone terribly wrong!", REQUIRE_ACKNOWLEDGMENT, 3); + message("something has gone terribly wrong!", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); break; } if (theItem @@ -389,7 +389,7 @@ item *placeItem(item *theItem, short x, short y) { } itemName(theItem, theItemName, false, false, NULL); sprintf(buf, "a pressure plate clicks underneath the %s!", theItemName); - message(buf, REQUIRE_ACKNOWLEDGMENT, 3); + message(buf, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } for (layer = 0; layer < NUMBER_TERRAIN_LAYERS; layer++) { if (tileCatalog[pmap[x][y].layers[layer]].flags & T_IS_DF_TRAP) { @@ -755,7 +755,7 @@ void pickUpItemAt(short x, short y) { theItem = itemAtLoc(x, y); if (!theItem) { - message("Error: Expected item; item not found.", REQUIRE_ACKNOWLEDGMENT, 3); + message("Error: Expected item; item not found.", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); return; } @@ -785,14 +785,14 @@ void pickUpItemAt(short x, short y) { rogue.gold += theItem->quantity; rogue.featRecord[FEAT_TONE] = false; sprintf(buf, "you found %i pieces of gold.", theItem->quantity); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); deleteItem(theItem); removeItemFrom(x, y); // triggers tiles with T_PROMOTES_ON_ITEM_PICKUP return; } if ((theItem->category & AMULET) && numberOfMatchingPackItems(AMULET, 0, 0, false)) { - message("you already have the Amulet of Yendor.", 0, 3); + message("you already have the Amulet of Yendor.", 0); deleteItem(theItem); return; } @@ -802,7 +802,7 @@ void pickUpItemAt(short x, short y) { itemName(theItem, buf2, true, true, NULL); // include suffix, article sprintf(buf, "you now have %s (%c).", buf2, theItem->inventoryLetter); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); removeItemFrom(x, y); // triggers tiles with T_PROMOTES_ON_ITEM_PICKUP @@ -829,7 +829,7 @@ void pickUpItemAt(short x, short y) { theItem->flags |= ITEM_PLAYER_AVOIDS; // explore shouldn't try to pick it up more than once. itemName(theItem, buf2, false, true, NULL); // include article sprintf(buf, "Your pack is too full to pick up %s.", buf2); - message(buf, 0, 3); + message(buf, 0); } } @@ -972,7 +972,7 @@ void checkForDisenchantment(item *theItem) { identify(theItem); itemName(theItem, buf2, false, false, NULL); sprintf(buf, "the runes fade from your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } } if (theItem->flags & ITEM_CURSED @@ -1012,7 +1012,7 @@ void swapItemToEnchantLevel(item *theItem, short newEnchant, boolean enchantment refreshDungeonCell(x, y); } if (playerCanSee(x, y)) { - messageWithColor(buf2, &itemMessageColor, 0, 3); + messageWithColor(buf2, &itemMessageColor, 0); } } else { if ((theItem->category & STAFF) @@ -1117,7 +1117,7 @@ void updateFloorItems() { if (playerCanSeeOrSense(x, y)) { itemName(theItem, buf, false, false, NULL); sprintf(buf2, "The %s plunge%s out of sight!", buf, (theItem->quantity > 1 ? "" : "s")); - messageWithColor(buf2, &itemMessageColor, 0, 3); + messageWithColor(buf2, &itemMessageColor, 0); } if (playerCanSee(x, y)) { discover(x, y); @@ -1210,7 +1210,7 @@ boolean inscribeItem(item *theItem) { confirmMessages(); itemName(theItem, nameOfItem, true, true, NULL); sprintf(buf, "%s %s.", (theItem->quantity > 1 ? "they're" : "it's"), nameOfItem); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); return true; } else { confirmMessages(); @@ -1272,7 +1272,7 @@ void call(item *theItem) { recordKeystroke(RETURN_KEY, false, false); } } else { - message("you already know what that is.", 0, 3); + message("you already know what that is.", 0); } return; } @@ -1317,10 +1317,10 @@ void call(item *theItem) { } confirmMessages(); itemName(theItem, buf, false, true, NULL); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } } else { - message("you already know what that is.", 0, 3); + message("you already know what that is.", 0); } } @@ -2724,7 +2724,7 @@ char displayInventory(unsigned short categoryMask, if (packItems->nextItem == NULL) { confirmMessages(); - message("Your pack is empty!", 0, 3); + message("Your pack is empty!", 0); restoreRNG; return 0; } @@ -2851,7 +2851,7 @@ char displayInventory(unsigned short categoryMask, itemCount = itemNumber; if (!itemNumber) { confirmMessages(); - message("Nothing of that type!", 0, 3); + message("Nothing of that type!", 0); restoreRNG; return 0; } @@ -2958,7 +2958,7 @@ char displayInventory(unsigned short categoryMask, overlayDisplayBuffer(dbuf, NULL); - playSpeech(buttons[highlightItemLine].text, 3); + playSpeech(buttons[highlightItemLine].text, THREE_SPEECH); //buttons[highlightItemLine].buttonColor = interfaceBoxColor; drawButton(&(buttons[highlightItemLine]), BUTTON_PRESSED, NULL); @@ -3045,7 +3045,7 @@ short numberOfMatchingPackItems(unsigned short categoryMask, if (packItems->nextItem == NULL) { if (displayErrors) { confirmMessages(); - message("Your pack is empty!", 0, 3); + message("Your pack is empty!", 0); } return 0; } @@ -3063,7 +3063,7 @@ short numberOfMatchingPackItems(unsigned short categoryMask, if (matchingItemCount == 0) { if (displayErrors) { confirmMessages(); - message("You have nothing suitable.", 0, 3); + message("You have nothing suitable.", 0); } return 0; } @@ -3111,7 +3111,7 @@ void strengthCheck(item *theItem, boolean noisy) { strcpy(buf1, ""); itemName(theItem, buf1, false, false, NULL); sprintf(buf2, "You can barely lift the %s; %i more strength would be ideal.", buf1, strengthDeficiency); - message(buf2, 0, 3); + message(buf2, 0); } if (theItem->category & ARMOR && theItem->strengthRequired > rogue.strength - player.weaknessAmount) { @@ -3120,7 +3120,7 @@ void strengthCheck(item *theItem, boolean noisy) { itemName(theItem, buf1, false, false, NULL); sprintf(buf2, "You stagger under the weight of the %s; %i more strength would be ideal.", buf1, strengthDeficiency); - message(buf2, 0, 3); + message(buf2, 0); } } } @@ -3151,7 +3151,7 @@ void equip(item *theItem) { if (theItem->category & RING) { if (theItem->flags & ITEM_EQUIPPED) { confirmMessages(); - message("you are already wearing that ring.", 0, 3); + message("you are already wearing that ring.", 0); return; } else if (rogue.ringLeft && rogue.ringRight) { confirmMessages(); @@ -3159,7 +3159,7 @@ void equip(item *theItem) { "You are already wearing two rings; remove which first?", true); if (!theItem2 || theItem2->category != RING || !(theItem2->flags & ITEM_EQUIPPED)) { if (theItem2) { // No message if canceled or did an inventory action instead. - message("Invalid entry.", 0, 3); + message("Invalid entry.", 0); } return; } else { @@ -3170,7 +3170,7 @@ void equip(item *theItem) { if (theItem->flags & ITEM_EQUIPPED) { confirmMessages(); - message("already equipped.", 0, 3); + message("already equipped.", 0); return; } @@ -3193,7 +3193,7 @@ void equip(item *theItem) { playerTurnEnded(); } else { confirmMessages(); - message("You can't equip that.", 0, 3); + message("You can't equip that.", 0); } } @@ -3303,7 +3303,7 @@ void aggravateMonsters(short distance, short x, short y, const color *flashColor discoverCell(x, y); colorFlash(flashColor, 0, (DISCOVERED | MAGIC_MAPPED), 10, distance, x, y); if (!playerCanSee(x, y)) { - message("You hear a piercing shriek; something must have triggered a nearby alarm.", 0, 3); + message("You hear a piercing shriek; something must have triggered a nearby alarm.", 0); } } @@ -3745,7 +3745,7 @@ void weaken(creature *monst, short maxDuration) { monst->status[STATUS_WEAKENED] = max(monst->status[STATUS_WEAKENED], maxDuration); monst->maxStatus[STATUS_WEAKENED] = max(monst->maxStatus[STATUS_WEAKENED], maxDuration); if (monst == &player) { - messageWithColor("your muscles weaken as an enervating toxin fills your veins.", &badMessageColor, 0, 3); + messageWithColor("your muscles weaken as an enervating toxin fills your veins.", &badMessageColor, 0); strengthCheck(rogue.weapon, true); strengthCheck(rogue.armor, true); } @@ -3836,7 +3836,7 @@ void slow(creature *monst, short turns) { monst->status[STATUS_HASTED] = 0; if (monst == &player) { updateEncumbrance(); - message("you feel yourself slow down.", 0, 3); + message("you feel yourself slow down.", 0); } else { monst->movementSpeed = monst->info.movementSpeed * 2; monst->attackSpeed = monst->info.attackSpeed * 2; @@ -3850,7 +3850,7 @@ void haste(creature *monst, short turns) { monst->status[STATUS_HASTED] = monst->maxStatus[STATUS_HASTED] = turns; if (monst == &player) { updateEncumbrance(); - message("you feel yourself speed up.", 0, 3); + message("you feel yourself speed up.", 0); } else { monst->movementSpeed = monst->info.movementSpeed / 2; monst->attackSpeed = monst->info.attackSpeed / 2; @@ -3908,9 +3908,9 @@ void makePlayerTelepathic(short duration) { refreshDungeonCell(monst->xLoc, monst->yLoc); } if (!hasNextCreature(iterateCreatures(monsters))) { - message("you can somehow tell that you are alone on this depth at the moment.", 0, 3); + message("you can somehow tell that you are alone on this depth at the moment.", 0); } else { - message("you can somehow feel the presence of other creatures' minds!", 0, 3); + message("you can somehow feel the presence of other creatures' minds!", 0); } } @@ -3963,9 +3963,9 @@ void rechargeItems(unsigned long categories) { strcat(buf, z == 1 ? "charm" : "charms"); } strcat(buf, "."); - message(buf, 0, 3); + message(buf, 0); } else { - message("a surge of energy courses through your pack, but nothing happens.", 0, 3); + message("a surge of energy courses through your pack, but nothing happens.", 0); } } @@ -4003,7 +4003,7 @@ void negationBlast(const char *emitterName, const short distance) { char buf[DCOLS]; sprintf(buf, "%s emits a numbing torrent of anti-magic!", emitterName); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); colorFlash(&pink, 0, IN_FIELD_OF_VIEW, 3 + distance / 5, distance, player.xLoc, player.yLoc); negate(&player); flashMonster(&player, &pink, 100); @@ -4058,7 +4058,7 @@ void discordBlast(const char *emitterName, const short distance) { char buf[DCOLS]; sprintf(buf, "%s emits a wave of unsettling purple radiation!", emitterName); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); colorFlash(&discordColor, 0, IN_FIELD_OF_VIEW, 3 + distance / 5, distance, player.xLoc, player.yLoc); for (creatureIterator it = iterateCreatures(monsters); hasNextCreature(it);) { creature *monst = nextCreature(&it); @@ -4450,7 +4450,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, *autoID = true; } sprintf(buf, "%s is bound to your will!", monstName); - message(buf, 0, 3); + message(buf, 0); if (boltCatalog[BOLT_DOMINATION].backColor) { flashMonster(monst, boltCatalog[BOLT_DOMINATION].backColor, 100); } @@ -4460,7 +4460,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, *autoID = true; } sprintf(buf, "%s resists the bolt of domination.", monstName); - message(buf, 0, 3); + message(buf, 0); } } break; @@ -4510,7 +4510,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, flashMonster(monst, &confusionGasColor, 100); monst->status[STATUS_CONFUSED] = staffEntrancementDuration(theBolt->magnitude * FP_FACTOR); monst->maxStatus[STATUS_CONFUSED] = max(monst->status[STATUS_CONFUSED], monst->maxStatus[STATUS_CONFUSED]); - message("the bolt hits you and you suddenly feel disoriented.", REQUIRE_ACKNOWLEDGMENT, 3); + message("the bolt hits you and you suddenly feel disoriented.", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); if (autoID) { *autoID = true; } @@ -4525,7 +4525,7 @@ boolean updateBolt(bolt *theBolt, creature *caster, short x, short y, *autoID = true; } sprintf(buf, "%s is entranced!", monstName); - message(buf, 0, 3); + message(buf, 0); } } break; @@ -5648,7 +5648,7 @@ void autoIdentify(item *theItem) { sprintf(buf, "(It must %s %s.)", ((theItem->category & (POTION | SCROLL)) ? "have been" : "be"), newName); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } if ((theItem->category & (WEAPON | ARMOR)) @@ -5659,7 +5659,7 @@ void autoIdentify(item *theItem) { theItem->flags |= (ITEM_RUNIC_IDENTIFIED | ITEM_RUNIC_HINTED); itemName(theItem, newName, true, true, NULL); sprintf(buf, "(Your %s must be %s.)", oldName, newName); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } } @@ -5719,23 +5719,23 @@ boolean hitMonsterWithProjectileWeapon(creature *thrower, creature *monst, item theItemName, (monst->info.flags & MONST_INANIMATE) ? "destroyed" : "killed", targetName); - messageWithColor(buf, messageColorFromVictim(monst), 0, 3); + messageWithColor(buf, messageColorFromVictim(monst), 0); } else { sprintf(buf, "the %s hit %s.", theItemName, targetName); if (theItem->flags & ITEM_RUNIC) { magicWeaponHit(monst, theItem, false); } - messageWithColor(buf, messageColorFromVictim(monst), 0, 3); + messageWithColor(buf, messageColorFromVictim(monst), 0); } moralAttack(thrower, monst); if (armorRunicString[0]) { - message(armorRunicString, 0, 3); + message(armorRunicString, 0); } return true; } else { theItem->flags &= ~ITEM_PLAYER_AVOIDS; // Don't avoid thrown weapons that missed. sprintf(buf, "the %s missed %s.", theItemName, targetName); - message(buf, 0, 3); + message(buf, 0); return false; } } @@ -5767,7 +5767,7 @@ void throwItem(item *theItem, creature *thrower, short targetLoc[2], short maxDi monsterName(buf2, thrower, true); itemName(theItem, buf3, false, true, NULL); sprintf(buf, "%s hurls %s.", buf2, buf3); - message(buf, 0, 3); + message(buf, 0); } for (i=0; ikind].flavor, buf2, tileText(x, y)); - message(buf, 0, 3); + message(buf, 0); if (theItem->kind == POTION_HALLUCINATION && (theItem->flags & ITEM_MAGIC_DETECTED)) { autoIdentify(theItem); } @@ -5982,7 +5982,7 @@ void throwCommand(item *theItem, boolean autoThrow) { } if (theItem->flags & ITEM_CURSED) { sprintf(buf, "You cannot unequip your %s; it appears to be cursed.", theName); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); return; } } @@ -6095,19 +6095,19 @@ void relabel(item *theItem) { oldItem->inventoryLetter = theItem->inventoryLetter; itemName(oldItem, theName, true, true, NULL); sprintf(buf, "Relabeled %s as (%c);", theName, oldItem->inventoryLetter); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } theItem->inventoryLetter = newLabel; itemName(theItem, theName, true, true, NULL); sprintf(buf, "%selabeled %s as (%c).", oldItem ? " r" : "R", theName, newLabel); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } else { itemName(theItem, theName, true, true, NULL); sprintf(buf, "%s %s already labeled (%c).", theName, theItem->quantity == 1 ? "is" : "are", theItem->inventoryLetter); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } } } @@ -6120,7 +6120,7 @@ void swapLastEquipment() { if (rogue.swappedIn == NULL || rogue.swappedOut == NULL) { confirmMessages(); - message("You have nothing to swap.", 0, 3); + message("You have nothing to swap.", 0); return; } @@ -6195,7 +6195,7 @@ boolean playerCancelsBlinking(const short originLoc[2], const short targetLoc[2] } } if (possibleDeath && certainDeath) { - message("that would be certain death!", 0, 3); + message("that would be certain death!", 0); return true; } if (possibleDeath @@ -6220,7 +6220,7 @@ boolean useStaffOrWand(item *theItem, boolean *commandsRecorded) { if (theItem->charges <= 0 && (theItem->flags & ITEM_IDENTIFIED)) { itemName(theItem, buf2, false, false, NULL); sprintf(buf, "Your %s has no charges.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); return false; } temporaryMessage("Direction? (, mouse, or ; to confirm)", REFRESH_SIDEBAR); @@ -6299,7 +6299,7 @@ boolean useStaffOrWand(item *theItem, boolean *commandsRecorded) { itemName(theItem, buf2, false, true, NULL); strcat(buf, buf2); strcat(buf, ".)"); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } } } else { @@ -6309,7 +6309,7 @@ boolean useStaffOrWand(item *theItem, boolean *commandsRecorded) { } else { sprintf(buf, "Your %s fizzles; it must be depleted.", buf2); } - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); theItem->flags |= ITEM_MAX_CHARGES_KNOWN; playerTurnEnded(); return false; @@ -6346,7 +6346,7 @@ void useCharm(item *theItem) { switch (theItem->kind) { case CHARM_HEALTH: heal(&player, charmHealing(enchant), false); - message("You feel much healthier.", 0, 3); + message("You feel much healthier.", 0); break; case CHARM_PROTECTION: if (charmProtection(enchant) > player.status[STATUS_SHIELDED]) { @@ -6356,7 +6356,7 @@ void useCharm(item *theItem) { if (boltCatalog[BOLT_SHIELDING].backColor) { flashMonster(&player, boltCatalog[BOLT_SHIELDING].backColor, 100); } - message("A shimmering shield coalesces around you.", 0, 3); + message("A shimmering shield coalesces around you.", 0); break; case CHARM_HASTE: haste(&player, charmEffectDuration(theItem->kind, theItem->enchant1)); @@ -6366,11 +6366,11 @@ void useCharm(item *theItem) { if (player.status[STATUS_BURNING]) { extinguishFireOnCreature(&player); } - message("you no longer fear fire.", 0, 3); + message("you no longer fear fire.", 0); break; case CHARM_INVISIBILITY: imbueInvisibility(&player, charmEffectDuration(theItem->kind, theItem->enchant1)); - message("You shiver as a chill runs up your spine.", 0, 3); + message("You shiver as a chill runs up your spine.", 0); break; case CHARM_TELEPATHY: makePlayerTelepathic(charmEffectDuration(theItem->kind, theItem->enchant1)); @@ -6378,14 +6378,14 @@ void useCharm(item *theItem) { case CHARM_LEVITATION: player.status[STATUS_LEVITATING] = player.maxStatus[STATUS_LEVITATING] = charmEffectDuration(theItem->kind, theItem->enchant1); player.bookkeepingFlags &= ~MB_SEIZED; // break free of holding monsters - message("you float into the air!", 0, 3); + message("you float into the air!", 0); break; case CHARM_SHATTERING: - messageWithColor("your charm emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0, 3); + messageWithColor("your charm emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0); crystalize(charmShattering(enchant)); break; case CHARM_GUARDIAN: - messageWithColor("your charm flashes and the form of a mythical guardian coalesces!", &itemMessageColor, 0, 3); + messageWithColor("your charm flashes and the form of a mythical guardian coalesces!", &itemMessageColor, 0); summonGuardian(theItem); break; case CHARM_TELEPORTATION: @@ -6458,9 +6458,9 @@ void apply(item *theItem, boolean recordCommands) { } player.status[STATUS_NUTRITION] = min(foodTable[theItem->kind].strengthRequired + player.status[STATUS_NUTRITION], STOMACH_SIZE); if (theItem->kind == RATION) { - messageWithColor("That food tasted delicious!", &itemMessageColor, 0, 3); + messageWithColor("That food tasted delicious!", &itemMessageColor, 0); } else { - messageWithColor("My, what a yummy mango!", &itemMessageColor, 0, 3); + messageWithColor("My, what a yummy mango!", &itemMessageColor, 0); } rogue.featRecord[FEAT_ASCETIC] = false; break; @@ -6499,7 +6499,7 @@ void apply(item *theItem, boolean recordCommands) { if (theItem->charges > 0) { itemName(theItem, buf2, false, false, NULL); sprintf(buf, "Your %s hasn't finished recharging.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); return; } if (!commandsRecorded) { @@ -6512,7 +6512,7 @@ void apply(item *theItem, boolean recordCommands) { default: itemName(theItem, buf2, false, true, NULL); sprintf(buf, "you can't apply %s.", buf2); - message(buf, 0, 3); + message(buf, 0); return; } @@ -6706,9 +6706,9 @@ void readScroll(item *theItem) { case SCROLL_IDENTIFY: identify(theItem); updateIdentifiableItems(); - messageWithColor("this is a scroll of identify.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 3); + messageWithColor("this is a scroll of identify.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); if (numberOfMatchingPackItems(ALL_ITEMS, ITEM_CAN_BE_IDENTIFIED, 0, false) == 0) { - message("everything in your pack is already identified.", 0, 3); + message("everything in your pack is already identified.", 0); break; } do { @@ -6722,7 +6722,7 @@ void readScroll(item *theItem) { confirmMessages(); itemName(theItem, buf2, true, true, NULL); sprintf(buf, "you already know %s %s.", (theItem->quantity > 1 ? "they're" : "it's"), buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } } while (theItem == NULL || !(theItem->flags & ITEM_CAN_BE_IDENTIFIED)); recordKeystroke(theItem->inventoryLetter, false, false); @@ -6730,7 +6730,7 @@ void readScroll(item *theItem) { identify(theItem); itemName(theItem, buf, true, true, NULL); sprintf(buf2, "%s %s.", (theItem->quantity == 1 ? "this is" : "these are"), buf); - messageWithColor(buf2, &itemMessageColor, 0, 3); + messageWithColor(buf2, &itemMessageColor, 0); break; case SCROLL_TELEPORT: teleport(&player, -1, -1, true); @@ -6743,17 +6743,17 @@ void readScroll(item *theItem) { } } if (hadEffect) { - message("your pack glows with a cleansing light, and a malevolent energy disperses.", 0, 3); + message("your pack glows with a cleansing light, and a malevolent energy disperses.", 0); } else { - message("your pack glows with a cleansing light, but nothing happens.", 0, 3); + message("your pack glows with a cleansing light, but nothing happens.", 0); } break; case SCROLL_ENCHANTING: identify(theItem); - messageWithColor("this is a scroll of enchanting.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 3); + messageWithColor("this is a scroll of enchanting.", &itemMessageColor, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); if (!numberOfMatchingPackItems((WEAPON | ARMOR | RING | STAFF | WAND | CHARM), 0, 0, false)) { confirmMessages(); - message("you have nothing that can be enchanted.", 0, 3); + message("you have nothing that can be enchanted.", 0); break; } do { @@ -6762,7 +6762,7 @@ void readScroll(item *theItem) { false); confirmMessages(); if (theItem == NULL || !(theItem->category & (WEAPON | ARMOR | RING | STAFF | WAND | CHARM))) { - message("Can't enchant that.", REQUIRE_ACKNOWLEDGMENT, 3); + message("Can't enchant that.", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } if (rogue.gameHasEnded) { return; @@ -6820,10 +6820,10 @@ void readScroll(item *theItem) { } itemName(theItem, buf, false, false, NULL); sprintf(buf2, "your %s gleam%s briefly in the darkness.", buf, (theItem->quantity == 1 ? "s" : "")); - messageWithColor(buf2, &itemMessageColor, 0, 3); + messageWithColor(buf2, &itemMessageColor, 0); if (theItem->flags & ITEM_CURSED) { sprintf(buf2, "a malevolent force leaves your %s.", buf); - messageWithColor(buf2, &itemMessageColor, 0, 3); + messageWithColor(buf2, &itemMessageColor, 0); theItem->flags &= ~ITEM_CURSED; } createFlare(player.xLoc, player.yLoc, SCROLL_ENCHANTMENT_LIGHT); @@ -6837,14 +6837,14 @@ void readScroll(item *theItem) { tempItem->flags |= ITEM_PROTECTED; itemName(tempItem, buf2, false, false, NULL); sprintf(buf, "a protective golden light covers your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); if (tempItem->flags & ITEM_CURSED) { sprintf(buf, "a malevolent force leaves your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); tempItem->flags &= ~ITEM_CURSED; } } else { - message("a protective golden light surrounds you, but it quickly disperses.", 0, 3); + message("a protective golden light surrounds you, but it quickly disperses.", 0); } createFlare(player.xLoc, player.yLoc, SCROLL_PROTECTION_LIGHT); break; @@ -6854,27 +6854,27 @@ void readScroll(item *theItem) { tempItem->flags |= ITEM_PROTECTED; itemName(tempItem, buf2, false, false, NULL); sprintf(buf, "a protective golden light covers your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); if (tempItem->flags & ITEM_CURSED) { sprintf(buf, "a malevolent force leaves your %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); tempItem->flags &= ~ITEM_CURSED; } if (rogue.weapon->quiverNumber) { rogue.weapon->quiverNumber = rand_range(1, 60000); } } else { - message("a protective golden light covers your empty hands, but it quickly disperses.", 0, 3); + message("a protective golden light covers your empty hands, but it quickly disperses.", 0); } createFlare(player.xLoc, player.yLoc, SCROLL_PROTECTION_LIGHT); break; case SCROLL_SANCTUARY: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_SACRED_GLYPHS], true, false); - messageWithColor("sprays of color arc to the ground, forming glyphs where they alight.", &itemMessageColor, 0, 3); + messageWithColor("sprays of color arc to the ground, forming glyphs where they alight.", &itemMessageColor, 0); break; case SCROLL_MAGIC_MAPPING: confirmMessages(); - messageWithColor("this scroll has a map on it!", &itemMessageColor, 0, 3); + messageWithColor("this scroll has a map on it!", &itemMessageColor, 0); for (i=0; i 1) { - message("the fabric of space ripples, and monsters appear!", 0, 3); + message("the fabric of space ripples, and monsters appear!", 0); } else if (numberOfMonsters == 1) { - message("the fabric of space ripples, and a monster appears!", 0, 3); + message("the fabric of space ripples, and a monster appears!", 0); } else { - message("the fabric of space boils violently around you, but nothing happens.", 0, 3); + message("the fabric of space boils violently around you, but nothing happens.", 0); } break; case SCROLL_NEGATION: negationBlast("the scroll", DCOLS); break; case SCROLL_SHATTERING: - messageWithColor("the scroll emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0, 3); + messageWithColor("the scroll emits a wave of turquoise light that pierces the nearby walls!", &itemMessageColor, 0); crystalize(9); break; case SCROLL_DISCORD: @@ -6966,15 +6966,15 @@ void drinkPotion(item *theItem) { player.info.maxHP += 10; heal(&player, 100, true); updatePlayerRegenerationDelay(); - messageWithColor(buf, &advancementMessageColor, 0, 3); + messageWithColor(buf, &advancementMessageColor, 0); break; case POTION_HALLUCINATION: player.status[STATUS_HALLUCINATING] = player.maxStatus[STATUS_HALLUCINATING] = 300; - message("colors are everywhere! The walls are singing!", 0, 3); + message("colors are everywhere! The walls are singing!", 0); break; case POTION_INCINERATION: //colorFlash(&darkOrange, 0, IN_FIELD_OF_VIEW, 4, 4, player.xLoc, player.yLoc); - message("as you uncork the flask, it explodes in flame!", 0, 3); + message("as you uncork the flask, it explodes in flame!", 0); spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_INCINERATION_POTION], true, false); exposeCreatureToFire(&player); break; @@ -6983,11 +6983,11 @@ void drinkPotion(item *theItem) { player.maxStatus[STATUS_DARKNESS] = max(400, player.maxStatus[STATUS_DARKNESS]); updateMinersLightRadius(); updateVision(true); - message("your vision flickers as a cloak of darkness settles around you!", 0, 3); + message("your vision flickers as a cloak of darkness settles around you!", 0); break; case POTION_DESCENT: colorFlash(&darkBlue, 0, IN_FIELD_OF_VIEW, 3, 3, player.xLoc, player.yLoc); - message("vapor pours out of the flask and causes the floor to disappear!", 0, 3); + message("vapor pours out of the flask and causes the floor to disappear!", 0); spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_HOLE_POTION], true, false); if (!player.status[STATUS_LEVITATING]) { player.bookkeepingFlags |= MB_IS_FALLING; @@ -6999,16 +6999,16 @@ void drinkPotion(item *theItem) { player.status[STATUS_WEAKENED] = 1; } updateEncumbrance(); - messageWithColor("newfound strength surges through your body.", &advancementMessageColor, 0, 3); + messageWithColor("newfound strength surges through your body.", &advancementMessageColor, 0); createFlare(player.xLoc, player.yLoc, POTION_STRENGTH_LIGHT); break; case POTION_POISON: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_POISON_GAS_CLOUD_POTION], true, false); - message("caustic gas billows out of the open flask!", 0, 3); + message("caustic gas billows out of the open flask!", 0); break; case POTION_PARALYSIS: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_PARALYSIS_GAS_CLOUD_POTION], true, false); - message("your muscles stiffen as a cloud of pink gas bursts from the open flask!", 0, 3); + message("your muscles stiffen as a cloud of pink gas bursts from the open flask!", 0); break; case POTION_TELEPATHY: makePlayerTelepathic(300); @@ -7016,14 +7016,14 @@ void drinkPotion(item *theItem) { case POTION_LEVITATION: player.status[STATUS_LEVITATING] = player.maxStatus[STATUS_LEVITATING] = 100; player.bookkeepingFlags &= ~MB_SEIZED; // break free of holding monsters - message("you float into the air!", 0, 3); + message("you float into the air!", 0); break; case POTION_CONFUSION: spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_CONFUSION_GAS_CLOUD_POTION], true, false); - message("a shimmering cloud of rainbow-colored gas billows out of the open flask!", 0, 3); + message("a shimmering cloud of rainbow-colored gas billows out of the open flask!", 0); break; case POTION_LICHEN: - message("a handful of tiny spores burst out of the open flask!", 0, 3); + message("a handful of tiny spores burst out of the open flask!", 0); spawnDungeonFeature(player.xLoc, player.yLoc, &dungeonFeatureCatalog[DF_LICHEN_PLANTED], true, false); break; case POTION_DETECT_MAGIC: @@ -7061,14 +7061,14 @@ void drinkPotion(item *theItem) { } if (hadEffect || hadEffect2) { if (hadEffect && hadEffect2) { - message("you can somehow feel the presence of magic on the level and in your pack.", 0, 3); + message("you can somehow feel the presence of magic on the level and in your pack.", 0); } else if (hadEffect) { - message("you can somehow feel the presence of magic on the level.", 0, 3); + message("you can somehow feel the presence of magic on the level.", 0); } else { - message("you can somehow feel the presence of magic in your pack.", 0, 3); + message("you can somehow feel the presence of magic in your pack.", 0); } } else { - message("you can somehow feel the absence of magic on the level and in your pack.", 0, 3); + message("you can somehow feel the absence of magic on the level and in your pack.", 0); } break; case POTION_HASTE_SELF: @@ -7079,14 +7079,14 @@ void drinkPotion(item *theItem) { if (player.status[STATUS_BURNING]) { extinguishFireOnCreature(&player); } - message("a comforting breeze envelops you, and you no longer fear fire.", 0, 3); + message("a comforting breeze envelops you, and you no longer fear fire.", 0); break; case POTION_INVISIBILITY: player.status[STATUS_INVISIBLE] = player.maxStatus[STATUS_INVISIBLE] = 75; - message("you shiver as a chill runs up your spine.", 0, 3); + message("you shiver as a chill runs up your spine.", 0); break; default: - message("you feel very strange, as though your body doesn't know how to react!", REQUIRE_ACKNOWLEDGMENT, 3); + message("you feel very strange, as though your body doesn't know how to react!", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } } @@ -7227,7 +7227,7 @@ void unequip(item *theItem) { buf2, theItem->quantity == 1 ? "was" : "were"); confirmMessages(); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); return; } else { if (!unequipItem(theItem, false)) { @@ -7240,7 +7240,7 @@ void unequip(item *theItem) { } confirmMessages(); sprintf(buf, "you are no longer %s %s.", (theItem->category & WEAPON ? "wielding" : "wearing"), buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } playerTurnEnded(); } @@ -7272,7 +7272,7 @@ void drop(item *theItem) { itemName(theItem, buf2, false, false, NULL); sprintf(buf, "you can't; your %s appears to be cursed.", buf2); confirmMessages(); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); } else if (canDrop()) { recordKeystrokeSequence(command); if (theItem->flags & ITEM_EQUIPPED) { @@ -7282,11 +7282,11 @@ void drop(item *theItem) { theItem->flags |= ITEM_PLAYER_AVOIDS; // Try not to pick up stuff you've already dropped. itemName(theItem, buf2, true, true, NULL); sprintf(buf, "You dropped %s.", buf2); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); playerTurnEnded(); } else { confirmMessages(); - message("There is already something there.", 0, 3); + message("There is already something there.", 0); } } @@ -7314,7 +7314,7 @@ item *promptForItemOfType(unsigned short category, if (keystroke < 'a' || keystroke > 'z') { confirmMessages(); if (keystroke != ESCAPE_KEY && keystroke != ACKNOWLEDGE_KEY) { - message("Invalid entry.", 0, 3); + message("Invalid entry.", 0); } return NULL; } @@ -7322,7 +7322,7 @@ item *promptForItemOfType(unsigned short category, theItem = itemOfPackLetter(keystroke); if (theItem == NULL) { confirmMessages(); - message("No such item.", 0, 3); + message("No such item.", 0); return NULL; } @@ -7350,7 +7350,7 @@ item *itemAtLoc(short x, short y) { pmap[x][y].flags &= ~HAS_ITEM; hiliteCell(x, y, &white, 75, true); rogue.automationActive = false; - message("ERROR: An item was supposed to be here, but I couldn't find it.", REQUIRE_ACKNOWLEDGMENT, 3); + message("ERROR: An item was supposed to be here, but I couldn't find it.", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); refreshDungeonCell(x, y); } return theItem; @@ -7485,7 +7485,7 @@ boolean equipItem(item *theItem, boolean force, item *unequipHint) { } confirmMessages(); - messageWithColor(buf1, &itemMessageColor, false, 3); + messageWithColor(buf1, &itemMessageColor, 0); if (theItem->flags & ITEM_CURSED) { itemName(theItem, buf2, false, false, NULL); @@ -7503,7 +7503,7 @@ boolean equipItem(item *theItem, boolean force, item *unequipHint) { sprintf(buf1, "your %s seizes you with a malevolent force.", buf2); break; } - messageWithColor(buf1, &itemMessageColor, 0, 3); + messageWithColor(buf1, &itemMessageColor, 0); } } @@ -7523,7 +7523,7 @@ boolean unequipItem(item *theItem, boolean force) { buf2, theItem->quantity == 1 ? "s" : ""); confirmMessages(); - messageWithColor(buf, &itemMessageColor, 0, 3); + messageWithColor(buf, &itemMessageColor, 0); return false; } theItem->flags &= ~ITEM_EQUIPPED; diff --git a/src/brogue/MainMenu.c b/src/brogue/MainMenu.c index 63cc546a..f8399d81 100644 --- a/src/brogue/MainMenu.c +++ b/src/brogue/MainMenu.c @@ -344,7 +344,7 @@ void titleMenu() { initializeMenuFlames(true, colors, colorStorage, colorSources, flames, mask); rogue.creaturesWillFlashThisTurn = false; // total unconscionable hack - playSpeech("Welcome to Brogue!", 1); + playSpeech("Welcome to Brogue!", ONE_SPEECH); do { if (isApplicationActive()) { diff --git a/src/brogue/Monsters.c b/src/brogue/Monsters.c index 0390e769..5bd44dec 100644 --- a/src/brogue/Monsters.c +++ b/src/brogue/Monsters.c @@ -572,7 +572,7 @@ creature *cloneMonster(creature *monst, boolean announce, boolean placeClone) { if (announce && canSeeMonster(newMonst)) { monsterName(monstName, newMonst, false); sprintf(buf, "another %s appears!", monstName); - message(buf, 0, 2); + message(buf, TWO_SPEECH); } } @@ -1006,7 +1006,7 @@ boolean summonMinions(creature *summoner) { } else { sprintf(buf, "%s incants darkly!", monstName); } - message(buf, 0, 2); + message(buf, TWO_SPEECH); } if (summoner->info.abilityFlags & MA_ENTER_SUMMONS) { @@ -1102,7 +1102,7 @@ void spawnPeriodicHorde() { // Instantally disentangles the player/creature. Useful for magical displacement like teleport and blink. void disentangle(creature *monst) { if (monst == &player && monst->status[STATUS_STUCK]) { - message("you break free!", false, 2); + message("you break free!", TWO_SPEECH); } monst->status[STATUS_STUCK] = 0; } @@ -1842,7 +1842,7 @@ void decrementMonsterStatus(creature *monst) { sprintf(buf2, "%s burns %s.", buf, (monst->info.flags & MONST_INANIMATE) ? "up" : "to death"); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), TWO_SPEECH); } return; } @@ -1859,7 +1859,7 @@ void decrementMonsterStatus(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s dissipates into thin air.", buf); - messageWithColor(buf2, &white, 0, 2); + messageWithColor(buf2, &white, TWO_SPEECH); } return; } @@ -1872,7 +1872,7 @@ void decrementMonsterStatus(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s dies of poison.", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), TWO_SPEECH); } return; } @@ -2244,7 +2244,7 @@ void perimeterCoords(short returnCoords[2], short n) { returnCoords[0] = 5; returnCoords[1] = (n - 31) - 4; } else { - message("ERROR! Bad perimeter coordinate request!", REQUIRE_ACKNOWLEDGMENT, 0); + message("ERROR! Bad perimeter coordinate request!", REQUIRE_ACKNOWLEDGMENT); returnCoords[0] = returnCoords[1] = 0; // garbage in, garbage out } } @@ -3088,7 +3088,7 @@ void moveAlly(creature *monst) { if (canSeeMonster(monst)) { monsterName(monstName, monst, true); sprintf(buf, "%s begins %s the fallen %s.", monstName, monsterText[monst->info.monsterID].absorbing, monst->targetCorpseName); - messageWithColor(buf, &goodMessageColor, 0, 2); + messageWithColor(buf, &goodMessageColor, TWO_SPEECH); } monst->corpseAbsorptionCounter = 20; monst->bookkeepingFlags |= MB_ABSORBING; @@ -3157,7 +3157,7 @@ boolean updateMonsterCorpseAbsorption(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf2, monst, true); sprintf(buf, "%s finished %s the %s.", buf2, monsterText[monst->info.monsterID].absorbing, monst->targetCorpseName); - messageWithColor(buf, &goodMessageColor, 0, 2); + messageWithColor(buf, &goodMessageColor, TWO_SPEECH); if (monst->absorptionBolt != BOLT_NONE) { sprintf(buf, "%s %s!", buf2, boltCatalog[monst->absorptionBolt].abilityDescription); } else if (monst->absorbBehavior) { @@ -3166,7 +3166,7 @@ boolean updateMonsterCorpseAbsorption(creature *monst) { sprintf(buf, "%s now %s!", buf2, monsterAbilityFlagDescriptions[unflag(monst->absorptionFlags)]); } resolvePronounEscapes(buf, monst); - messageWithColor(buf, &advancementMessageColor, 0, 2); + messageWithColor(buf, &advancementMessageColor, TWO_SPEECH); } monst->absorptionFlags = 0; monst->absorptionBolt = BOLT_NONE; diff --git a/src/brogue/Movement.c b/src/brogue/Movement.c index 998c8036..b87e2862 100644 --- a/src/brogue/Movement.c +++ b/src/brogue/Movement.c @@ -405,7 +405,7 @@ void speakLocation(char *locationDescription, short x, short y) { strcat(locationMessage, posY); strcat(locationMessage, posX); - playSpeech(locationMessage, 0); + playSpeech(locationMessage, ZERO_SPEECH); } void printLocationDescription(short x, short y) { @@ -454,7 +454,7 @@ void useKeyAt(item *theItem, short x, short y) { buf2, preposition, terrainName); - messageWithColor(buf, &itemMessageColor, 0, 1); + messageWithColor(buf, &itemMessageColor, 0); deleteItem(theItem); } else if (removeItemFromChain(theItem, floorItems)) { deleteItem(theItem); @@ -551,7 +551,7 @@ void freeCaptive(creature *monst) { becomeAllyWith(monst); monsterName(monstName, monst, false); sprintf(buf, "you free the grateful %s and gain a faithful ally.", monstName); - message(buf, 0, 2); + message(buf, TWO_SPEECH); } boolean freeCaptivesEmbeddedAt(short x, short y) { @@ -872,7 +872,7 @@ boolean playerMoves(short direction) { layer = layerWithTMFlag(newX, newY, TM_PROMOTES_ON_PLAYER_ENTRY); if (tileCatalog[pmap[newX][newY].layers[layer]].flags & T_OBSTRUCTS_PASSABILITY) { committed = true; - message(tileCatalog[pmap[newX][newY].layers[layer]].flavorText, 0, 1); + message(tileCatalog[pmap[newX][newY].layers[layer]].flavorText, 0); promoteTile(newX, newY, layer, false); playerTurnEnded(); return true; @@ -984,12 +984,12 @@ boolean playerMoves(short direction) { committed = true; sprintf(buf, "you struggle but %s is holding your legs!", monstName); moveEntrancedMonsters(direction); - message(buf, 0, 2); + message(buf, TWO_SPEECH); playerTurnEnded(); return true; } else { sprintf(buf, "you cannot move; %s is holding your legs!", monstName); - message(buf, 0, 2); + message(buf, TWO_SPEECH); cancelKeystroke(); return false; } @@ -1005,7 +1005,7 @@ boolean playerMoves(short direction) { && player.status[STATUS_IMMUNE_TO_FIRE] <= 1 && !cellHasTerrainFlag(newX, newY, T_ENTANGLES) && !cellHasTMFlag(newX, newY, TM_IS_SECRET)) { - message("that would be certain death!", 0, 2); + message("that would be certain death!", TWO_SPEECH); brogueAssert(!committed); cancelKeystroke(); return false; // player won't willingly step into lava @@ -1098,7 +1098,7 @@ boolean playerMoves(short direction) { // Don't interrupt exploration with this message. if (--player.status[STATUS_STUCK]) { if (!rogue.automationActive) { - message("you struggle but cannot free yourself.", 0, 2); + message("you struggle but cannot free yourself.", TWO_SPEECH); } moveEntrancedMonsters(direction); committed = true; @@ -1106,7 +1106,7 @@ boolean playerMoves(short direction) { return true; } else { if (!rogue.automationActive) { - message("you break free!", 0, 2); + message("you break free!", TWO_SPEECH); } if (tileCatalog[pmap[x][y].layers[SURFACE]].flags & T_ENTANGLES) { pmap[x][y].layers[SURFACE] = NOTHING; @@ -1191,7 +1191,7 @@ boolean playerMoves(short direction) { refreshDungeonCell(newX, newY); } - messageWithColor(tileCatalog[i].flavorText, &backgroundMessageColor, 0, 2); + messageWithColor(tileCatalog[i].flavorText, &backgroundMessageColor, TWO_SPEECH); } } return playerMoved; @@ -1633,7 +1633,7 @@ void travel(short x, short y, boolean autoConfirm) { } if (!(pmap[x][y].flags & (DISCOVERED | MAGIC_MAPPED))) { - message("You have not explored that location.", 0, 2); + message("You have not explored that location.", TWO_SPEECH); return; } @@ -1653,7 +1653,7 @@ void travel(short x, short y, boolean autoConfirm) { staircaseConfirmKey = 0; } displayRoute(distanceMap, false); - message("Travel this route? (y/n)", 0, 2); + message("Travel this route? (y/n)", TWO_SPEECH); do { nextBrogueEvent(&theEvent, true, false, false); @@ -1682,7 +1682,7 @@ void travel(short x, short y, boolean autoConfirm) { // } } else { rogue.cursorLoc[0] = rogue.cursorLoc[1] = -1; - message("No path is available.", 0, 2); + message("No path is available.", TWO_SPEECH); } freeGrid(distanceMap); } @@ -1915,11 +1915,11 @@ boolean explore(short frameDelay) { headingToStairs = false; if (player.status[STATUS_CONFUSED]) { - message("Not while you're confused.", 0, 2); + message("Not while you're confused.", TWO_SPEECH); return false; } if (cellHasTerrainFlag(player.xLoc, player.yLoc, T_OBSTRUCTS_PASSABILITY)) { - message("Not while you're trapped.", 0, 2); + message("Not while you're trapped.", TWO_SPEECH); return false; } @@ -1942,7 +1942,7 @@ boolean explore(short frameDelay) { if (!rogue.autoPlayingLevel) { message(KEYBOARD_LABELS ? "Exploring... press any key to stop." : "Exploring... touch anywhere to stop.", - 0, 0); + 0); // A little hack so the exploring message remains bright while exploring and then auto-dims when // another message is displayed: confirmMessages(); @@ -2009,7 +2009,7 @@ void autoPlayLevel(boolean fastForward) { rogue.autoPlayingLevel = true; confirmMessages(); - message(KEYBOARD_LABELS ? "Playing... press any key to stop." : "Playing... touch anywhere to stop.", 0, 0); + message(KEYBOARD_LABELS ? "Playing... press any key to stop." : "Playing... touch anywhere to stop.", 0); // explore until we are not making progress do { @@ -2168,7 +2168,7 @@ boolean search(short searchStrength) { boolean proposeOrConfirmLocation(short x, short y, char *failureMessage) { boolean retval = false; if (player.xLoc == x && player.yLoc == y) { - message("you are already there.", 0, 0); + message("you are already there.", 0); } else if (pmap[x][y].flags & (DISCOVERED | MAGIC_MAPPED)) { if (rogue.cursorLoc[0] == x && rogue.cursorLoc[1] == y) { retval = true; @@ -2177,7 +2177,7 @@ boolean proposeOrConfirmLocation(short x, short y, char *failureMessage) { rogue.cursorLoc[1] = y; } } else { - message(failureMessage, 0, 0); + message(failureMessage, 0); } return retval; } @@ -2191,7 +2191,7 @@ boolean useStairs(short stairDirection) { //copyDisplayBuffer(fromBuf, displayBuffer); rogue.cursorLoc[0] = rogue.cursorLoc[1] = -1; rogue.depthLevel++; - message("You descend.", 0, 1); + message("You descend.", 0); startLevel(rogue.depthLevel - 1, stairDirection); if (rogue.depthLevel > rogue.deepestLevel) { rogue.deepestLevel = rogue.depthLevel; @@ -2202,8 +2202,8 @@ boolean useStairs(short stairDirection) { victory(true); } else { confirmMessages(); - messageWithColor("the crystal archway repels you with a mysterious force!", &lightBlue, 0, 1); - messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0, 1); + messageWithColor("the crystal archway repels you with a mysterious force!", &lightBlue, 0); + messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0); } succeeded = true; } else { @@ -2214,7 +2214,7 @@ boolean useStairs(short stairDirection) { victory(false); } else { //copyDisplayBuffer(fromBuf, displayBuffer); - message("You ascend.", 0, 1); + message("You ascend.", 0); startLevel(rogue.depthLevel + 1, stairDirection); //copyDisplayBuffer(toBuf, displayBuffer); //irisFadeBetweenBuffers(fromBuf, toBuf, mapToWindowX(player.xLoc), mapToWindowY(player.yLoc), 20, true); @@ -2222,8 +2222,8 @@ boolean useStairs(short stairDirection) { succeeded = true; } else { confirmMessages(); - messageWithColor("The dungeon exit is magically sealed!", &lightBlue, 0, 1); - messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0, 1); + messageWithColor("The dungeon exit is magically sealed!", &lightBlue, 0); + messageWithColor("(Only the bearer of the Amulet of Yendor may pass.)", &backgroundMessageColor, 0); } } @@ -2266,7 +2266,7 @@ void updateFieldOfViewDisplay(boolean updateDancingTerrain, boolean refreshDispl if (theItem && (theItem->category & KEY)) { itemName(theItem, name, false, true, NULL); sprintf(buf, "you see %s.", name); - messageWithColor(buf, &itemMessageColor, 0, 1); + messageWithColor(buf, &itemMessageColor, 0); } } if (!(pmap[i][j].flags & MAGIC_MAPPED) @@ -2274,7 +2274,7 @@ void updateFieldOfViewDisplay(boolean updateDancingTerrain, boolean refreshDispl strcpy(name, tileCatalog[pmap[i][j].layers[layerWithTMFlag(i, j, TM_INTERRUPT_EXPLORATION_WHEN_SEEN)]].description); sprintf(buf, "you see %s.", name); - messageWithColor(buf, &backgroundMessageColor, 0, 1); + messageWithColor(buf, &backgroundMessageColor, 0); } } discoverCell(i, j); diff --git a/src/brogue/Recordings.c b/src/brogue/Recordings.c index 255fb8e4..069325a9 100644 --- a/src/brogue/Recordings.c +++ b/src/brogue/Recordings.c @@ -312,7 +312,7 @@ void playbackPanic() { refreshSideBar(-1, -1, false); confirmMessages(); - message("Playback is out of sync.", 0, 0); + message("Playback is out of sync.", 0); printTextBox(OOS_APOLOGY, 0, 0, 0, &white, &black, rbuf, NULL, 0); @@ -360,7 +360,7 @@ void recallEvent(rogueEvent *event) { case END_OF_RECORDING: case EVENT_ERROR: default: - message("Unrecognized event type in playback.", REQUIRE_ACKNOWLEDGMENT, 0); + message("Unrecognized event type in playback.", REQUIRE_ACKNOWLEDGMENT); printf("Unrecognized event type in playback: event ID %i", c); tryAgain = true; playbackPanic(); @@ -817,13 +817,13 @@ void pausePlayback() { if (!rogue.playbackPaused) { rogue.playbackPaused = true; messageWithColor(KEYBOARD_LABELS ? "recording paused. Press space to play." : "recording paused.", - &teal, 0, 0); + &teal, 0); refreshSideBar(-1, -1, false); //oldRNG = rogue.RNG; //rogue.RNG = RNG_SUBSTANTIVE; mainInputLoop(); //rogue.RNG = oldRNG; - messageWithColor("recording unpaused.", &teal, 0, 0); + messageWithColor("recording unpaused.", &teal, 0); rogue.playbackPaused = false; refreshSideBar(-1, -1, false); rogue.playbackDelayThisTurn = DEFAULT_PLAYBACK_DELAY; @@ -877,9 +877,9 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { displayLevel(); refreshSideBar(-1, -1, false); if (rogue.playbackOmniscience) { - messageWithColor("Omniscience enabled.", &teal, 0, 0); + messageWithColor("Omniscience enabled.", &teal, 0); } else { - messageWithColor("Omniscience disabled.", &teal, 0, 0); + messageWithColor("Omniscience disabled.", &teal, 0); } return true; case ASCEND_KEY: @@ -959,7 +959,7 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { rogue.nextGame = NG_VIEW_RECORDING; rogue.gameHasEnded = true; } else { - message("File not found.", 0, 0); + message("File not found.", 0); } } rogue.playbackMode = true; @@ -973,7 +973,7 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { rogue.nextGame = NG_OPEN_GAME; rogue.gameHasEnded = true; } else { - message("File not found.", 0, 0); + message("File not found.", 0); } } rogue.playbackMode = true; @@ -999,10 +999,10 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { refreshSideBar(-1, -1, false); if (rogue.trueColorMode) { messageWithColor(KEYBOARD_LABELS ? "Color effects disabled. Press '\\' again to enable." : "Color effects disabled.", - &teal, 0, 0); + &teal, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Color effects enabled. Press '\\' again to disable." : "Color effects enabled.", - &teal, 0, 0); + &teal, 0); } return true; case AGGRO_DISPLAY_KEY: @@ -1011,10 +1011,10 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { refreshSideBar(-1, -1, false); if (rogue.displayAggroRangeMode) { messageWithColor(KEYBOARD_LABELS ? "Stealth range displayed. Press ']' again to hide." : "Stealth range displayed.", - &teal, 0, 0); + &teal, 0); } else { messageWithColor(KEYBOARD_LABELS ? "Stealth range hidden. Press ']' again to display." : "Stealth range hidden.", - &teal, 0, 0); + &teal, 0); } return true; case GRAPHICS_KEY: @@ -1024,17 +1024,17 @@ boolean executePlaybackInput(rogueEvent *recordingInput) { case TEXT_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to text mode. Press 'G' again to enable tiles." - : "Switched to text mode.", &teal, 0, 0); + : "Switched to text mode.", &teal, 0); break; case TILES_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to graphical tiles. Press 'G' again to enable hybrid mode." - : "Switched to graphical tiles.", &teal, 0, 0); + : "Switched to graphical tiles.", &teal, 0); break; case HYBRID_GRAPHICS: messageWithColor(KEYBOARD_LABELS ? "Switched to hybrid mode. Press 'G' again to disable tiles." - : "Switched to hybrid mode.", &teal, 0, 0); + : "Switched to hybrid mode.", &teal, 0); break; } } @@ -1189,7 +1189,7 @@ void saveGame() { rename(currentFilePath, filePath); strcpy(currentFilePath, filePath); rogue.recording = false; - message("Saved.", REQUIRE_ACKNOWLEDGMENT, 0); + message("Saved.", REQUIRE_ACKNOWLEDGMENT); rogue.gameHasEnded = true; } else { askAgain = true; @@ -1415,7 +1415,7 @@ boolean selectFile(char *prompt, char *defaultName, char *suffix) { retval = true; } else { confirmMessages(); - message("File not found.", 0, 0); + message("File not found.", 0); retval = false; } } @@ -1496,7 +1496,7 @@ void parseFile() { recordingLocation = oldRecLoc; lengthOfPlaybackFile = oldLength; locationInRecordingBuffer = oldBufLoc; - message("File parsed.", 0, 0); + message("File parsed.", 0); } else { confirmMessages(); } diff --git a/src/brogue/Rogue.h b/src/brogue/Rogue.h index fd7c1995..36c4d547 100644 --- a/src/brogue/Rogue.h +++ b/src/brogue/Rogue.h @@ -357,6 +357,7 @@ typedef struct rogueEvent { typedef struct speechData { short priority; + unsigned long flags; char message[DCOLS]; } speechData; @@ -1160,6 +1161,7 @@ enum tileFlags { #define AUTOPLAY_KEY 'A' #define SEED_KEY '~' #define EASY_MODE_KEY '&' +#define TTS_TOGGLE_KEY '!' #define ESCAPE_KEY '\033' #define RETURN_KEY '\012' #define DELETE_KEY '\177' @@ -2657,6 +2659,12 @@ enum messageFlags { REQUIRE_ACKNOWLEDGMENT = Fl(0), REFRESH_SIDEBAR = Fl(1), FOLDABLE = Fl(2), + NO_SPEECH = Fl(3), + ZERO_SPEECH = Fl(4), + ONE_SPEECH = Fl(5), + TWO_SPEECH = Fl(6), + THREE_SPEECH = Fl(7), + SPEECH_BLOCKS = Fl(8) }; typedef struct archivedMessage { @@ -2750,8 +2758,9 @@ extern "C" { void nextKeyOrMouseEvent(rogueEvent *returnEvent, boolean textInput, boolean colorsDance); void notifyEvent(short eventId, int data1, int data2, const char *str1, const char *str2); boolean takeScreenshot(); + void toggleTTS(); enum graphicsModes setGraphicsMode(enum graphicsModes mode); - void playSpeech(char *text, short priority); + void playSpeech(char *text, enum messageFlags flags); boolean controlKeyIsDown(); boolean shiftKeyIsDown(); short getHighScoresList(rogueHighScoresEntry returnList[HIGH_SCORES_COUNT]); @@ -2924,9 +2933,9 @@ extern "C" { void displayRecentMessages(); void displayMessageArchive(); void temporaryMessage(const char *msg1, enum messageFlags flags); - void messageWithColor(char *msg, color *theColor, enum messageFlags flags, short speechPriority); + void messageWithColor(char *msg, color *theColor, enum messageFlags flags); void flavorMessage(char *msg); - void message(const char *msg, enum messageFlags flags, short speechPriority); + void message(const char *msg, enum messageFlags flags); void displayMoreSignWithoutWaitingForAcknowledgment(); void displayMoreSign(); short encodeMessageColor(char *msg, short i, const color *theColor); diff --git a/src/brogue/RogueMain.c b/src/brogue/RogueMain.c index 6248968d..36a19e61 100644 --- a/src/brogue/RogueMain.c +++ b/src/brogue/RogueMain.c @@ -123,16 +123,16 @@ void benchmark() { void welcome() { char buf[DCOLS*3], buf2[DCOLS*3]; - message("Hello and welcome, adventurer, to the Dungeons of Doom!", 0, 1); + message("Hello and welcome, adventurer, to the Dungeons of Doom!", 0); strcpy(buf, "Retrieve the "); encodeMessageColor(buf, strlen(buf), &itemMessageColor); strcat(buf, "Amulet of Yendor"); encodeMessageColor(buf, strlen(buf), &white); sprintf(buf2, " from the %ith floor and escape with it!", AMULET_LEVEL); strcat(buf, buf2); - message(buf, 0, 1); + message(buf, 0); if (KEYBOARD_LABELS) { - messageWithColor("Press for help at any time.", &backgroundMessageColor, 0, 1); + messageWithColor("Press for help at any time.", &backgroundMessageColor, 0); } flavorMessage("The doors to the dungeon slam shut behind you."); } @@ -744,9 +744,9 @@ void startLevel(short oldLevelNumber, short stairDirection) { if (!levels[rogue.depthLevel-1].visited) { levels[rogue.depthLevel-1].visited = true; if (rogue.depthLevel == AMULET_LEVEL) { - messageWithColor("An alien energy permeates the area. The Amulet of Yendor must be nearby!", &itemMessageColor, 0, 2); + messageWithColor("An alien energy permeates the area. The Amulet of Yendor must be nearby!", &itemMessageColor, 0); } else if (rogue.depthLevel == DEEPEST_LEVEL) { - messageWithColor("An overwhelming sense of peace and tranquility settles upon you.", &lightBlue, 0, 2); + messageWithColor("An overwhelming sense of peace and tranquility settles upon you.", &lightBlue, 0); } } @@ -972,7 +972,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { if (rogue.playbackMode) { playback = rogue.playbackMode; rogue.playbackMode = false; - message("(The player quit at this point.)", REQUIRE_ACKNOWLEDGMENT, 2); + message("(The player quit at this point.)", REQUIRE_ACKNOWLEDGMENT); rogue.playbackMode = playback; } } else { @@ -987,7 +987,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { } player.currentHP = 0; // So it shows up empty in the side bar. refreshSideBar(-1, -1, false); - messageWithColor(buf, &badMessageColor, 0, 3); + messageWithColor(buf, &badMessageColor, 0); displayMoreSignWithoutWaitingForAcknowledgment(); do { @@ -1017,7 +1017,7 @@ void gameOver(char *killedBy, boolean useCustomPhrasing) { rogue.creaturesWillFlashThisTurn = false; if (D_IMMORTAL && !rogue.quit) { - message("...but then you get better.", 0, 3); + message("...but then you get better.", 0); player.currentHP = player.info.maxHP; if (player.status[STATUS_NUTRITION] < 10) { player.status[STATUS_NUTRITION] = STOMACH_SIZE; @@ -1126,7 +1126,7 @@ void victory(boolean superVictory) { // First screen - Congratulations... // if (superVictory) { - message( "Light streams through the portal, and you are teleported out of the dungeon.", 0, 3); + message( "Light streams through the portal, and you are teleported out of the dungeon.", 0); copyDisplayBuffer(dbuf, displayBuffer); funkyFade(dbuf, &superVictoryColor, 0, 240, mapToWindowX(player.xLoc), mapToWindowY(player.yLoc), false); displayMoreSign(); @@ -1136,7 +1136,7 @@ void victory(boolean superVictory) { deleteMessages(); strcpy(displayedMessage[0], "You retire in splendor, forever renowned for your remarkable triumph. "); } else { - message( "You are bathed in sunlight as you throw open the heavy doors.", 0, 3); + message( "You are bathed in sunlight as you throw open the heavy doors.", 0); copyDisplayBuffer(dbuf, displayBuffer); funkyFade(dbuf, &white, 0, 240, mapToWindowX(player.xLoc), mapToWindowY(player.yLoc), false); displayMoreSign(); @@ -1260,22 +1260,22 @@ void victory(boolean superVictory) { void enableEasyMode() { if (rogue.easyMode) { - message("Alas, all hope of salvation is lost. You shed scalding tears at your plight.", 0, 3); + message("Alas, all hope of salvation is lost. You shed scalding tears at your plight.", 0); return; } - message("A dark presence surrounds you, whispering promises of stolen power.", REQUIRE_ACKNOWLEDGMENT, 3); + message("A dark presence surrounds you, whispering promises of stolen power.", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); if (confirm("Succumb to demonic temptation (i.e. enable Easy Mode)?", false)) { recordKeystroke(EASY_MODE_KEY, false, true); - message("An ancient and terrible evil burrows into your willing flesh!", REQUIRE_ACKNOWLEDGMENT, 3); + message("An ancient and terrible evil burrows into your willing flesh!", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); player.info.displayChar = '&'; rogue.easyMode = true; refreshDungeonCell(player.xLoc, player.yLoc); refreshSideBar(-1, -1, false); - message("Wracked by spasms, your body contorts into an ALL-POWERFUL AMPERSAND!!!", 0, 3); - message("You have a feeling that you will take 20% as much damage from now on.", 0, 3); - message("But great power comes at a great price -- specifically, a 90% income tax rate.", 0, 3); + message("Wracked by spasms, your body contorts into an ALL-POWERFUL AMPERSAND!!!", 0); + message("You have a feeling that you will take 20% as much damage from now on.", 0); + message("But great power comes at a great price -- specifically, a 90% income tax rate.", 0); } else { - message("The evil dissipates, hissing, from the air around you.", 0, 3); + message("The evil dissipates, hissing, from the air around you.", 0); } } diff --git a/src/brogue/Time.c b/src/brogue/Time.c index 82bc8742..6283dd68 100644 --- a/src/brogue/Time.c +++ b/src/brogue/Time.c @@ -170,7 +170,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { if (monst == &player) { sprintf(buf, "you plunge into %s!", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_LAVA_INSTA_DEATH)]].description); - message(buf, REQUIRE_ACKNOWLEDGMENT, 2); + message(buf, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); sprintf(buf, "Killed by %s", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_LAVA_INSTA_DEATH)]].description); gameOver(buf, true); @@ -186,7 +186,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { s += 3; } sprintf(buf2, "%s is consumed by the %s instantly!", buf, s); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), 0); } killCreature(monst, false); spawnDungeonFeature(*x, *y, &(dungeonFeatureCatalog[DF_CREATURE_FIRE]), true, false); @@ -226,10 +226,10 @@ void applyInstantTileEffectsToCreature(creature *monst) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "a pressure plate clicks underneath %s!", buf); - message(buf2, REQUIRE_ACKNOWLEDGMENT, 2); + message(buf2, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } else if (playerCanSee(*x, *y)) { // usually means an invisible monster - message("a pressure plate clicks!", 0, 2); + message("a pressure plate clicks!", 0 | SPEECH_BLOCKS); } for (layer = 0; layer < NUMBER_TERRAIN_LAYERS; layer++) { if (tileCatalog[pmap[*x][*y].layers[layer]].flags & T_IS_DF_TRAP) { @@ -284,14 +284,14 @@ void applyInstantTileEffectsToCreature(creature *monst) { // Don't interrupt exploration with this message. sprintf(buf2, "you are stuck fast in %s!", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_ENTANGLES)]].description); - message(buf2, 0, 2); + message(buf2, 0); } } else if (canDirectlySeeMonster(monst)) { // it's a monster if (!rogue.automationActive) { monsterName(buf, monst, true); sprintf(buf2, "%s is stuck fast in %s!", buf, tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_ENTANGLES)]].description); - message(buf2, 0, 2); + message(buf2, 0); } } } @@ -305,11 +305,11 @@ void applyInstantTileEffectsToCreature(creature *monst) { if (monst == &player) { rogue.disturbed = true; for (layer = 0; layer < NUMBER_TERRAIN_LAYERS && !(tileCatalog[pmap[*x][*y].layers[layer]].flags & T_CAUSES_EXPLOSIVE_DAMAGE); layer++); - message(tileCatalog[pmap[*x][*y].layers[layer]].flavorText, 0, 2); + message(tileCatalog[pmap[*x][*y].layers[layer]].flavorText, 0); if (rogue.armor && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_DAMPENING) { itemName(rogue.armor, buf2, false, false, NULL); sprintf(buf, "Your %s pulses and absorbs the damage.", buf2); - messageWithColor(buf, &goodMessageColor, 0, 2); + messageWithColor(buf, &goodMessageColor, 0); autoIdentify(rogue.armor); } else if (inflictDamage(NULL, &player, damage, &yellow, false)) { strcpy(buf2, tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_CAUSES_EXPLOSIVE_DAMAGE)]].description); @@ -330,14 +330,14 @@ void applyInstantTileEffectsToCreature(creature *monst) { sprintf(buf2, "%s %s %s.", buf, (monst->info.flags & MONST_INANIMATE) ? "is destroyed by" : "dies in", buf3); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), 0); refreshDungeonCell(*x, *y); return; } else { // if survived sprintf(buf2, "%s engulfs %s.", tileCatalog[pmap[*x][*y].layers[layerWithFlag(*x, *y, T_CAUSES_EXPLOSIVE_DAMAGE)]].description, buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), 0); } } } @@ -350,7 +350,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_RESPIRATION) { if (!(rogue.armor->flags & ITEM_RUNIC_IDENTIFIED)) { - message("Your armor trembles and a pocket of clean air swirls around you.", 0, 2); + message("Your armor trembles and a pocket of clean air swirls around you.", 0); autoIdentify(rogue.armor); } } else { @@ -370,7 +370,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { monsterName(buf, monst, true); sprintf(buf2, "%s choke%s and gag%s on the overpowering stench of decay.", buf, (monst == &player ? "": "s"), (monst == &player ? "": "s")); - message(buf2, 0, 2); + message(buf2, 0); } monst->status[STATUS_NAUSEOUS] = monst->maxStatus[STATUS_NAUSEOUS] = max(monst->status[STATUS_NAUSEOUS], 20); } @@ -387,7 +387,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { flashMonster(monst, &confusionGasColor, 100); monsterName(buf, monst, true); sprintf(buf2, "%s %s very confused!", buf, (monst == &player ? "feel": "looks")); - message(buf2, 0, 2); + message(buf2, 0); } monst->status[STATUS_CONFUSED] = monst->maxStatus[STATUS_CONFUSED] = max(monst->status[STATUS_CONFUSED], 25); } @@ -401,7 +401,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { flashMonster(monst, &pink, 100); monsterName(buf, monst, true); sprintf(buf2, "%s %s paralyzed!", buf, (monst == &player ? "are": "is")); - message(buf2, (monst == &player) ? REQUIRE_ACKNOWLEDGMENT : 0, 2); + message(buf2, (monst == &player) ? REQUIRE_ACKNOWLEDGMENT : 0); } monst->status[STATUS_PARALYZED] = monst->maxStatus[STATUS_PARALYZED] = max(monst->status[STATUS_PARALYZED], 20); if (monst == &player) { @@ -425,7 +425,7 @@ void applyInstantTileEffectsToCreature(creature *monst) { flashMonster(monst, &green, 100); monsterName(buf, monst, true); sprintf(buf2, "the lichen's grasping tendrils poison %s.", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), 0); } damage = max(0, 5 - monst->status[STATUS_POISONED]); addPoison(monst, damage, 0); // Lichen doesn't increase poison concentration above 1. @@ -482,7 +482,7 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { sprintf(buf, "%s float%s away in the current!", buf2, (theItem->quantity == 1 ? "s" : "")); - messageWithColor(buf, &itemMessageColor, 0, 2); + messageWithColor(buf, &itemMessageColor, 0); } } } @@ -501,12 +501,12 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { if (monst == &player) { if (rogue.armor && (rogue.armor->flags & ITEM_RUNIC) && rogue.armor->enchant2 == A_RESPIRATION) { if (!(rogue.armor->flags & ITEM_RUNIC_IDENTIFIED)) { - message("Your armor trembles and a pocket of clean air swirls around you.", 0, 2); + message("Your armor trembles and a pocket of clean air swirls around you.", 0); autoIdentify(rogue.armor); } } else { rogue.disturbed = true; - messageWithColor(tileCatalog[pmap[x][y].layers[layer]].flavorText, &badMessageColor, 0, 2); + messageWithColor(tileCatalog[pmap[x][y].layers[layer]].flavorText, &badMessageColor, 0); if (inflictDamage(NULL, &player, damage, tileCatalog[pmap[x][y].layers[layer]].backColor, true)) { sprintf(buf, "Killed by %s", tileCatalog[pmap[x][y].layers[layer]].description); gameOver(buf, true); @@ -521,7 +521,7 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s dies.", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), 0); } refreshDungeonCell(x, y); return; @@ -538,7 +538,7 @@ void applyGradualTileEffectsToCreature(creature *monst, short ticks) { if (monst->currentHP < monst->info.maxHP) { monst->currentHP = min(monst->currentHP + damage, monst->info.maxHP); if (monst == &player) { - messageWithColor("you feel much better.", &goodMessageColor, 0, 2); + messageWithColor("you feel much better.", &goodMessageColor, 0); } } } @@ -809,21 +809,21 @@ void checkNutrition() { if (player.status[STATUS_NUTRITION] == HUNGER_THRESHOLD) { player.status[STATUS_NUTRITION]--; sprintf(buf, "you are hungry%s.", foodWarning); - message(buf, foodWarning[0] ? REQUIRE_ACKNOWLEDGMENT : 0, 2); + message(buf, foodWarning[0] ? REQUIRE_ACKNOWLEDGMENT : 0); } else if (player.status[STATUS_NUTRITION] == WEAK_THRESHOLD) { player.status[STATUS_NUTRITION]--; sprintf(buf, "you feel weak with hunger%s.", foodWarning); - message(buf, REQUIRE_ACKNOWLEDGMENT, 2); + message(buf, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } else if (player.status[STATUS_NUTRITION] == FAINT_THRESHOLD) { player.status[STATUS_NUTRITION]--; sprintf(buf, "you feel faint with hunger%s.", foodWarning); - message(buf, REQUIRE_ACKNOWLEDGMENT, 2); + message(buf, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } else if (player.status[STATUS_NUTRITION] <= 1) { // Force the player to eat something if he has it for (theItem = packItems->nextItem; theItem != NULL; theItem = theItem->nextItem) { if (theItem->category == FOOD) { sprintf(buf, "unable to control your hunger, you eat a %s.", (theItem->kind == FRUIT ? "mango" : "ration of food")); - messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 2); + messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); apply(theItem, false); break; } @@ -832,7 +832,7 @@ void checkNutrition() { if (player.status[STATUS_NUTRITION] == 1) { // Didn't manage to eat any food above. player.status[STATUS_NUTRITION] = 0; // So the status bar changes in time for the message: - message("you are starving to death!", REQUIRE_ACKNOWLEDGMENT, 2); + message("you are starving to death!", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } } @@ -852,7 +852,7 @@ void burnItem(item *theItem) { refreshDungeonCell(x, y); } if (playerCanSee(x, y)) { - messageWithColor(buf2, &itemMessageColor, 0, 2); + messageWithColor(buf2, &itemMessageColor, 0); } spawnDungeonFeature(x, y, &(dungeonFeatureCatalog[DF_ITEM_FIRE]), true, false); } @@ -935,7 +935,7 @@ void addXPXPToAlly(short XPXP, creature *monst) { updateVision(true); monsterName(theMonsterName, monst, false); sprintf(buf, "you have developed a telepathic bond with your %s.", theMonsterName); - messageWithColor(buf, &advancementMessageColor, 0, 2); + messageWithColor(buf, &advancementMessageColor, 0); } if (monst->xpxp > 1500 * 20) { rogue.featRecord[FEAT_COMPANION] = true; @@ -980,9 +980,9 @@ void playerFalls() { layer = layerWithFlag(player.xLoc, player.yLoc, T_AUTO_DESCENT); if (layer >= 0) { - message(tileCatalog[pmap[player.xLoc][player.yLoc].layers[layer]].flavorText, REQUIRE_ACKNOWLEDGMENT, 2); + message(tileCatalog[pmap[player.xLoc][player.yLoc].layers[layer]].flavorText, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } else if (layer == -1) { - message("You plunge downward!", REQUIRE_ACKNOWLEDGMENT, 2); + message("You plunge downward!", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } player.bookkeepingFlags &= ~(MB_IS_FALLING | MB_SEIZED | MB_SEIZING); @@ -994,12 +994,12 @@ void playerFalls() { damage = randClumpedRange(FALL_DAMAGE_MIN, FALL_DAMAGE_MAX, 2); boolean killed = false; if (terrainFlags(player.xLoc, player.yLoc) & T_IS_DEEP_WATER) { - messageWithColor("You fall into deep water, unharmed.", &badMessageColor, 0, 2); + messageWithColor("You fall into deep water, unharmed.", &badMessageColor, 0); } else { if (cellHasTMFlag(player.xLoc, player.yLoc, TM_ALLOWS_SUBMERGING)) { damage /= 2; // falling into liquid (shallow water, bog, etc.) hurts less than hitting hard floor } - messageWithColor("You are injured by the fall.", &badMessageColor, 0, 2); + messageWithColor("You are injured by the fall.", &badMessageColor, 0); if (inflictDamage(NULL, &player, damage, &red, false)) { gameOver("Killed by a fall", true); killed = true; @@ -1009,7 +1009,7 @@ void playerFalls() { rogue.deepestLevel = rogue.depthLevel; } } else { - message("A strange force seizes you as you fall.", 0, 2); + message("A strange force seizes you as you fall.", 0); teleport(&player, -1, -1, true); } createFlare(player.xLoc, player.yLoc, GENERIC_FLASH_LIGHT); @@ -1364,7 +1364,7 @@ void monstersFall() { if (canSeeMonster(monst)) { monsterName(buf, monst, true); sprintf(buf2, "%s plunges out of sight!", buf); - messageWithColor(buf2, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf2, messageColorFromVictim(monst), 0); } if (monst->info.flags & MONST_GETS_TURN_ON_ACTIVATION) { @@ -1772,7 +1772,7 @@ void processIncrementalAutoID() { if (theItem->charges <= 0) { itemName(theItem, theItemName, false, false, NULL); sprintf(buf, "you are now familiar enough with your %s to identify it.", theItemName); - messageWithColor(buf, &itemMessageColor, 0, 2); + messageWithColor(buf, &itemMessageColor, 0); if (theItem->category & ARMOR) { // Don't necessarily reveal the armor's runic specifically, just that it has one. @@ -1784,7 +1784,7 @@ void processIncrementalAutoID() { itemName(theItem, theItemName, true, true, NULL); sprintf(buf, "%s %s.", (theItem->quantity > 1 ? "they are" : "it is"), theItemName); - messageWithColor(buf, &itemMessageColor, 0, 2); + messageWithColor(buf, &itemMessageColor, 0); } } } @@ -1837,7 +1837,7 @@ void rechargeItemsIncrementally(short multiplier) { if (theItem->charges == 0) { itemName(theItem, theItemName, false, false, NULL); sprintf(buf, "your %s has recharged.", theItemName); - message(buf, 0, 2); + message(buf, 0); } } } @@ -1851,7 +1851,7 @@ void extinguishFireOnCreature(creature *monst) { rogue.minersLight.lightColor = &minersLightColor; refreshDungeonCell(player.xLoc, player.yLoc); updateVision(true); - message("you are no longer on fire.", 0, 2); + message("you are no longer on fire.", 0); } } @@ -1918,17 +1918,17 @@ void monsterEntersLevel(creature *monst, short n) { if (inflictDamage(NULL, monst, randClumpedRange(6, 12, 2), &red, false)) { if (canSeeMonster(monst)) { sprintf(buf, "%s plummets from above and splatters against the ground!", monstName); - messageWithColor(buf, messageColorFromVictim(monst), 0, 2); + messageWithColor(buf, messageColorFromVictim(monst), 0); } } else { if (canSeeMonster(monst)) { sprintf(buf, "%s falls from above and crashes to the ground!", monstName); - message(buf, 0, 2); + message(buf, 0); } } } else if (canSeeMonster(monst)) { sprintf(buf, "%s swoops into the cavern from above.", monstName); - message(buf, 0, 2); + message(buf, 0); } } } @@ -1970,7 +1970,7 @@ void decrementPlayerStatus() { if (player.status[STATUS_TELEPATHIC] > 0 && !--player.status[STATUS_TELEPATHIC]) { updateVision(true); - message("your preternatural mental sensitivity fades.", 0, 2); + message("your preternatural mental sensitivity fades.", 0); } if (player.status[STATUS_DARKNESS] > 0) { @@ -1981,42 +1981,42 @@ void decrementPlayerStatus() { if (player.status[STATUS_HALLUCINATING] > 0 && !--player.status[STATUS_HALLUCINATING]) { displayLevel(); - message("your hallucinations fade.", 0, 2); + message("your hallucinations fade.", 0); } if (player.status[STATUS_LEVITATING] > 0 && !--player.status[STATUS_LEVITATING]) { - message("you are no longer levitating.", 0, 2); + message("you are no longer levitating.", 0); } if (player.status[STATUS_CONFUSED] > 0 && !--player.status[STATUS_CONFUSED]) { - message("you no longer feel confused.", 0, 2); + message("you no longer feel confused.", 0); } if (player.status[STATUS_NAUSEOUS] > 0 && !--player.status[STATUS_NAUSEOUS]) { - message("you feel less nauseous.", 0, 2); + message("you feel less nauseous.", 0); } if (player.status[STATUS_PARALYZED] > 0 && !--player.status[STATUS_PARALYZED]) { - message("you can move again.", 0, 2); + message("you can move again.", 0); } if (player.status[STATUS_HASTED] > 0 && !--player.status[STATUS_HASTED]) { player.movementSpeed = player.info.movementSpeed; player.attackSpeed = player.info.attackSpeed; synchronizePlayerTimeState(); - message("your supernatural speed fades.", 0, 2); + message("your supernatural speed fades.", 0); } if (player.status[STATUS_SLOWED] > 0 && !--player.status[STATUS_SLOWED]) { player.movementSpeed = player.info.movementSpeed; player.attackSpeed = player.info.attackSpeed; synchronizePlayerTimeState(); - message("your normal speed resumes.", 0, 2); + message("your normal speed resumes.", 0); } if (player.status[STATUS_WEAKENED] > 0 && !--player.status[STATUS_WEAKENED]) { player.weaknessAmount = 0; - message("strength returns to your muscles as the weakening toxin wears off.", 0, 2); + message("strength returns to your muscles as the weakening toxin wears off.", 0); updateEncumbrance(); } @@ -2026,7 +2026,7 @@ void decrementPlayerStatus() { } if (player.status[STATUS_IMMUNE_TO_FIRE] > 0 && !--player.status[STATUS_IMMUNE_TO_FIRE]) { - message("you no longer feel immune to fire.", 0, 2); + message("you no longer feel immune to fire.", 0); } if (player.status[STATUS_STUCK] && !cellHasTerrainFlag(player.xLoc, player.yLoc, T_ENTANGLES)) { @@ -2053,7 +2053,7 @@ void decrementPlayerStatus() { } if (player.status[STATUS_INVISIBLE] > 0 && !--player.status[STATUS_INVISIBLE]) { - message("you are no longer invisible.", 0, 2); + message("you are no longer invisible.", 0); } if (rogue.monsterSpawnFuse <= 0) { @@ -2159,7 +2159,7 @@ void manualSearch() { } else { // Do a final, larger-radius search on the fifth search in a row searchStrength = 160; - message("you finish your detailed search of the area.", 0, 2); + message("you finish your detailed search of the area.", 0); player.status[STATUS_SEARCHING] = 0; } @@ -2482,7 +2482,7 @@ void playerTurnEnded() { buf2); if (rogue.cautiousMode) { strcat(buf, "."); - message(buf, REQUIRE_ACKNOWLEDGMENT, 2); + message(buf, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } else { combatMessage(buf, 0); } @@ -2507,7 +2507,7 @@ void playerTurnEnded() { rogue.weapon->flags |= ITEM_RUNIC_HINTED; itemName(rogue.weapon, buf2, false, false, NULL); sprintf(buf, "the runes on your %s gleam balefully.", buf2); - messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 2); + messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } if (rogue.armor && rogue.armor->flags & ITEM_RUNIC && rogue.armor->enchant2 == A_IMMUNITY @@ -2517,7 +2517,7 @@ void playerTurnEnded() { rogue.armor->flags |= ITEM_RUNIC_HINTED; itemName(rogue.armor, buf2, false, false, NULL); sprintf(buf, "the runes on your %s glow protectively.", buf2); - messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT, 2); + messageWithColor(buf, &itemMessageColor, REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); } } } @@ -2585,11 +2585,11 @@ void playerTurnEnded() { turnsToShore = player.status[STATUS_LEVITATING] * 100 / player.movementSpeed; } if (turnsRequiredToShore == turnsToShore || turnsRequiredToShore + 1 == turnsToShore) { - message("better head back to solid ground!", REQUIRE_ACKNOWLEDGMENT, 2); + message("better head back to solid ground!", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); rogue.receivedLevitationWarning = true; } else if (turnsRequiredToShore > turnsToShore && turnsRequiredToShore < 10000) { - message("you're past the point of no return!", REQUIRE_ACKNOWLEDGMENT, 2); + message("you're past the point of no return!", REQUIRE_ACKNOWLEDGMENT | SPEECH_BLOCKS); rogue.receivedLevitationWarning = true; } } diff --git a/src/platform/platform.h b/src/platform/platform.h index 440da196..71c4c0aa 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -84,6 +84,7 @@ struct brogueConsole { */ enum graphicsModes (*setGraphicsMode)(enum graphicsModes mode); void (*playSpeech)(); + boolean (*toggleTTS)(); }; // defined in platform diff --git a/src/platform/platformdependent.c b/src/platform/platformdependent.c index b36243fb..b11f0dcf 100644 --- a/src/platform/platformdependent.c +++ b/src/platform/platformdependent.c @@ -267,9 +267,15 @@ enum graphicsModes setGraphicsMode(enum graphicsModes mode) { } } -void playSpeech(char *text, short priority) { +void toggleTTS() { + if (currentConsole.toggleTTS) { + currentConsole.toggleTTS(); + } +} + +void playSpeech(char *text, enum messageFlags flags) { if (currentConsole.playSpeech) { - currentConsole.playSpeech(text, priority); + currentConsole.playSpeech(text, flags); } } diff --git a/src/platform/sdl2-platform.c b/src/platform/sdl2-platform.c index d60bcf6d..474ea7f5 100644 --- a/src/platform/sdl2-platform.c +++ b/src/platform/sdl2-platform.c @@ -21,6 +21,12 @@ static struct keypair remapping[MAX_REMAPS]; static size_t nremaps = 0; static enum graphicsModes showGraphics = TEXT_GRAPHICS; +#ifdef BROGUE_SPEECH + static boolean useTTS = true; +#else + static boolean useTTS = false; +#endif + static rogueEvent lastEvent; static speechData lastSpeech; @@ -152,20 +158,25 @@ static boolean audioInit() { static void _playSpeech( char *text, - short priority + enum messageFlags flags ) { - if (priority >= lastSpeech.priority) { - espeak_Cancel(); - } else { + if (!useTTS) { + return; + } + long priority = flags & (NO_SPEECH | ZERO_SPEECH | ONE_SPEECH | TWO_SPEECH | THREE_SPEECH); + if (lastSpeech.flags & SPEECH_BLOCKS) { espeak_Synchronize(); + } else if (priority >= lastSpeech.priority) { + espeak_Cancel(); } // remove any escape codes from the text int i, j; char sanitizedMessage[90] = ""; + color white; for(i = 0, j = 0; i < strlen(text); i++) { - while (text[i] == COLOR_ESCAPE) { - i += 4; + if (text[i] == COLOR_ESCAPE) { + i = decodeMessageColor(text, i, &white); } if(i >= strlen(text)) { @@ -175,18 +186,21 @@ static void _playSpeech( sanitizedMessage[j++]= text[i]; } printf(sanitizedMessage); - espeak_Synth( - sanitizedMessage, - strlen(sanitizedMessage), - 0, - 0, - 0, - espeakCHARS_UTF8, - NULL, - NULL - ); + if (strlen(sanitizedMessage) > 0) { + espeak_Synth( + sanitizedMessage, + strlen(sanitizedMessage), + 0, + 0, + 0, + espeakCHARS_UTF8, + NULL, + NULL + ); + } // TODO: mark interruptable messages with unique_identifier lastSpeech.priority = priority; + lastSpeech.flags = flags; } @@ -474,6 +488,13 @@ static enum graphicsModes _setGraphicsMode(enum graphicsModes mode) { return mode; } +static boolean _toggleTTS() { + useTTS = !useTTS; + if (useTTS) { + playSpeech("Speech enabled", ZERO_SPEECH); + } +} + struct brogueConsole sdlConsole = { _gameLoop, @@ -485,5 +506,6 @@ struct brogueConsole sdlConsole = { NULL, _takeScreenshot, _setGraphicsMode, + .toggleTTS = _toggleTTS, .playSpeech = _playSpeech };