diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9b3bc7715..dab39589c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -149,6 +149,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 k_mapuser.c k_powerup.cpp k_hitlag.c + k_dialogue.cpp music.cpp music_manager.cpp ) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 1939c1d2d..2507f26eb 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -43,6 +43,8 @@ #include "../k_podium.h" #include "../k_bot.h" #include "../z_zone.h" +#include "../r_draw.h" +#include "../k_dialogue.hpp" #include "call-funcs.hpp" @@ -663,6 +665,46 @@ bool CallFunc_CameraWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: return true; // Execution interrupted } +/*-------------------------------------------------- + bool CallFunc_DialogueWaitDismiss(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Pauses the thread until the current + dialogue box is dismissed. +--------------------------------------------------*/ +bool CallFunc_DialogueWaitDismiss(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + (void)argV; + (void)argC; + + thread->state = { + ACSVM::ThreadState::WaitTag, + 0, + ACS_TAGTYPE_DIALOGUE + }; + + return true; // Execution interrupted +} + +/*-------------------------------------------------- + bool CallFunc_DialogueWaitText(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Pauses the thread until the current + dialogue box finishes rendering its text. +--------------------------------------------------*/ +bool CallFunc_DialogueWaitText(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + (void)argV; + (void)argC; + + thread->state = { + ACSVM::ThreadState::WaitTag, + 1, + ACS_TAGTYPE_DIALOGUE + }; + + return true; // Execution interrupted +} + /*-------------------------------------------------- bool CallFunc_ChangeFloor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) @@ -1856,6 +1898,98 @@ bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word return false; } +/*-------------------------------------------------- + bool CallFunc_DialogueSetSpeaker(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Set the dialogue speaker to a skin. +--------------------------------------------------*/ +bool CallFunc_DialogueSetSpeaker(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + ACSVM::MapScope *map = nullptr; + + ACSVM::String *skinStr = nullptr; + const char *skinName = nullptr; + + int spriteFrame = 0; + + (void)argC; + + map = thread->scopeMap; + + skinStr = map->getString(argV[0]); + skinName = skinStr->str; + + spriteFrame = argV[1]; + + g_dialogue.SetSpeaker(skinName, spriteFrame); + return false; +} + +/*-------------------------------------------------- + bool CallFunc_DialogueSetCustomSpeaker(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Set the dialogue speaker to specific graphics. +--------------------------------------------------*/ +bool CallFunc_DialogueSetCustomSpeaker(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + ACSVM::MapScope *map = nullptr; + + ACSVM::String *nametagStr = nullptr; + const char *nametag = nullptr; + + ACSVM::String *patchStr = nullptr; + const char *patchName = nullptr; + + ACSVM::String *colorStr = nullptr; + const char *colorName = nullptr; + skincolornum_t colorID = SKINCOLOR_NONE; + UINT8 *colormap = nullptr; + + (void)argC; + + map = thread->scopeMap; + + nametagStr = map->getString(argV[0]); + nametag = nametagStr->str; + + patchStr = map->getString(argV[1]); + patchName = patchStr->str; + + colorStr = map->getString(argV[1]); + colorName = colorStr->str; + + if (ACS_GetColorFromString(colorName, &colorID) == true) + { + colormap = R_GetTranslationColormap(TC_DEFAULT, colorID, GTC_CACHE); + } + + g_dialogue.SetSpeaker(nametag, patchName, colormap); + return false; +} + +/*-------------------------------------------------- + bool CallFunc_DialogueNewText(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) + + Change the current dialogue text. +--------------------------------------------------*/ +bool CallFunc_DialogueNewText(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) +{ + ACSVM::MapScope *map = nullptr; + + ACSVM::String *textStr = nullptr; + const char *text = nullptr; + + (void)argC; + + map = thread->scopeMap; + + textStr = map->getString(argV[0]); + text = textStr->str; + + g_dialogue.NewText(text); + return false; +} + /*-------------------------------------------------- bool CallFunc_Get/SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC) diff --git a/src/acs/call-funcs.hpp b/src/acs/call-funcs.hpp index bb9aa23b5..49f2fa9fa 100644 --- a/src/acs/call-funcs.hpp +++ b/src/acs/call-funcs.hpp @@ -42,6 +42,8 @@ bool CallFunc_ThingCount(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM:: bool CallFunc_TagWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_PolyWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_CameraWait(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_DialogueWaitDismiss(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_DialogueWaitText(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_ChangeFloor(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_ChangeCeiling(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_LineSide(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); @@ -88,6 +90,10 @@ bool CallFunc_SetLineRenderStyle(ACSVM::Thread *thread, const ACSVM::Word *argV, bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_AddBot(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_DialogueSetSpeaker(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_DialogueSetCustomSpeaker(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); +bool CallFunc_DialogueNewText(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); + bool CallFunc_GetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_SetLineProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); bool CallFunc_GetSideProperty(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC); diff --git a/src/acs/environment.cpp b/src/acs/environment.cpp index c886f3651..e99ed033a 100644 --- a/src/acs/environment.cpp +++ b/src/acs/environment.cpp @@ -27,6 +27,7 @@ #include "../w_wad.h" #include "../z_zone.h" #include "../p_local.h" +#include "../k_dialogue.hpp" #include "environment.hpp" #include "thread.hpp" @@ -171,6 +172,12 @@ Environment::Environment() addFuncDataACS0( 503, addCallFunc(CallFunc_SetLineRenderStyle)); addFuncDataACS0( 504, addCallFunc(CallFunc_MapWarp)); addFuncDataACS0( 505, addCallFunc(CallFunc_AddBot)); + + addFuncDataACS0( 600, addCallFunc(CallFunc_DialogueSetSpeaker)); + addFuncDataACS0( 601, addCallFunc(CallFunc_DialogueSetCustomSpeaker)); + addFuncDataACS0( 602, addCallFunc(CallFunc_DialogueNewText)); + addFuncDataACS0( 603, addCallFunc(CallFunc_DialogueWaitDismiss)); + addFuncDataACS0( 604, addCallFunc(CallFunc_DialogueWaitText)); } ACSVM::Thread *Environment::allocThread() @@ -284,6 +291,20 @@ bool Environment::checkTag(ACSVM::Word type, ACSVM::Word tag) return (camera->tracer == nullptr || P_MobjWasRemoved(camera->tracer) == true); } + + case ACS_TAGTYPE_DIALOGUE: + { + if (tag == 0) // cheeky reuse + { + // wait for dismissal + return (!g_dialogue.Active()); + } + else + { + // wait for text to finish + return (g_dialogue.TextDone()); + } + } } return true; diff --git a/src/acs/thread.hpp b/src/acs/thread.hpp index 3c146ddf6..97caf5447 100644 --- a/src/acs/thread.hpp +++ b/src/acs/thread.hpp @@ -52,6 +52,7 @@ enum acs_tagType_e ACS_TAGTYPE_POLYOBJ, ACS_TAGTYPE_SECTOR, ACS_TAGTYPE_CAMERA, + ACS_TAGTYPE_DIALOGUE, }; class ThreadInfo : public ACSVM::ThreadInfo diff --git a/src/info.c b/src/info.c index f21641943..0980ee74b 100644 --- a/src/info.c +++ b/src/info.c @@ -915,6 +915,7 @@ char spr2names[NUMPLAYERSPRITES][5] = "SIGN", // Finish signpost "XTRA", // Three Faces of Darkness + "TALK", // Dialogue }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; @@ -956,6 +957,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_SIGN 0, // SPR2_XTRA + 0, // SPR2_TALK }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) diff --git a/src/info.h b/src/info.h index 81e6554bc..8d7d35fef 100644 --- a/src/info.h +++ b/src/info.h @@ -1468,6 +1468,7 @@ typedef enum playersprite SPR2_DEAD, SPR2_SIGN, SPR2_XTRA, + SPR2_TALK, SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, diff --git a/src/k_dialogue.cpp b/src/k_dialogue.cpp new file mode 100644 index 000000000..886bd274b --- /dev/null +++ b/src/k_dialogue.cpp @@ -0,0 +1,280 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) by Sonic Team Junior +// Copyright (C) by Kart Krew +// Copyright (C) by Sally "TehRealSalt" Cochenour +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_dialogue.cpp +/// \brief Basic text prompts + +#include "k_dialogue.hpp" +#include "k_dialogue.h" + +#include +#include + +#include "info.h" +#include "g_game.h" +#include "v_video.h" +#include "r_draw.h" +#include "r_skins.h" +#include "z_zone.h" + +#include "acs/interface.h" + +using srb2::Dialogue; + +void Dialogue::SetSpeaker(void) +{ + // Unset speaker + speaker.clear(); + portrait = nullptr; + portraitColormap = nullptr; +} + +void Dialogue::SetSpeaker(std::string skinName, int portraitID) +{ + // Set speaker based on a skin + int skinID = -1; + + if (!skinName.empty()) + { + skinID = R_SkinAvailable(skinName.c_str()); + } + + if (skinID >= 0 && skinID < numskins) + { + const skin_t *skin = &skins[skinID]; + const spritedef_t *sprdef = &skin->sprites[SPR2_TALK]; + + if (sprdef->numframes > 0) + { + portraitID %= sprdef->numframes; + } + + const spriteframe_t *sprframe = &sprdef->spriteframes[portraitID]; + + speaker = skin->realname; + portrait = static_cast( W_CachePatchNum(sprframe->lumppat[0], PU_CACHE) ); + portraitColormap = R_GetTranslationColormap(skinID, static_cast(skin->prefcolor), GTC_CACHE); + } + else + { + SetSpeaker(); + } +} + +void Dialogue::SetSpeaker(std::string customName, std::string customPatch, UINT8 *customColormap) +{ + // Set custom speaker + speaker = customName; + + if (speaker.empty()) + { + portrait = nullptr; + portraitColormap = nullptr; + return; + } + + portrait = static_cast( W_CachePatchName(customPatch.c_str(), PU_CACHE) ); + portraitColormap = customColormap; +} + +void Dialogue::NewText(std::string newText) +{ + text.clear(); + + textDest = newText; + std::reverse(textDest.begin(), textDest.end()); + + textTimer = kTextPunctPause; + textSpeed = kTextSpeedDefault; + textDone = false; +} + +bool Dialogue::Active(void) +{ + return (!speaker.empty()); +} + +bool Dialogue::TextDone(void) +{ + return textDone; +} + +void Dialogue::WriteText(void) +{ + textTimer -= textSpeed; + + while (textTimer <= 0 && !textDest.empty()) + { + char c = textDest.back(); + text.push_back(c); + + if (c == '.' || c == '!' || c == '?') + { + // slow down for punctuation + textTimer += kTextPunctPause; + } + else + { + textTimer += FRACUNIT; + } + + textDest.pop_back(); + } + + textDone = (textTimer <= 0 && textDest.empty()); +} + +void Dialogue::CompleteText(void) +{ + while (!textDest.empty()) + { + text.push_back( textDest.back() ); + textDest.pop_back(); + } + + textTimer = 0; + textDone = true; +} + +void Dialogue::Tick(void) +{ + if (Active() == false) + { + return; + } + + WriteText(); + + bool pressed = ( + ((players[serverplayer].cmd.buttons & BT_VOTE) == BT_VOTE) && + ((players[serverplayer].oldcmd.buttons & BT_VOTE) == 0) + ); + + if (pressed == true) + { + if (textDone) + { + SetSpeaker(); + } + else + { + CompleteText(); + } + } +} + +void Dialogue::UpdatePatches(void) +{ + if (bgPatch == nullptr) + { + bgPatch = static_cast(W_CachePatchName("TUTDIAG1", PU_HUDGFX) ); + } + + if (confirmPatch == nullptr) + { + confirmPatch = static_cast(W_CachePatchName("TUTDIAG2", PU_HUDGFX) ); + } +} + +void Dialogue::Draw(void) +{ + if (Active() == false) + { + return; + } + + UpdatePatches(); + + V_DrawFixedPatch( + 0, 0, + FRACUNIT, + V_SNAPTOTOP, + bgPatch, + nullptr + ); + + if (portrait != nullptr) + { + V_DrawFixedPatch( + 10 * FRACUNIT, 41 * FRACUNIT, + FRACUNIT, + V_SNAPTOTOP, + portrait, + portraitColormap + ); + } + + V_DrawString( + 45, 39, + V_SNAPTOTOP, + speaker.c_str() + ); + + V_DrawString( + 10, 3, + V_SNAPTOTOP, + text.c_str() + ); + + if (textDone) + { + V_DrawFixedPatch( + 304 * FRACUNIT, 7 * FRACUNIT, + FRACUNIT, + V_SNAPTOTOP, + confirmPatch, + nullptr + ); + } +} + +void Dialogue::Dismiss(void) +{ + if (Active() == false) + { + return; + } + + SetSpeaker(); + + text.clear(); + textDest.clear(); + + if (G_GamestateUsesLevel() == true && !script.empty()) + { + ACS_Execute(script.c_str(), nullptr, 0, nullptr); + } + + script.clear(); +} + +/* + Ideally, the Dialogue class would be on player_t instead of in global space + for full multiplayer compatibility, but right now it's only being used for + the tutorial, and I don't feel like writing network code. If you feel like + doing that, then you can remove g_dialogue entirely. +*/ + +Dialogue g_dialogue; + +void K_DismissDialogue(void) +{ + g_dialogue.Dismiss(); +} + +void K_DrawDialogue(void) +{ + g_dialogue.Draw(); +} + +void K_TickDialogue(void) +{ + g_dialogue.Tick(); +} diff --git a/src/k_dialogue.h b/src/k_dialogue.h new file mode 100644 index 000000000..6ec4c3dad --- /dev/null +++ b/src/k_dialogue.h @@ -0,0 +1,32 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) by Sonic Team Junior +// Copyright (C) by Kart Krew +// Copyright (C) by Sally "TehRealSalt" Cochenour +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_dialogue.h +/// \brief Basic text prompts + +#ifndef __K_DIALOGUE__ +#define __K_DIALOGUE__ + +#include "doomtype.h" +#include "doomdef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void K_DismissDialogue(void); +void K_DrawDialogue(void); +void K_TickDialogue(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //__K_DIALOGUE__ diff --git a/src/k_dialogue.hpp b/src/k_dialogue.hpp new file mode 100644 index 000000000..4601dd006 --- /dev/null +++ b/src/k_dialogue.hpp @@ -0,0 +1,77 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) by Sonic Team Junior +// Copyright (C) by Kart Krew +// Copyright (C) by Sally "TehRealSalt" Cochenour +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file k_dialogue.hpp +/// \brief Basic text prompts + +#ifndef __K_DIALOGUE_HPP__ +#define __K_DIALOGUE_HPP__ + +#include + +#include "doomdef.h" +#include "doomtype.h" +#include "typedef.h" +#include "v_video.h" + +namespace srb2 +{ + +class Dialogue +{ +private: + patch_t *bgPatch; + patch_t *confirmPatch; + + bool active; + + std::string speaker; + patch_t *portrait; + UINT8 *portraitColormap; + + std::string text; + std::string textDest; + + fixed_t textTimer; + fixed_t textSpeed; + bool textDone; + + bool freeze; + std::string script; + + void UpdatePatches(void); + + void WriteText(void); + void CompleteText(void); + +public: + static constexpr fixed_t kTextSpeedDefault = FRACUNIT; + static constexpr fixed_t kTextPunctPause = FRACUNIT * TICRATE * 3 / 5; + + void SetSpeaker(void); + void SetSpeaker(std::string skinName, int portraitID); + void SetSpeaker(std::string customName, std::string customPatch, UINT8 *customColormap); + + void NewText(std::string newText); + + bool Active(void); + bool TextDone(void); + + void Tick(void); + void Draw(void); + + void Dismiss(void); +}; + +}; // namespace srb2 + +extern srb2::Dialogue g_dialogue; + +#endif //__K_DIALOGUE_HPP__ diff --git a/src/p_setup.c b/src/p_setup.c index 07302c90b..b060b390a 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -105,6 +105,7 @@ #include "k_rank.h" #include "k_mapuser.h" #include "music.h" +#include "k_dialogue.h" // Replay names have time #if !defined (UNDER_CE) @@ -1282,7 +1283,6 @@ static void P_LoadSidedefs(UINT8 *data) case 425: // Calls P_SetMobjState on calling mobj case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 443: // Calls a named Lua function - case 459: // Control text prompt (named tag) case 461: // Spawns an object on the map based on texture offsets case 463: // Colorizes an object case 475: // ACS_Execute @@ -5994,25 +5994,6 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[3] = (lines[i].sidenum[1] != 0xffff) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : 0; lines[i].args[4] = !!(lines[i].flags & ML_NOSKEW); break; - case 459: //Control text prompt - lines[i].args[1] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; - lines[i].args[2] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; - if (lines[i].flags & ML_BLOCKPLAYERS) - lines[i].args[3] |= TMP_CLOSE; - if (lines[i].flags & ML_SKEWTD) - lines[i].args[3] |= TMP_RUNPOSTEXEC; - if (lines[i].flags & ML_TFERLINE) - lines[i].args[3] |= TMP_CALLBYNAME; - if (lines[i].flags & ML_NOSKEW) - lines[i].args[3] |= TMP_KEEPCONTROLS; - if (lines[i].flags & ML_MIDPEG) - lines[i].args[3] |= TMP_KEEPREALTIME; - /*if (lines[i].flags & ML_NOCLIMB) - lines[i].args[3] |= TMP_ALLPLAYERS; - if (lines[i].flags & ML_MIDSOLID) - lines[i].args[3] |= TMP_FREEZETHINKERS;*/ - lines[i].args[4] = (lines[i].sidenum[1] != 0xFFFF) ? sides[lines[i].sidenum[1]].textureoffset >> FRACBITS : tag; - break; case 460: //Award rings lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index 9e7336a14..c7b65dabf 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3366,13 +3366,10 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha } break; - case 437: // Disable Player Controls + case 437: // Toggle Player Controls if (mo && mo->player) { - UINT16 fractime = (UINT16)(args[0]); - if (fractime < 1) - fractime = 1; //instantly wears off upon leaving - mo->player->nocontrol = fractime; + mo->player->nocontrol = ((args[0] != 0) ? UINT16_MAX : 0); } break; @@ -4153,33 +4150,6 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha } break; - case 459: // Control Text Prompt - // console player only - if (mo && mo->player && P_IsLocalPlayer(mo->player)) - { - INT32 promptnum = max(0, args[1] - 1); - INT32 pagenum = max(0, args[2] - 1); - INT32 postexectag = abs(args[4]); - - boolean closetextprompt = (args[3] & TMP_CLOSE); - //boolean allplayers = (args[3] & TMP_ALLPLAYERS); - boolean runpostexec = (args[3] & TMP_RUNPOSTEXEC); - boolean blockcontrols = !(args[3] & TMP_KEEPCONTROLS); - boolean freezerealtime = !(args[3] & TMP_KEEPREALTIME); - //boolean freezethinkers = (args[3] & TMP_FREEZETHINKERS); - boolean callbynamedtag = (args[3] & TMP_CALLBYNAME); - - if (closetextprompt) - F_EndTextPrompt(false, false); - else - { - if (callbynamedtag && stringargs[0] && stringargs[0][0]) - F_GetPromptPageByNamedTag(stringargs[0], &promptnum, &pagenum); - F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); - } - } - break; - case 460: // Award rings { if (gametyperules & GTR_SPHERES) diff --git a/src/p_tick.c b/src/p_tick.c index 8e408e92b..b478a6668 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -43,6 +43,7 @@ #include "acs/interface.h" #include "k_objects.h" #include "music.h" +#include "k_dialogue.h" #ifdef PARANOIA #include "deh_tables.h" // MOBJTYPE_LIST @@ -1033,6 +1034,11 @@ void P_Ticker(boolean run) P_RunChaseCameras(); } + if (run) + { + K_TickDialogue(); + } + LUA_HOOK(PostThinkFrame); if (run) diff --git a/src/st_stuff.c b/src/st_stuff.c index c7166c414..75c556fd3 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -52,6 +52,7 @@ #include "k_zvote.h" #include "music.h" #include "i_sound.h" +#include "k_dialogue.h" UINT16 objectsdrawn = 0; @@ -1244,6 +1245,8 @@ static void ST_overlayDrawer(void) } K_DrawMidVote(); + + K_DrawDialogue(); } void ST_DrawDemoTitleEntry(void)