From 16e6aa423e87ae7b02867b53cedfbb511fe27b7e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 24 Aug 2023 17:28:53 -0400 Subject: [PATCH 1/6] Dialogue 2 --- src/CMakeLists.txt | 1 + src/acs/call-funcs.cpp | 134 +++++++++++++++++++ src/acs/call-funcs.hpp | 6 + src/acs/environment.cpp | 21 +++ src/acs/thread.hpp | 1 + src/info.c | 2 + src/info.h | 1 + src/k_dialogue.cpp | 280 ++++++++++++++++++++++++++++++++++++++++ src/k_dialogue.h | 32 +++++ src/k_dialogue.hpp | 77 +++++++++++ src/p_setup.c | 21 +-- src/p_spec.c | 34 +---- src/p_tick.c | 6 + src/st_stuff.c | 3 + 14 files changed, 567 insertions(+), 52 deletions(-) create mode 100644 src/k_dialogue.cpp create mode 100644 src/k_dialogue.h create mode 100644 src/k_dialogue.hpp 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) From ffda0974213c73e0750b992fa855b7527a8c670d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 25 Aug 2023 05:05:51 -0400 Subject: [PATCH 2/6] Fix no control toggle --- src/k_kart.c | 1 - src/p_setup.c | 2 +- src/p_spec.c | 2 +- src/p_user.c | 4 +--- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 193da3181..2a2f4c8f4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -8250,7 +8250,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - if (player->stealingtimer == 0 && player->rocketsneakertimer && onground == true) diff --git a/src/p_setup.c b/src/p_setup.c index b060b390a..89ff63d11 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -5844,7 +5844,7 @@ static void P_ConvertBinaryLinedefTypes(void) lines[i].args[1] = sides[lines[i].sidenum[0]].rowoffset >> FRACBITS; break; case 437: //Disable player control - lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS; + lines[i].args[0] = ((sides[lines[i].sidenum[0]].textureoffset >> FRACBITS) != 0); break; case 438: //Change object size lines[i].args[0] = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index c7b65dabf..bd8791484 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3369,7 +3369,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha case 437: // Toggle Player Controls if (mo && mo->player) { - mo->player->nocontrol = ((args[0] != 0) ? UINT16_MAX : 0); + mo->player->nocontrol = ((args[0] == 0) ? UINT16_MAX : 0); } break; diff --git a/src/p_user.c b/src/p_user.c index c199eea76..8882f7872 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4342,15 +4342,13 @@ void P_PlayerThink(player_t *player) if (!(--player->nocontrol)) { if (player->pflags & PF_FAULT) - { + { player->pflags &= ~PF_FAULT; player->mo->renderflags &= ~RF_DONTDRAW; player->mo->flags &= ~MF_NOCLIPTHING; } } } - else - player->nocontrol = 0; // Flash player after being hit. if (!(player->hyudorotimer // SRB2kart - fixes Hyudoro not flashing when it should. From 3009f1c106d9f460e1de1ef9f02c4d6bf1a46ee6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 25 Aug 2023 06:50:12 -0400 Subject: [PATCH 3/6] Small dialogue polish - Slide in from top - Fix chaining multiple dialogues with the same speaker not working - Unset when changing level - Sped up punctuation pause a bit --- src/acs/call-funcs.cpp | 4 + src/d_main.c | 3 + src/k_dialogue.cpp | 178 +++++++++++++++++++++++------------------ src/k_dialogue.h | 2 +- src/k_dialogue.hpp | 17 ++-- src/p_setup.c | 2 + 6 files changed, 123 insertions(+), 83 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index 2507f26eb..c688778bd 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -676,6 +676,8 @@ bool CallFunc_DialogueWaitDismiss(ACSVM::Thread *thread, const ACSVM::Word *argV (void)argV; (void)argC; + g_dialogue.SetDismissable(true); + thread->state = { ACSVM::ThreadState::WaitTag, 0, @@ -696,6 +698,8 @@ bool CallFunc_DialogueWaitText(ACSVM::Thread *thread, const ACSVM::Word *argV, A (void)argV; (void)argC; + g_dialogue.SetDismissable(false); + thread->state = { ACSVM::ThreadState::WaitTag, 1, diff --git a/src/d_main.c b/src/d_main.c index 9652f0d10..1028e192c 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -84,6 +84,7 @@ #include "k_vote.h" #include "k_serverstats.h" #include "music.h" +#include "k_dialogue.h" #ifdef HWRENDER #include "hardware/hw_main.h" // 3D View Rendering @@ -1012,6 +1013,8 @@ void D_ClearState(void) if (gamedata && gamedata->deferredsave) G_SaveGameData(); + K_UnsetDialogue(); + G_SetGamestate(GS_NULL); wipegamestate = GS_NULL; } diff --git a/src/k_dialogue.cpp b/src/k_dialogue.cpp index 886bd274b..b8190281b 100644 --- a/src/k_dialogue.cpp +++ b/src/k_dialogue.cpp @@ -21,13 +21,22 @@ #include "g_game.h" #include "v_video.h" #include "r_draw.h" +#include "m_easing.h" #include "r_skins.h" #include "z_zone.h" +#include "v_draw.hpp" + #include "acs/interface.h" using srb2::Dialogue; +void Dialogue::Init(void) +{ + active = true; + dismissable = false; +} + void Dialogue::SetSpeaker(void) { // Unset speaker @@ -38,9 +47,10 @@ void Dialogue::SetSpeaker(void) void Dialogue::SetSpeaker(std::string skinName, int portraitID) { + Init(); + // Set speaker based on a skin int skinID = -1; - if (!skinName.empty()) { skinID = R_SkinAvailable(skinName.c_str()); @@ -70,6 +80,8 @@ void Dialogue::SetSpeaker(std::string skinName, int portraitID) void Dialogue::SetSpeaker(std::string customName, std::string customPatch, UINT8 *customColormap) { + Init(); + // Set custom speaker speaker = customName; @@ -86,6 +98,15 @@ void Dialogue::SetSpeaker(std::string customName, std::string customPatch, UINT8 void Dialogue::NewText(std::string newText) { + Init(); + + newText = V_ScaledWordWrap( + 290 << FRACBITS, + FRACUNIT, FRACUNIT, FRACUNIT, + 0, HU_FONT, + newText.c_str() + ); + text.clear(); textDest = newText; @@ -98,7 +119,7 @@ void Dialogue::NewText(std::string newText) bool Dialogue::Active(void) { - return (!speaker.empty()); + return active; } bool Dialogue::TextDone(void) @@ -106,6 +127,16 @@ bool Dialogue::TextDone(void) return textDone; } +bool Dialogue::Dismissable(void) +{ + return dismissable; +} + +void Dialogue::SetDismissable(bool value) +{ + dismissable = value; +} + void Dialogue::WriteText(void) { textTimer -= textSpeed; @@ -145,114 +176,109 @@ void Dialogue::CompleteText(void) void Dialogue::Tick(void) { - if (Active() == false) + if (Active()) + { + if (slide < FRACUNIT) + { + slide += kSlideSpeed; + } + } + else + { + if (slide > 0) + { + slide -= kSlideSpeed; + + if (slide <= 0) + { + Unset(); + } + } + } + + slide = std::clamp(slide, 0, FRACUNIT); + + if (slide != FRACUNIT) { return; } WriteText(); - bool pressed = ( - ((players[serverplayer].cmd.buttons & BT_VOTE) == BT_VOTE) && - ((players[serverplayer].oldcmd.buttons & BT_VOTE) == 0) - ); - - if (pressed == true) + if (Dismissable() == true) { - if (textDone) + bool pressed = ( + ((players[serverplayer].cmd.buttons & BT_VOTE) == BT_VOTE) && + ((players[serverplayer].oldcmd.buttons & BT_VOTE) == 0) + ); + + if (pressed == true) { - SetSpeaker(); + if (TextDone()) + { + Dismiss(); + } + else + { + CompleteText(); + } } - 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) + if (slide == 0) { return; } - UpdatePatches(); + srb2::Draw drawer = + srb2::Draw( + 0, FixedToFloat(Easing_OutCubic(slide, -78 * FRACUNIT, 0)) + ).flags(V_SNAPTOTOP); - V_DrawFixedPatch( - 0, 0, - FRACUNIT, - V_SNAPTOTOP, - bgPatch, - nullptr - ); + drawer.patch("TUTDIAG1"); if (portrait != nullptr) { - V_DrawFixedPatch( - 10 * FRACUNIT, 41 * FRACUNIT, - FRACUNIT, - V_SNAPTOTOP, - portrait, - portraitColormap - ); + drawer + .xy(10, 41) + .colormap(portraitColormap) + .patch(portrait); } - V_DrawString( - 45, 39, - V_SNAPTOTOP, - speaker.c_str() - ); + drawer + .xy(45, 39) + .font(srb2::Draw::Font::kConsole) + .text( speaker.c_str() ); - V_DrawString( - 10, 3, - V_SNAPTOTOP, - text.c_str() - ); + drawer + .xy(10, 3) + .font(srb2::Draw::Font::kConsole) + .text( text.c_str() ); - if (textDone) + if (Dismissable() && TextDone() && Active()) { - V_DrawFixedPatch( - 304 * FRACUNIT, 7 * FRACUNIT, - FRACUNIT, - V_SNAPTOTOP, - confirmPatch, - nullptr - ); + drawer + .xy(304, 7) + .patch("TUTDIAG2"); } } void Dialogue::Dismiss(void) { - if (Active() == false) - { - return; - } - - SetSpeaker(); + active = false; + dismissable = false; text.clear(); textDest.clear(); +} - if (G_GamestateUsesLevel() == true && !script.empty()) - { - ACS_Execute(script.c_str(), nullptr, 0, nullptr); - } - - script.clear(); +void Dialogue::Unset(void) +{ + Dismiss(); + SetSpeaker(); } /* @@ -264,9 +290,9 @@ void Dialogue::Dismiss(void) Dialogue g_dialogue; -void K_DismissDialogue(void) +void K_UnsetDialogue(void) { - g_dialogue.Dismiss(); + g_dialogue.Unset(); } void K_DrawDialogue(void) diff --git a/src/k_dialogue.h b/src/k_dialogue.h index 6ec4c3dad..7b4f7437e 100644 --- a/src/k_dialogue.h +++ b/src/k_dialogue.h @@ -21,7 +21,7 @@ extern "C" { #endif -void K_DismissDialogue(void); +void K_UnsetDialogue(void); void K_DrawDialogue(void); void K_TickDialogue(void); diff --git a/src/k_dialogue.hpp b/src/k_dialogue.hpp index 4601dd006..02289fc29 100644 --- a/src/k_dialogue.hpp +++ b/src/k_dialogue.hpp @@ -30,8 +30,6 @@ private: patch_t *bgPatch; patch_t *confirmPatch; - bool active; - std::string speaker; patch_t *portrait; UINT8 *portraitColormap; @@ -39,21 +37,25 @@ private: std::string text; std::string textDest; + bool active; + fixed_t slide; + fixed_t textTimer; fixed_t textSpeed; bool textDone; - bool freeze; - std::string script; + bool dismissable; - void UpdatePatches(void); + void Init(void); + //void Unset(void); void WriteText(void); void CompleteText(void); public: static constexpr fixed_t kTextSpeedDefault = FRACUNIT; - static constexpr fixed_t kTextPunctPause = FRACUNIT * TICRATE * 3 / 5; + static constexpr fixed_t kTextPunctPause = (FRACUNIT * TICRATE * 2) / 5; + static constexpr fixed_t kSlideSpeed = FRACUNIT / (TICRATE / 5); void SetSpeaker(void); void SetSpeaker(std::string skinName, int portraitID); @@ -63,11 +65,14 @@ public: bool Active(void); bool TextDone(void); + bool Dismissable(void); + void SetDismissable(bool value); void Tick(void); void Draw(void); void Dismiss(void); + void Unset(void); }; }; // namespace srb2 diff --git a/src/p_setup.c b/src/p_setup.c index 89ff63d11..14fa88c42 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8299,6 +8299,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // Close text prompt before freeing the old level F_EndTextPrompt(false, true); + K_UnsetDialogue(); + LUA_InvalidateLevel(); for (ss = sectors; sectors+numsectors != ss; ss++) From 764010b3ab8d60fb9a3117d622b728004fad5867 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 25 Aug 2023 07:53:09 -0400 Subject: [PATCH 4/6] Implement talk sounds We're in Undertale --- src/acs/call-funcs.cpp | 15 ++++++++++++--- src/deh_tables.c | 1 + src/k_dialogue.cpp | 40 ++++++++++++++++++++++++++++++++++------ src/k_dialogue.hpp | 5 ++++- src/sounds.c | 1 + src/sounds.h | 2 ++ 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index c688778bd..f93946a94 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -1943,12 +1943,17 @@ bool CallFunc_DialogueSetCustomSpeaker(ACSVM::Thread *thread, const ACSVM::Word ACSVM::String *patchStr = nullptr; const char *patchName = nullptr; + patch_t *patch = nullptr; ACSVM::String *colorStr = nullptr; const char *colorName = nullptr; skincolornum_t colorID = SKINCOLOR_NONE; UINT8 *colormap = nullptr; + ACSVM::String *voiceStr = nullptr; + const char *voiceName = nullptr; + sfxenum_t voiceID = sfx_None; + (void)argC; map = thread->scopeMap; @@ -1958,16 +1963,20 @@ bool CallFunc_DialogueSetCustomSpeaker(ACSVM::Thread *thread, const ACSVM::Word patchStr = map->getString(argV[1]); patchName = patchStr->str; + patch = static_cast( W_CachePatchName(patchName, PU_CACHE) ); - colorStr = map->getString(argV[1]); + colorStr = map->getString(argV[2]); colorName = colorStr->str; - if (ACS_GetColorFromString(colorName, &colorID) == true) { colormap = R_GetTranslationColormap(TC_DEFAULT, colorID, GTC_CACHE); } - g_dialogue.SetSpeaker(nametag, patchName, colormap); + voiceStr = map->getString(argV[3]); + voiceName = voiceStr->str; + ACS_GetSFXFromString(voiceName, &voiceID); + + g_dialogue.SetSpeaker(nametag, patch, colormap, voiceID); return false; } diff --git a/src/deh_tables.c b/src/deh_tables.c index 0196e2086..e234782a7 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6677,6 +6677,7 @@ struct int_const_s const INT_CONST[] = { {"SKSKSLOW",SKSKSLOW}, // Overtake taunt {"SKSKHITM",SKSKHITM}, // Hit confirm taunt {"SKSKPOWR",SKSKPOWR}, // Power item taunt + {"SKSKTALK",SKSKTALK}, // Dialogue // 3D Floor/Fake Floor/FOF/whatever flags {"FOF_EXISTS",FOF_EXISTS}, ///< Always set, to check for validity. diff --git a/src/k_dialogue.cpp b/src/k_dialogue.cpp index b8190281b..c579daea2 100644 --- a/src/k_dialogue.cpp +++ b/src/k_dialogue.cpp @@ -18,11 +18,13 @@ #include #include "info.h" +#include "sounds.h" #include "g_game.h" #include "v_video.h" #include "r_draw.h" #include "m_easing.h" #include "r_skins.h" +#include "s_sound.h" #include "z_zone.h" #include "v_draw.hpp" @@ -35,14 +37,18 @@ void Dialogue::Init(void) { active = true; dismissable = false; + syllable = true; } void Dialogue::SetSpeaker(void) { // Unset speaker speaker.clear(); + portrait = nullptr; portraitColormap = nullptr; + + voiceSfx = sfx_None; } void Dialogue::SetSpeaker(std::string skinName, int portraitID) @@ -69,8 +75,11 @@ void Dialogue::SetSpeaker(std::string skinName, int portraitID) 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); + + voiceSfx = skin->soundsid[ S_sfx[sfx_ktalk].skinsound ]; } else { @@ -78,22 +87,25 @@ void Dialogue::SetSpeaker(std::string skinName, int portraitID) } } -void Dialogue::SetSpeaker(std::string customName, std::string customPatch, UINT8 *customColormap) +void Dialogue::SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice) { Init(); // Set custom speaker - speaker = customName; + speaker = name; if (speaker.empty()) { portrait = nullptr; portraitColormap = nullptr; + voiceSfx = sfx_None; return; } - portrait = static_cast( W_CachePatchName(customPatch.c_str(), PU_CACHE) ); - portraitColormap = customColormap; + portrait = patch; + portraitColormap = colormap; + + voiceSfx = voice; } void Dialogue::NewText(std::string newText) @@ -106,7 +118,7 @@ void Dialogue::NewText(std::string newText) 0, HU_FONT, newText.c_str() ); - + text.clear(); textDest = newText; @@ -139,6 +151,8 @@ void Dialogue::SetDismissable(bool value) void Dialogue::WriteText(void) { + bool voicePlayed = false; + textTimer -= textSpeed; while (textTimer <= 0 && !textDest.empty()) @@ -146,7 +160,21 @@ void Dialogue::WriteText(void) char c = textDest.back(); text.push_back(c); - if (c == '.' || c == '!' || c == '?') + if (voicePlayed == false + && std::isprint(c) + && c != ' ') + { + if (syllable) + { + S_StopSoundByNum(voiceSfx); + S_StartSound(nullptr, voiceSfx); + } + + syllable = !syllable; + voicePlayed = true; + } + + if (c == '.' || c == ',' || c == ';' || c == '!' || c == '?') { // slow down for punctuation textTimer += kTextPunctPause; diff --git a/src/k_dialogue.hpp b/src/k_dialogue.hpp index 02289fc29..553d2827f 100644 --- a/src/k_dialogue.hpp +++ b/src/k_dialogue.hpp @@ -19,6 +19,7 @@ #include "doomdef.h" #include "doomtype.h" #include "typedef.h" +#include "sounds.h" #include "v_video.h" namespace srb2 @@ -33,6 +34,7 @@ private: std::string speaker; patch_t *portrait; UINT8 *portraitColormap; + sfxenum_t voiceSfx; std::string text; std::string textDest; @@ -43,6 +45,7 @@ private: fixed_t textTimer; fixed_t textSpeed; bool textDone; + bool syllable; bool dismissable; @@ -59,7 +62,7 @@ public: void SetSpeaker(void); void SetSpeaker(std::string skinName, int portraitID); - void SetSpeaker(std::string customName, std::string customPatch, UINT8 *customColormap); + void SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice); void NewText(std::string newText); diff --git a/src/sounds.c b/src/sounds.c index 7e8560eb2..8b1ff2a84 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1439,6 +1439,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"kslow", false, 64, 32, -1, NULL, 0, SKSKSLOW, -1, LUMPERROR, ""}, {"khitem", false, 128, 32, -1, NULL, 0, SKSKHITM, -1, LUMPERROR, ""}, {"kgloat", false, 64, 48, -1, NULL, 0, SKSKPOWR, -1, LUMPERROR, ""}, + {"ktalk", false, 64, 48, -1, NULL, 0, SKSKTALK, -1, LUMPERROR, ""}, // skin sounds free slots to add sounds at run time (Boris HACK!!!) // initialized to NULL diff --git a/src/sounds.h b/src/sounds.h index 324066ac9..176dfc541 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -56,6 +56,7 @@ typedef enum SKSKSLOW, // Overtake taunt SKSKHITM, // Hit confirm taunt SKSKPOWR, // Power item taunt + SKSKTALK, NUMSKINSOUNDS } skinsound_t; @@ -1506,6 +1507,7 @@ typedef enum sfx_kslow, sfx_khitem, sfx_kgloat, + sfx_ktalk, // free slots for S_AddSoundFx() at run-time -------------------- sfx_freeslot0, From 71e068a8b683bcd97eac85b49108bdde1aac9162 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 25 Aug 2023 08:16:16 -0400 Subject: [PATCH 5/6] Display Z button --- src/k_dialogue.cpp | 42 +++++++++++++++++++++++++++++------------- src/k_dialogue.hpp | 3 +++ 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/k_dialogue.cpp b/src/k_dialogue.cpp index c579daea2..ee14cffbc 100644 --- a/src/k_dialogue.cpp +++ b/src/k_dialogue.cpp @@ -26,6 +26,7 @@ #include "r_skins.h" #include "s_sound.h" #include "z_zone.h" +#include "k_hud.h" #include "v_draw.hpp" @@ -36,7 +37,6 @@ using srb2::Dialogue; void Dialogue::Init(void) { active = true; - dismissable = false; syllable = true; } @@ -190,6 +190,19 @@ void Dialogue::WriteText(void) textDone = (textTimer <= 0 && textDest.empty()); } +bool Dialogue::Held(void) +{ + return ((players[serverplayer].cmd.buttons & BT_VOTE) == BT_VOTE); +} + +bool Dialogue::Pressed(void) +{ + return ( + ((players[serverplayer].cmd.buttons & BT_VOTE) == BT_VOTE) && + ((players[serverplayer].oldcmd.buttons & BT_VOTE) == 0) + ); +} + void Dialogue::CompleteText(void) { while (!textDest.empty()) @@ -235,12 +248,7 @@ void Dialogue::Tick(void) if (Dismissable() == true) { - bool pressed = ( - ((players[serverplayer].cmd.buttons & BT_VOTE) == BT_VOTE) && - ((players[serverplayer].oldcmd.buttons & BT_VOTE) == 0) - ); - - if (pressed == true) + if (Pressed() == true) { if (TextDone()) { @@ -286,19 +294,27 @@ void Dialogue::Draw(void) .font(srb2::Draw::Font::kConsole) .text( text.c_str() ); - if (Dismissable() && TextDone() && Active()) + if (Dismissable()) { - drawer - .xy(304, 7) - .patch("TUTDIAG2"); + if (TextDone()) + { + drawer + .xy(304, 7) + .patch("TUTDIAG2"); + } + + K_drawButton( + FloatToFixed(drawer.x() + 303), + FloatToFixed(drawer.y() + 39), + V_SNAPTOTOP, + kp_button_z[0], Held() + ); } } void Dialogue::Dismiss(void) { active = false; - dismissable = false; - text.clear(); textDest.clear(); } diff --git a/src/k_dialogue.hpp b/src/k_dialogue.hpp index 553d2827f..c3fb8dd5a 100644 --- a/src/k_dialogue.hpp +++ b/src/k_dialogue.hpp @@ -55,6 +55,9 @@ private: void WriteText(void); void CompleteText(void); + bool Pressed(void); + bool Held(void); + public: static constexpr fixed_t kTextSpeedDefault = FRACUNIT; static constexpr fixed_t kTextPunctPause = (FRACUNIT * TICRATE * 2) / 5; From e30ff926d8000d2d175e1433c2d1de6ace3214df Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 25 Aug 2023 13:15:50 -0400 Subject: [PATCH 6/6] Default voice to sfx_ktalk Someone just needs to put an actual sound for it in sounds.pk3 --- src/acs/call-funcs.cpp | 2 +- src/k_dialogue.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index f93946a94..8567a782c 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -1952,7 +1952,7 @@ bool CallFunc_DialogueSetCustomSpeaker(ACSVM::Thread *thread, const ACSVM::Word ACSVM::String *voiceStr = nullptr; const char *voiceName = nullptr; - sfxenum_t voiceID = sfx_None; + sfxenum_t voiceID = sfx_ktalk; (void)argC; diff --git a/src/k_dialogue.cpp b/src/k_dialogue.cpp index ee14cffbc..e75e18a4d 100644 --- a/src/k_dialogue.cpp +++ b/src/k_dialogue.cpp @@ -48,7 +48,7 @@ void Dialogue::SetSpeaker(void) portrait = nullptr; portraitColormap = nullptr; - voiceSfx = sfx_None; + voiceSfx = sfx_ktalk; } void Dialogue::SetSpeaker(std::string skinName, int portraitID) @@ -98,7 +98,7 @@ void Dialogue::SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfx { portrait = nullptr; portraitColormap = nullptr; - voiceSfx = sfx_None; + voiceSfx = sfx_ktalk; return; }