mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-13 07:57:58 +00:00
This commit is contained in:
commit
75b81381f6
3 changed files with 95 additions and 41 deletions
|
@ -67,7 +67,7 @@ DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode,
|
||||||
{
|
{
|
||||||
auto c = PClass::FindClass("MessageBoxMenu");
|
auto c = PClass::FindClass("MessageBoxMenu");
|
||||||
auto p = c->CreateNew();
|
auto p = c->CreateNew();
|
||||||
VMValue params[] = { p, parent, FString(message), messagemode, playsound, action.GetIndex(), handler };
|
VMValue params[] = { p, parent, FString(message), messagemode, playsound, action.GetIndex(), reinterpret_cast<void*>(handler) };
|
||||||
|
|
||||||
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
auto f = dyn_cast<PFunction>(c->Symbols.FindSymbol("Init", false));
|
||||||
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0);
|
||||||
|
|
|
@ -113,6 +113,7 @@ static int ConversationMenuY;
|
||||||
|
|
||||||
static int ConversationPauseTic;
|
static int ConversationPauseTic;
|
||||||
static bool ShowGold;
|
static bool ShowGold;
|
||||||
|
static int StaticLastReply;
|
||||||
|
|
||||||
static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool include, int type);
|
static bool LoadScriptFile(int lumpnum, FileReader *lump, int numnodes, bool include, int type);
|
||||||
static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeakerType);
|
static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeakerType);
|
||||||
|
@ -689,6 +690,49 @@ static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SendConversationReply(int node, int reply)
|
||||||
|
{
|
||||||
|
switch (node)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
Net_WriteByte(DEM_CONVNULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case -2:
|
||||||
|
Net_WriteByte(DEM_CONVCLOSE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Net_WriteByte(DEM_CONVREPLY);
|
||||||
|
Net_WriteWord(node);
|
||||||
|
Net_WriteByte(reply);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
StaticLastReply = reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Needed for the conversion process.
|
||||||
|
class DBrokenLines : public DObject
|
||||||
|
{
|
||||||
|
DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject)
|
||||||
|
|
||||||
|
public:
|
||||||
|
FBrokenLines *mBroken;
|
||||||
|
unsigned int mCount;
|
||||||
|
|
||||||
|
DBrokenLines(FBrokenLines *broken, unsigned int count)
|
||||||
|
{
|
||||||
|
mBroken = broken;
|
||||||
|
mCount = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnDestroy() override
|
||||||
|
{
|
||||||
|
V_FreeBrokenLines(mBroken);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// The conversation menu
|
// The conversation menu
|
||||||
|
@ -699,17 +743,16 @@ class DConversationMenu : public DMenu
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(DConversationMenu, DMenu)
|
DECLARE_CLASS(DConversationMenu, DMenu)
|
||||||
|
|
||||||
|
public:
|
||||||
FString mSpeaker;
|
FString mSpeaker;
|
||||||
FBrokenLines *mDialogueLines;
|
DBrokenLines *mDialogueLines;
|
||||||
TArray<FString> mResponseLines;
|
TArray<FString> mResponseLines;
|
||||||
TArray<unsigned int> mResponses;
|
TArray<unsigned int> mResponses;
|
||||||
bool mShowGold;
|
bool mShowGold;
|
||||||
FStrifeDialogueNode *mCurNode;
|
FStrifeDialogueNode *mCurNode;
|
||||||
int mYpos;
|
int mYpos;
|
||||||
player_t *mPlayer;
|
player_t *mPlayer;
|
||||||
|
int mSelection;
|
||||||
public:
|
|
||||||
static int mSelection;
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -717,7 +760,7 @@ public:
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player)
|
DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player, int activereply)
|
||||||
{
|
{
|
||||||
mCurNode = CurNode;
|
mCurNode = CurNode;
|
||||||
mPlayer = player;
|
mPlayer = player;
|
||||||
|
@ -749,16 +792,24 @@ public:
|
||||||
{
|
{
|
||||||
toSay = ".";
|
toSay = ".";
|
||||||
}
|
}
|
||||||
mDialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac - 24*2, toSay);
|
unsigned int count;
|
||||||
|
auto bl = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac - 24*2, toSay, true, &count);
|
||||||
|
mDialogueLines = new DBrokenLines(bl, count);
|
||||||
|
|
||||||
|
mSelection = -1;
|
||||||
|
|
||||||
FStrifeDialogueReply *reply;
|
FStrifeDialogueReply *reply;
|
||||||
|
int r = -1;
|
||||||
int i,j;
|
int i,j;
|
||||||
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
|
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
|
||||||
{
|
{
|
||||||
|
r++;
|
||||||
if (ShouldSkipReply(reply, mPlayer))
|
if (ShouldSkipReply(reply, mPlayer))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (activereply == r) mSelection = i - 1;
|
||||||
|
|
||||||
mShowGold |= reply->NeedsGold;
|
mShowGold |= reply->NeedsGold;
|
||||||
|
|
||||||
const char *ReplyText = reply->Reply;
|
const char *ReplyText = reply->Reply;
|
||||||
|
@ -776,9 +827,14 @@ public:
|
||||||
{
|
{
|
||||||
mResponseLines.Push(ReplyLines[j].Text);
|
mResponseLines.Push(ReplyLines[j].Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
V_FreeBrokenLines (ReplyLines);
|
V_FreeBrokenLines (ReplyLines);
|
||||||
}
|
}
|
||||||
|
if (mSelection == -1)
|
||||||
|
{
|
||||||
|
mSelection = r < activereply ? r + 1 : 0;
|
||||||
|
}
|
||||||
const char *goodbyestr = CurNode->Goodbye;
|
const char *goodbyestr = CurNode->Goodbye;
|
||||||
if (*goodbyestr == 0)
|
if (*goodbyestr == 0)
|
||||||
{
|
{
|
||||||
|
@ -802,11 +858,8 @@ public:
|
||||||
mResponseLines.Push(FString(goodbyestr));
|
mResponseLines.Push(FString(goodbyestr));
|
||||||
|
|
||||||
// Determine where the top of the reply list should be positioned.
|
// Determine where the top of the reply list should be positioned.
|
||||||
i = OptionSettings.mLinespacing;
|
mYpos = MIN<int> (140, 192 - mResponseLines.Size() * OptionSettings.mLinespacing);
|
||||||
mYpos = MIN<int> (140, 192 - mResponseLines.Size() * i);
|
i = 44 + count * (OptionSettings.mLinespacing + 2);
|
||||||
for (i = 0; mDialogueLines[i].Width >= 0; ++i)
|
|
||||||
{ }
|
|
||||||
i = 44 + i * 10;
|
|
||||||
if (mYpos - 100 < i - screen->GetHeight() / CleanYfac / 2)
|
if (mYpos - 100 < i - screen->GetHeight() / CleanYfac / 2)
|
||||||
{
|
{
|
||||||
mYpos = i - screen->GetHeight() / CleanYfac / 2 + 100;
|
mYpos = i - screen->GetHeight() / CleanYfac / 2 + 100;
|
||||||
|
@ -830,7 +883,7 @@ public:
|
||||||
|
|
||||||
void OnDestroy() override
|
void OnDestroy() override
|
||||||
{
|
{
|
||||||
V_FreeBrokenLines(mDialogueLines);
|
mDialogueLines->Destroy();
|
||||||
mDialogueLines = NULL;
|
mDialogueLines = NULL;
|
||||||
I_SetMusicVolume (1.f);
|
I_SetMusicVolume (1.f);
|
||||||
Super::OnDestroy();
|
Super::OnDestroy();
|
||||||
|
@ -841,6 +894,25 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetReplyNum()
|
||||||
|
{
|
||||||
|
assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size());
|
||||||
|
assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode);
|
||||||
|
|
||||||
|
// This is needed because mSelection represents the replies currently being displayed which will
|
||||||
|
// not match up with what's supposed to be selected if there are any hidden/skipped replies. [FishyClockwork]
|
||||||
|
FStrifeDialogueReply *reply = mCurNode->Children;
|
||||||
|
int replynum = mSelection;
|
||||||
|
for (int i = 0; i <= mSelection && reply != nullptr; reply = reply->Next)
|
||||||
|
{
|
||||||
|
if (ShouldSkipReply(reply, mPlayer))
|
||||||
|
replynum++;
|
||||||
|
else
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return replynum;
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -870,36 +942,21 @@ public:
|
||||||
}
|
}
|
||||||
else if (mkey == MKEY_Back)
|
else if (mkey == MKEY_Back)
|
||||||
{
|
{
|
||||||
Net_WriteByte (DEM_CONVNULL);
|
SendConversationReply(-1, GetReplyNum());
|
||||||
Close();
|
Close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (mkey == MKEY_Enter)
|
else if (mkey == MKEY_Enter)
|
||||||
{
|
{
|
||||||
|
int replynum = GetReplyNum();
|
||||||
if ((unsigned)mSelection >= mResponses.Size())
|
if ((unsigned)mSelection >= mResponses.Size())
|
||||||
{
|
{
|
||||||
Net_WriteByte(DEM_CONVCLOSE);
|
SendConversationReply(-1, replynum);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size());
|
|
||||||
assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode);
|
|
||||||
|
|
||||||
// This is needed because mSelection represents the replies currently being displayed which will
|
|
||||||
// not match up with what's supposed to be selected if there are any hidden/skipped replies. [FishyClockwork]
|
|
||||||
FStrifeDialogueReply *reply = mCurNode->Children;
|
|
||||||
int replynum = mSelection;
|
|
||||||
for (int i = 0; i <= mSelection && reply != nullptr; reply = reply->Next)
|
|
||||||
{
|
|
||||||
if (ShouldSkipReply(reply, mPlayer))
|
|
||||||
replynum++;
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
// Send dialogue and reply numbers across the wire.
|
// Send dialogue and reply numbers across the wire.
|
||||||
Net_WriteByte(DEM_CONVREPLY);
|
SendConversationReply(mCurNode->ThisNodeNum, replynum);
|
||||||
Net_WriteWord(mCurNode->ThisNodeNum);
|
|
||||||
Net_WriteByte(replynum);
|
|
||||||
}
|
}
|
||||||
Close();
|
Close();
|
||||||
return true;
|
return true;
|
||||||
|
@ -1020,9 +1077,7 @@ public:
|
||||||
// Dim the screen behind the dialogue (but only if there is no backdrop).
|
// Dim the screen behind the dialogue (but only if there is no backdrop).
|
||||||
if (!CurNode->Backdrop.isValid())
|
if (!CurNode->Backdrop.isValid())
|
||||||
{
|
{
|
||||||
int i;
|
int i = mDialogueLines->mCount;
|
||||||
for (i = 0; mDialogueLines[i].Width >= 0; ++i)
|
|
||||||
{ }
|
|
||||||
screen->Dim (0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200,
|
screen->Dim (0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200,
|
||||||
308 * screen->GetWidth() / 320 - 14 * screen->GetWidth () / 320,
|
308 * screen->GetWidth() / 320 - 14 * screen->GetWidth () / 320,
|
||||||
speakerName == NULL ? linesize * i + 6 * CleanYfac
|
speakerName == NULL ? linesize * i + 6 * CleanYfac
|
||||||
|
@ -1043,9 +1098,9 @@ public:
|
||||||
y += linesize * 3 / 2;
|
y += linesize * 3 / 2;
|
||||||
}
|
}
|
||||||
x = 24 * screen->GetWidth() / 320;
|
x = 24 * screen->GetWidth() / 320;
|
||||||
for (int i = 0; mDialogueLines[i].Width >= 0; ++i)
|
for (int i = 0; i < mDialogueLines->mCount; ++i)
|
||||||
{
|
{
|
||||||
screen->DrawText (SmallFont, CR_UNTRANSLATED, x, y, mDialogueLines[i].Text,
|
screen->DrawText (SmallFont, CR_UNTRANSLATED, x, y, mDialogueLines->mBroken[i].Text,
|
||||||
DTA_CleanNoMove, true, TAG_DONE);
|
DTA_CleanNoMove, true, TAG_DONE);
|
||||||
y += linesize;
|
y += linesize;
|
||||||
}
|
}
|
||||||
|
@ -1108,7 +1163,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
IMPLEMENT_CLASS(DConversationMenu, true, false)
|
IMPLEMENT_CLASS(DConversationMenu, true, false)
|
||||||
int DConversationMenu::mSelection; // needs to be preserved if the same dialogue is restarted
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
@ -1228,12 +1282,12 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
|
||||||
S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM);
|
S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM);
|
||||||
}
|
}
|
||||||
|
|
||||||
DConversationMenu *cmenu = new DConversationMenu(CurNode, pc->player);
|
DConversationMenu *cmenu = new DConversationMenu(CurNode, pc->player, StaticLastReply);
|
||||||
|
|
||||||
|
|
||||||
if (CurNode != PrevNode)
|
if (CurNode != PrevNode)
|
||||||
{ // Only reset the selection if showing a different menu.
|
{ // Only reset the selection if showing a different menu.
|
||||||
DConversationMenu::mSelection = 0;
|
StaticLastReply = 0;
|
||||||
PrevNode = CurNode;
|
PrevNode = CurNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ class MessageBoxMenu : Menu
|
||||||
mMouseLeft = 140;
|
mMouseLeft = 140;
|
||||||
mMouseY = 0x80000000;
|
mMouseY = 0x80000000;
|
||||||
int mr1 = 170 + SmallFont.StringWidth(Stringtable.Localize("$TXT_YES"));
|
int mr1 = 170 + SmallFont.StringWidth(Stringtable.Localize("$TXT_YES"));
|
||||||
int mr2 = 170 + SmallFont.StringWidth(Stringtable.Localize("TXT_NO"));
|
int mr2 = 170 + SmallFont.StringWidth(Stringtable.Localize("$TXT_NO"));
|
||||||
mMouseRight = MAX(mr1, mr2);
|
mMouseRight = MAX(mr1, mr2);
|
||||||
mParentMenu = parent;
|
mParentMenu = parent;
|
||||||
mMessage = SmallFont.BreakLines(message, 300);
|
mMessage = SmallFont.BreakLines(message, 300);
|
||||||
|
|
Loading…
Reference in a new issue