mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-03-09 12:46:19 +00:00
Merge branch 'dialogue-2' into 'master'
Dialogue 2 See merge request KartKrew/Kart!1421
This commit is contained in:
commit
3f596a24ba
20 changed files with 671 additions and 57 deletions
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
#include "../k_bot.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../music.h"
|
||||
#include "../r_draw.h"
|
||||
#include "../k_dialogue.hpp"
|
||||
|
||||
#include "call-funcs.hpp"
|
||||
|
||||
|
|
@ -664,6 +666,50 @@ 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;
|
||||
|
||||
g_dialogue.SetDismissable(true);
|
||||
|
||||
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;
|
||||
|
||||
g_dialogue.SetDismissable(false);
|
||||
|
||||
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)
|
||||
|
||||
|
|
@ -1858,6 +1904,84 @@ 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;
|
||||
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_ktalk;
|
||||
|
||||
(void)argC;
|
||||
|
||||
map = thread->scopeMap;
|
||||
|
||||
nametagStr = map->getString(argV[0]);
|
||||
nametag = nametagStr->str;
|
||||
|
||||
patchStr = map->getString(argV[1]);
|
||||
patchName = patchStr->str;
|
||||
patch = static_cast<patch_t *>( W_CachePatchName(patchName, PU_CACHE) );
|
||||
|
||||
colorStr = map->getString(argV[2]);
|
||||
colorName = colorStr->str;
|
||||
if (ACS_GetColorFromString(colorName, &colorID) == true)
|
||||
{
|
||||
colormap = R_GetTranslationColormap(TC_DEFAULT, colorID, GTC_CACHE);
|
||||
}
|
||||
|
||||
voiceStr = map->getString(argV[3]);
|
||||
voiceName = voiceStr->str;
|
||||
ACS_GetSFXFromString(voiceName, &voiceID);
|
||||
|
||||
g_dialogue.SetSpeaker(nametag, patch, colormap, voiceID);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
bool CallFunc_StopLevelExit(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC)
|
||||
|
||||
|
|
@ -1898,7 +2022,29 @@ bool CallFunc_ExitLevel(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::W
|
|||
|
||||
if (server)
|
||||
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -93,6 +95,10 @@ bool CallFunc_MusicPlay(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::W
|
|||
bool CallFunc_MusicStopAll(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Word argC);
|
||||
bool CallFunc_MusicRemap(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);
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
@ -176,6 +177,12 @@ Environment::Environment()
|
|||
addFuncDataACS0( 508, addCallFunc(CallFunc_MusicPlay));
|
||||
addFuncDataACS0( 509, addCallFunc(CallFunc_MusicStopAll));
|
||||
addFuncDataACS0( 510, addCallFunc(CallFunc_MusicRemap));
|
||||
|
||||
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()
|
||||
|
|
@ -289,6 +296,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;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ enum acs_tagType_e
|
|||
ACS_TAGTYPE_POLYOBJ,
|
||||
ACS_TAGTYPE_SECTOR,
|
||||
ACS_TAGTYPE_CAMERA,
|
||||
ACS_TAGTYPE_DIALOGUE,
|
||||
};
|
||||
|
||||
class ThreadInfo : public ACSVM::ThreadInfo
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6657,6 +6657,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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -1468,6 +1468,7 @@ typedef enum playersprite
|
|||
SPR2_DEAD,
|
||||
SPR2_SIGN,
|
||||
SPR2_XTRA,
|
||||
SPR2_TALK,
|
||||
|
||||
SPR2_FIRSTFREESLOT,
|
||||
SPR2_LASTFREESLOT = 0x7f,
|
||||
|
|
|
|||
350
src/k_dialogue.cpp
Normal file
350
src/k_dialogue.cpp
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
// 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 <string>
|
||||
#include <algorithm>
|
||||
|
||||
#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 "k_hud.h"
|
||||
|
||||
#include "v_draw.hpp"
|
||||
|
||||
#include "acs/interface.h"
|
||||
|
||||
using srb2::Dialogue;
|
||||
|
||||
void Dialogue::Init(void)
|
||||
{
|
||||
active = true;
|
||||
syllable = true;
|
||||
}
|
||||
|
||||
void Dialogue::SetSpeaker(void)
|
||||
{
|
||||
// Unset speaker
|
||||
speaker.clear();
|
||||
|
||||
portrait = nullptr;
|
||||
portraitColormap = nullptr;
|
||||
|
||||
voiceSfx = sfx_ktalk;
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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<patch_t *>( W_CachePatchNum(sprframe->lumppat[0], PU_CACHE) );
|
||||
portraitColormap = R_GetTranslationColormap(skinID, static_cast<skincolornum_t>(skin->prefcolor), GTC_CACHE);
|
||||
|
||||
voiceSfx = skin->soundsid[ S_sfx[sfx_ktalk].skinsound ];
|
||||
}
|
||||
else
|
||||
{
|
||||
SetSpeaker();
|
||||
}
|
||||
}
|
||||
|
||||
void Dialogue::SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice)
|
||||
{
|
||||
Init();
|
||||
|
||||
// Set custom speaker
|
||||
speaker = name;
|
||||
|
||||
if (speaker.empty())
|
||||
{
|
||||
portrait = nullptr;
|
||||
portraitColormap = nullptr;
|
||||
voiceSfx = sfx_ktalk;
|
||||
return;
|
||||
}
|
||||
|
||||
portrait = patch;
|
||||
portraitColormap = colormap;
|
||||
|
||||
voiceSfx = voice;
|
||||
}
|
||||
|
||||
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;
|
||||
std::reverse(textDest.begin(), textDest.end());
|
||||
|
||||
textTimer = kTextPunctPause;
|
||||
textSpeed = kTextSpeedDefault;
|
||||
textDone = false;
|
||||
}
|
||||
|
||||
bool Dialogue::Active(void)
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
bool Dialogue::TextDone(void)
|
||||
{
|
||||
return textDone;
|
||||
}
|
||||
|
||||
bool Dialogue::Dismissable(void)
|
||||
{
|
||||
return dismissable;
|
||||
}
|
||||
|
||||
void Dialogue::SetDismissable(bool value)
|
||||
{
|
||||
dismissable = value;
|
||||
}
|
||||
|
||||
void Dialogue::WriteText(void)
|
||||
{
|
||||
bool voicePlayed = false;
|
||||
|
||||
textTimer -= textSpeed;
|
||||
|
||||
while (textTimer <= 0 && !textDest.empty())
|
||||
{
|
||||
char c = textDest.back();
|
||||
text.push_back(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;
|
||||
}
|
||||
else
|
||||
{
|
||||
textTimer += FRACUNIT;
|
||||
}
|
||||
|
||||
textDest.pop_back();
|
||||
}
|
||||
|
||||
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())
|
||||
{
|
||||
text.push_back( textDest.back() );
|
||||
textDest.pop_back();
|
||||
}
|
||||
|
||||
textTimer = 0;
|
||||
textDone = true;
|
||||
}
|
||||
|
||||
void Dialogue::Tick(void)
|
||||
{
|
||||
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();
|
||||
|
||||
if (Dismissable() == true)
|
||||
{
|
||||
if (Pressed() == true)
|
||||
{
|
||||
if (TextDone())
|
||||
{
|
||||
Dismiss();
|
||||
}
|
||||
else
|
||||
{
|
||||
CompleteText();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Dialogue::Draw(void)
|
||||
{
|
||||
if (slide == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
srb2::Draw drawer =
|
||||
srb2::Draw(
|
||||
0, FixedToFloat(Easing_OutCubic(slide, -78 * FRACUNIT, 0))
|
||||
).flags(V_SNAPTOTOP);
|
||||
|
||||
drawer.patch("TUTDIAG1");
|
||||
|
||||
if (portrait != nullptr)
|
||||
{
|
||||
drawer
|
||||
.xy(10, 41)
|
||||
.colormap(portraitColormap)
|
||||
.patch(portrait);
|
||||
}
|
||||
|
||||
drawer
|
||||
.xy(45, 39)
|
||||
.font(srb2::Draw::Font::kConsole)
|
||||
.text( speaker.c_str() );
|
||||
|
||||
drawer
|
||||
.xy(10, 3)
|
||||
.font(srb2::Draw::Font::kConsole)
|
||||
.text( text.c_str() );
|
||||
|
||||
if (Dismissable())
|
||||
{
|
||||
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;
|
||||
text.clear();
|
||||
textDest.clear();
|
||||
}
|
||||
|
||||
void Dialogue::Unset(void)
|
||||
{
|
||||
Dismiss();
|
||||
SetSpeaker();
|
||||
}
|
||||
|
||||
/*
|
||||
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_UnsetDialogue(void)
|
||||
{
|
||||
g_dialogue.Unset();
|
||||
}
|
||||
|
||||
void K_DrawDialogue(void)
|
||||
{
|
||||
g_dialogue.Draw();
|
||||
}
|
||||
|
||||
void K_TickDialogue(void)
|
||||
{
|
||||
g_dialogue.Tick();
|
||||
}
|
||||
32
src/k_dialogue.h
Normal file
32
src/k_dialogue.h
Normal file
|
|
@ -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_UnsetDialogue(void);
|
||||
void K_DrawDialogue(void);
|
||||
void K_TickDialogue(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif //__K_DIALOGUE__
|
||||
88
src/k_dialogue.hpp
Normal file
88
src/k_dialogue.hpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// 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 <string>
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomtype.h"
|
||||
#include "typedef.h"
|
||||
#include "sounds.h"
|
||||
#include "v_video.h"
|
||||
|
||||
namespace srb2
|
||||
{
|
||||
|
||||
class Dialogue
|
||||
{
|
||||
private:
|
||||
patch_t *bgPatch;
|
||||
patch_t *confirmPatch;
|
||||
|
||||
std::string speaker;
|
||||
patch_t *portrait;
|
||||
UINT8 *portraitColormap;
|
||||
sfxenum_t voiceSfx;
|
||||
|
||||
std::string text;
|
||||
std::string textDest;
|
||||
|
||||
bool active;
|
||||
fixed_t slide;
|
||||
|
||||
fixed_t textTimer;
|
||||
fixed_t textSpeed;
|
||||
bool textDone;
|
||||
bool syllable;
|
||||
|
||||
bool dismissable;
|
||||
|
||||
void Init(void);
|
||||
//void Unset(void);
|
||||
|
||||
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;
|
||||
static constexpr fixed_t kSlideSpeed = FRACUNIT / (TICRATE / 5);
|
||||
|
||||
void SetSpeaker(void);
|
||||
void SetSpeaker(std::string skinName, int portraitID);
|
||||
void SetSpeaker(std::string name, patch_t *patch, UINT8 *colormap, sfxenum_t voice);
|
||||
|
||||
void NewText(std::string newText);
|
||||
|
||||
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
|
||||
|
||||
extern srb2::Dialogue g_dialogue;
|
||||
|
||||
#endif //__K_DIALOGUE_HPP__
|
||||
|
|
@ -8250,7 +8250,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (player->stealingtimer == 0
|
||||
&& player->rocketsneakertimer
|
||||
&& onground == true)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -1260,7 +1261,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
|
||||
|
|
@ -5800,7 +5800,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;
|
||||
|
|
@ -5950,25 +5950,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;
|
||||
|
|
@ -8278,6 +8259,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++)
|
||||
|
|
|
|||
34
src/p_spec.c
34
src/p_spec.c
|
|
@ -3284,13 +3284,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;
|
||||
|
||||
|
|
@ -4071,33 +4068,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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -4335,15 +4335,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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue