This commit is contained in:
Rachael Alexanderson 2017-02-19 05:26:51 -05:00
commit 75b81381f6
3 changed files with 95 additions and 41 deletions

View file

@ -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);

View file

@ -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;
} }

View file

@ -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);