diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 3250651d1a..dbee57a4e1 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1022,166 +1022,6 @@ public: } return Super::Responder(ev); } - - //============================================================================ - // - // Draw the backdrop, returns true if the text background should be dimmed - // - //============================================================================ - - virtual bool DrawBackdrop() - { - if (mCurNode->Backdrop.isValid()) - { - screen->DrawTexture(TexMan(mCurNode->Backdrop), 0, 0, DTA_320x200, true, TAG_DONE); - return false; - } - return true; - } - - //============================================================================ - // - // Draw the speaker text - // - //============================================================================ - - virtual void DrawSpeakerText(bool dimbg) - { - FString speakerName; - int x = 16 * screen->GetWidth() / 320; - int y = 16 * screen->GetHeight() / 200; - int linesize = (OptionSettings.mLinespacing+2) * CleanYfac; - - // Who is talking to you? - if (mCurNode->SpeakerName.IsNotEmpty()) - { - speakerName = mCurNode->SpeakerName; - if (speakerName[0] == '$') speakerName = GStrings(speakerName + 1); - } - else - { - speakerName = players[consoleplayer].ConversationNPC->GetTag("Person"); - } - - // Dim the screen behind the dialogue (but only if there is no backdrop). - if (dimbg) - { - int i = mDialogueLines->mCount; - screen->Dim(0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200, - 308 * screen->GetWidth() / 320 - 14 * screen->GetWidth() / 320, - speakerName.IsEmpty() ? linesize * i + 6 * CleanYfac - : linesize * i + 6 * CleanYfac + linesize * 3 / 2); - } - - if (speakerName.IsNotEmpty()) - { - screen->DrawText(SmallFont, CR_WHITE, x, y, speakerName, - DTA_CleanNoMove, true, TAG_DONE); - y += linesize * 3 / 2; - } - x = 24 * screen->GetWidth() / 320; - for (int i = 0; i < mDialogueLines->mCount; ++i) - { - screen->DrawText(SmallFont, CR_UNTRANSLATED, x, y, mDialogueLines->mBroken[i].Text, - DTA_CleanNoMove, true, TAG_DONE); - y += linesize; - } - } - - - virtual void DrawReplies() - { - // Dim the screen behind the PC's choices. - screen->Dim(0, 0.45f, (24 - 160) * CleanXfac + screen->GetWidth() / 2, - (mYpos - 2 - 100) * CleanYfac + screen->GetHeight() / 2, - 272 * CleanXfac, - MIN(mResponseLines.Size() * OptionSettings.mLinespacing + 4, 200 - mYpos) * CleanYfac); - - int y = mYpos; - int fontheight = OptionSettings.mLinespacing; - - int response = 0; - for (unsigned i = 0; i < mResponseLines.Size(); i++, y += fontheight) - { - int width = SmallFont->StringWidth(mResponseLines[i]); - int x = 64; - - screen->DrawText(SmallFont, CR_GREEN, x, y, mResponseLines[i], DTA_Clean, true, TAG_DONE); - - if (i == mResponses[response]) - { - char tbuf[16]; - - response++; - mysnprintf(tbuf, countof(tbuf), "%d.", response); - x = 50 - SmallFont->StringWidth(tbuf); - screen->DrawText(SmallFont, CR_GREY, x, y, tbuf, DTA_Clean, true, TAG_DONE); - - if (response == mSelection + 1) - { - int color = ((MenuTime % 8) < 4) || CurrentMenu != this ? CR_RED : CR_GREY; - - x = (50 + 3 - 160) * CleanXfac + screen->GetWidth() / 2; - int yy = (y + fontheight / 2 - 5 - 100) * CleanYfac + screen->GetHeight() / 2; - screen->DrawText(ConFont, color, x, yy, "\xd", - DTA_CellX, 8 * CleanXfac, - DTA_CellY, 8 * CleanYfac, - TAG_DONE); - } - } - } - } - - virtual void DrawGold() - { - if (mShowGold) - { - auto cointype = PClass::FindActor("Coin"); - if (cointype) - { - AInventory *coin = players[consoleplayer].ConversationPC->FindInventory(cointype); - char goldstr[32]; - - mysnprintf(goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0); - screen->DrawText(SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true, - DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE); - screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon), - 3, 190, DTA_320x200, true, - DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE); - screen->DrawText(SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE); - screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon), - 2, 189, DTA_320x200, true, TAG_DONE); - } - } - - } - - //============================================================================ - // - // DrawConversationMenu - // - //============================================================================ - - void Drawer() - { - if (mCurNode == NULL) - { - Close (); - return; - } - - // [CW] Freeze the game depending on MAPINFO options. - if (ConversationPauseTic < gametic && !multiplayer && !(level.flags2 & LEVEL2_CONV_SINGLE_UNFREEZE)) - { - menuactive = MENU_On; - } - - bool dimbg = DrawBackdrop(); - DrawSpeakerText(dimbg); - DrawReplies(); - DrawGold(); - } - }; IMPLEMENT_CLASS(DConversationMenu, true, false) @@ -1316,7 +1156,6 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang // And open the menu M_StartControlPanel (false); M_ActivateMenu(cmenu); - ConversationPauseTic = gametic + 20; menuactive = MENU_OnNoPause; } } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index cbe913fa36..528431575a 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -23,6 +23,7 @@ #include "zscript/menu/textentermenu.txt" #include "zscript/menu/videomenu.txt" #include "zscript/menu/readthis.txt" +#include "zscript/menu/conversationmenu.txt" #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" diff --git a/wadsrc/static/zscript/menu/conversationmenu.txt b/wadsrc/static/zscript/menu/conversationmenu.txt new file mode 100644 index 0000000000..474fd50f2a --- /dev/null +++ b/wadsrc/static/zscript/menu/conversationmenu.txt @@ -0,0 +1,247 @@ +/* +** conversationmenu.txt +** The Strife dialogue display +** +**--------------------------------------------------------------------------- +** Copyright 2010-2017 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +struct StrifeDialogueNode native +{ + native Class DropType; + native int ThisNodeNum; + native int ItemCheckNode; + + native Class SpeakerType; + native String SpeakerName; + native Sound SpeakerVoice; + native TextureID Backdrop; + native String Dialogue; + native String Goodbye; + + native StrifeDialogueReply Children; +} + +// FStrifeDialogueReply holds responses the player can give to the NPC +struct StrifeDialogueReply native +{ + native StrifeDialogueReply Next; + native Class GiveType; + native int ActionSpecial; + native int Args[5]; + native int PrintAmount; + native String Reply; + native String QuickYes; + native String QuickNo; + native String LogString; + native int NextNode; // index into StrifeDialogues + native int LogNumber; + native bool NeedsGold; +} + + +class ConversationMenu : Menu native +{ + native String mSpeaker; + native BrokenLines mDialogueLines; + native Array mResponseLines; + native Array mResponses; + native bool mShowGold; + native StrifeDialogueNode mCurNode; + native int mYpos; + native PlayerInfo mPlayer; + native int mSelection; + + //ConversationPauseTic = gametic + 20; + + //============================================================================ + // + // Draw the backdrop, returns true if the text background should be dimmed + // + //============================================================================ + + virtual bool DrawBackdrop() + { + if (mCurNode.Backdrop.isValid()) + { + screen.DrawTexture(mCurNode.Backdrop, false, 0, 0, DTA_320x200, true); + return false; + } + return true; + } + + //============================================================================ + // + // Draw the speaker text + // + //============================================================================ + + virtual void DrawSpeakerText(bool dimbg) + { + String speakerName; + int linesize = OptionMenuSettings.mLinespacing * CleanYfac; + int cnt = mDialogueLines.Count(); + + // Who is talking to you? + if (mCurNode.SpeakerName.Length() > 0) + { + speakerName = Stringtable.Localize(mCurNode.SpeakerName); + } + else + { + speakerName = players[consoleplayer].ConversationNPC.GetTag("Person"); + } + + + // Dim the screen behind the dialogue (but only if there is no backdrop). + if (dimbg) + { + int x = 14 * screen.GetWidth() / 320; + int y = 13 * screen.GetHeight() / 200; + int w = 294 * screen.GetWidth() / 320; + int h = linesize * cnt + 6 * CleanYfac; + if (speakerName.Length() > 0) h += linesize * 3 / 2; + screen.Dim(0, 0.45f, x, y, w, h); + } + + int x = 16 * screen.GetWidth() / 320; + int y = 16 * screen.GetHeight() / 200; + + if (speakerName.Length() > 0) + { + screen.DrawText(SmallFont, Font.CR_WHITE, x, y, speakerName, DTA_CleanNoMove, true); + y += linesize * 3 / 2; + } + x = 24 * screen.GetWidth() / 320; + for (int i = 0; i < cnt; ++i) + { + screen.DrawText(SmallFont, Font.CR_UNTRANSLATED, x, y, mDialogueLines.StringAt(i), DTA_CleanNoMove, true); + y += linesize; + } + } + + + //============================================================================ + // + // Draw the replies + // + //============================================================================ + + virtual void DrawReplies() + { + // Dim the screen behind the PC's choices. + screen.Dim(0, 0.45, (24 - 160) * CleanXfac + screen.GetWidth() / 2, (mYpos - 2 - 100) * CleanYfac + screen.GetHeight() / 2, + 272 * CleanXfac, MIN(mResponseLines.Size() * OptionMenuSettings.mLinespacing + 4, 200 - mYpos) * CleanYfac); + + int y = mYpos; + int fontheight = OptionMenuSettings.mLinespacing; + + int response = 0; + for (int i = 0; i < mResponseLines.Size(); i++) + { + int width = SmallFont.StringWidth(mResponseLines[i]); + int x = 64; + + screen.DrawText(SmallFont, Font.CR_GREEN, x, y, mResponseLines[i], DTA_Clean, true); + + if (i == mResponses[response]) + { + String tbuf; + + response++; + tbuf = String.Format("%d.", response); + x = 50 - SmallFont.StringWidth(tbuf); + screen.DrawText(SmallFont, Font.CR_GREY, x, y, tbuf, DTA_Clean, true); + + if (response == mSelection + 1) + { + int colr = ((MenuTime() % 8) < 4) || GetCurrentMenu() != self ? Font.CR_RED : Font.CR_GREY; + + x = (50 + 3 - 160) * CleanXfac + screen.GetWidth() / 2; + int yy = (y + fontheight / 2 - 5 - 100) * CleanYfac + screen.GetHeight() / 2; + screen.DrawText(ConFont, colr, x, yy, "\xd", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); + } + } + y += fontheight; + } + } + + virtual void DrawGold() + { + if (mShowGold) + { + let coin = players[consoleplayer].ConversationPC.FindInventory("Coin"); + let icon = GetDefaultByType("Coin").Icon; + let goldstr = String.Format("%d", coin != NULL ? coin.Amount : 0); + screen.DrawText(SmallFont, Font.CR_GRAY, 21, 191, goldstr, DTA_320x200, true, DTA_FillColor, 0, DTA_Alpha, HR_SHADOW); + screen.DrawTexture(icon, false, 3, 190, DTA_320x200, true, DTA_FillColor, 0, DTA_Alpha, HR_SHADOW); + screen.DrawText(SmallFont, Font.CR_GRAY, 20, 190, goldstr, DTA_320x200, true); + screen.DrawTexture(icon, false, 2, 189, DTA_320x200, true); + } + + } + + //============================================================================ + // + // DrawConversationMenu + // + //============================================================================ + + override void Drawer() + { + if (mCurNode == NULL) + { + Close (); + return; + } + + bool dimbg = DrawBackdrop(); + DrawSpeakerText(dimbg); + DrawReplies(); + DrawGold(); + } + + + //============================================================================ + // + // + // + //============================================================================ + + override void Ticker() + { + // will be reactivated later. + // [CW] Freeze the game depending on MAPINFO options. + //if (ConversationPauseTic < gametic && !multiplayer && !level.no_dlg_freeze) + { + menuactive = Menu.On; + } + } + +}