2017-02-19 11:28:05 +00:00
|
|
|
/*
|
|
|
|
** 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.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
2017-03-05 13:03:27 +00:00
|
|
|
struct StrifeDialogueNode native version("2.4")
|
2017-02-19 11:28:05 +00:00
|
|
|
{
|
|
|
|
native Class<Actor> DropType;
|
|
|
|
native int ThisNodeNum;
|
|
|
|
native int ItemCheckNode;
|
|
|
|
|
|
|
|
native Class<Actor> SpeakerType;
|
|
|
|
native String SpeakerName;
|
|
|
|
native Sound SpeakerVoice;
|
2017-02-19 13:21:49 +00:00
|
|
|
native String Backdrop;
|
2017-02-19 11:28:05 +00:00
|
|
|
native String Dialogue;
|
|
|
|
native String Goodbye;
|
|
|
|
|
|
|
|
native StrifeDialogueReply Children;
|
2018-01-13 11:13:38 +00:00
|
|
|
native Name MenuClassName;
|
|
|
|
native String UserData;
|
2017-02-19 11:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FStrifeDialogueReply holds responses the player can give to the NPC
|
2017-03-05 13:03:27 +00:00
|
|
|
struct StrifeDialogueReply native version("2.4")
|
2017-02-19 11:28:05 +00:00
|
|
|
{
|
|
|
|
native StrifeDialogueReply Next;
|
|
|
|
native Class<Actor> 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;
|
2017-02-19 12:07:49 +00:00
|
|
|
|
|
|
|
native bool ShouldSkipReply(PlayerInfo player);
|
2017-02-19 11:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-19 13:21:49 +00:00
|
|
|
class ConversationMenu : Menu
|
2017-02-19 11:28:05 +00:00
|
|
|
{
|
2017-02-19 13:21:49 +00:00
|
|
|
String mSpeaker;
|
|
|
|
BrokenLines mDialogueLines;
|
|
|
|
Array<String> mResponseLines;
|
|
|
|
Array<uint> mResponses;
|
|
|
|
bool mShowGold;
|
2019-07-27 07:35:45 +00:00
|
|
|
bool mHasBackdrop;
|
|
|
|
bool mConfineTextToBackdrop;
|
2017-02-19 13:21:49 +00:00
|
|
|
StrifeDialogueNode mCurNode;
|
|
|
|
int mYpos;
|
|
|
|
PlayerInfo mPlayer;
|
|
|
|
int mSelection;
|
|
|
|
int ConversationPauseTic;
|
2019-03-19 16:46:59 +00:00
|
|
|
int LineHeight;
|
2019-04-11 16:55:35 +00:00
|
|
|
int ReplyLineHeight;
|
|
|
|
Font displayFont;
|
2019-07-27 07:35:45 +00:00
|
|
|
int speechDisplayWidth;
|
2019-04-11 16:55:35 +00:00
|
|
|
int displayWidth;
|
|
|
|
int displayHeight;
|
|
|
|
int fontScale;
|
|
|
|
int refwidth;
|
|
|
|
int refheight;
|
2020-06-04 12:11:36 +00:00
|
|
|
Array<double> ypositions;
|
2017-02-19 13:21:49 +00:00
|
|
|
|
|
|
|
int SpeechWidth;
|
|
|
|
int ReplyWidth;
|
2017-02-19 11:28:05 +00:00
|
|
|
|
2017-02-19 12:07:49 +00:00
|
|
|
native static void SendConversationReply(int node, int reply);
|
|
|
|
|
2017-02-19 13:21:49 +00:00
|
|
|
const NUM_RANDOM_LINES = 10;
|
|
|
|
const NUM_RANDOM_GOODBYES = 3;
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
//
|
2019-07-27 07:35:45 +00:00
|
|
|
// returns the y position of the replies box for positioning the terminal response.
|
2017-02-19 13:21:49 +00:00
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
virtual int Init(StrifeDialogueNode CurNode, PlayerInfo player, int activereply)
|
|
|
|
{
|
|
|
|
mCurNode = CurNode;
|
|
|
|
mPlayer = player;
|
|
|
|
mShowGold = false;
|
|
|
|
ConversationPauseTic = gametic + 20;
|
|
|
|
DontDim = true;
|
2019-07-27 07:35:45 +00:00
|
|
|
|
|
|
|
let tex = TexMan.CheckForTexture (CurNode.Backdrop, TexMan.Type_MiscPatch);
|
|
|
|
mHasBackdrop = tex.isValid();
|
2019-08-09 13:22:52 +00:00
|
|
|
DontBlur = !mHasBackdrop;
|
2019-07-27 07:35:45 +00:00
|
|
|
|
2019-07-26 18:23:46 +00:00
|
|
|
if (!generic_ui && !dlg_vgafont)
|
2019-04-11 16:55:35 +00:00
|
|
|
{
|
|
|
|
displayFont = SmallFont;
|
|
|
|
displayWidth = CleanWidth;
|
|
|
|
displayHeight = CleanHeight;
|
|
|
|
fontScale = CleanXfac;
|
|
|
|
refwidth = 320;
|
|
|
|
refheight = 200;
|
|
|
|
ReplyWidth = 320-50-10;
|
|
|
|
SpeechWidth = screen.GetWidth()/CleanXfac - 24*2;
|
|
|
|
ReplyLineHeight = LineHeight = displayFont.GetHeight();
|
2019-07-27 07:35:45 +00:00
|
|
|
mConfineTextToBackdrop = false;
|
|
|
|
speechDisplayWidth = displayWidth;
|
2019-04-11 16:55:35 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
displayFont = NewSmallFont;
|
|
|
|
fontScale = (CleanXfac+1) / 2;
|
|
|
|
refwidth = 640;
|
|
|
|
refheight = 400;
|
|
|
|
ReplyWidth = 640-100-20;
|
2019-07-27 07:35:45 +00:00
|
|
|
displayWidth = screen.GetWidth() / fontScale;
|
|
|
|
displayHeight = screen.GetHeight() / fontScale;
|
|
|
|
let aspect = Screen.GetAspectRatio();
|
|
|
|
if (!mHasBackdrop || aspect <= 1.3334)
|
|
|
|
{
|
|
|
|
SpeechWidth = screen.GetWidth()/fontScale - (24*3 * CleanXfac / fontScale);
|
|
|
|
mConfineTextToBackdrop = false;
|
|
|
|
speechDisplayWidth = displayWidth;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-13 11:48:40 +00:00
|
|
|
speechDisplayWidth = int(Screen.GetHeight() * 1.3333 / fontScale);
|
|
|
|
SpeechWidth = speechDisplayWidth - (24*3 * CleanXfac / fontScale);
|
2019-07-27 07:35:45 +00:00
|
|
|
mConfineTextToBackdrop = true;
|
|
|
|
}
|
|
|
|
|
2019-04-11 16:55:35 +00:00
|
|
|
LineHeight = displayFont.GetHeight() + 2;
|
|
|
|
ReplyLineHeight = LineHeight * fontScale / CleanYfac;
|
|
|
|
}
|
2017-02-19 13:21:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
FormatSpeakerMessage();
|
|
|
|
return FormatReplies(activereply);
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
virtual int FormatReplies(int activereply)
|
|
|
|
{
|
|
|
|
mSelection = -1;
|
2017-02-19 12:07:49 +00:00
|
|
|
|
2017-02-19 13:21:49 +00:00
|
|
|
StrifeDialogueReply reply;
|
|
|
|
int r = -1;
|
|
|
|
int i = 1,j;
|
|
|
|
for (reply = mCurNode.Children; reply != NULL; reply = reply.Next)
|
|
|
|
{
|
|
|
|
r++;
|
|
|
|
if (reply.ShouldSkipReply(mPlayer))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (activereply == r) mSelection = i - 1;
|
|
|
|
|
|
|
|
mShowGold |= reply.NeedsGold;
|
|
|
|
|
|
|
|
let ReplyText = Stringtable.Localize(reply.Reply);
|
2019-02-20 19:20:06 +00:00
|
|
|
if (reply.NeedsGold)
|
|
|
|
{
|
2019-03-19 23:49:00 +00:00
|
|
|
ReplyText.AppendFormat(" %s", Stringtable.Localize("$TXT_TRADE"));
|
2019-02-20 19:20:06 +00:00
|
|
|
let amount = String.Format("%u", reply.PrintAmount);
|
2019-03-19 23:49:00 +00:00
|
|
|
ReplyText.Replace("%u", amount);
|
2019-02-20 19:20:06 +00:00
|
|
|
}
|
2019-04-11 16:55:35 +00:00
|
|
|
let ReplyLines = displayFont.BreakLines (ReplyText, ReplyWidth);
|
2017-02-19 13:21:49 +00:00
|
|
|
|
|
|
|
mResponses.Push(mResponseLines.Size());
|
|
|
|
for (j = 0; j < ReplyLines.Count(); ++j)
|
|
|
|
{
|
|
|
|
mResponseLines.Push(ReplyLines.StringAt(j));
|
|
|
|
}
|
|
|
|
|
|
|
|
++i;
|
|
|
|
ReplyLines.Destroy();
|
|
|
|
}
|
|
|
|
if (mSelection == -1)
|
|
|
|
{
|
|
|
|
mSelection = r < activereply ? r + 1 : 0;
|
|
|
|
}
|
|
|
|
let goodbyestr = mCurNode.Goodbye;
|
|
|
|
if (goodbyestr.Length() == 0)
|
|
|
|
{
|
|
|
|
goodbyestr = String.Format("$TXT_RANDOMGOODBYE_%d", Random[RandomSpeech](1, NUM_RANDOM_GOODBYES));
|
|
|
|
}
|
|
|
|
else if (goodbyestr.Left(7) == "RANDOM_")
|
|
|
|
{
|
|
|
|
goodbyestr = String.Format("$TXT_%s_%02d", goodbyestr, Random[RandomSpeech](1, NUM_RANDOM_LINES));
|
|
|
|
}
|
|
|
|
goodbyestr = Stringtable.Localize(goodbyestr);
|
- fixed deprecation warnings in core scripts
Script warning, "gzdoom.pk3:zscript/ui/statscreen/statscreen.zs" line 24:
Call to deprecated function CharAt
Script warning, "gzdoom.pk3:zscript/ui/statscreen/statscreen.zs" line 24:
Accessing deprecated function CharAt - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 64:
Call to deprecated function ToLower
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 64:
Accessing deprecated function ToLower - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 65:
Call to deprecated function ToLower
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 65:
Accessing deprecated function ToLower - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 202:
Call to deprecated function CharAt
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 202:
Accessing deprecated function CharAt - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 235:
Call to deprecated function CharAt
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 235:
Accessing deprecated function CharAt - deprecated since 4.1.0
2019-04-28 08:26:01 +00:00
|
|
|
if (goodbyestr.Length() == 0 || goodbyestr.Left(1) == "$") goodbyestr = "Bye.";
|
2017-02-19 13:21:49 +00:00
|
|
|
mResponses.Push(mResponseLines.Size());
|
|
|
|
mResponseLines.Push(goodbyestr);
|
|
|
|
|
|
|
|
// Determine where the top of the reply list should be positioned.
|
2019-04-11 16:55:35 +00:00
|
|
|
mYpos = MIN (140, 192 - mResponseLines.Size() * ReplyLineHeight);
|
|
|
|
i = 44 + mResponseLines.Size() * ReplyLineHeight;
|
2017-02-19 13:21:49 +00:00
|
|
|
if (mYpos - 100 < i - screen.GetHeight() / CleanYfac / 2)
|
|
|
|
{
|
|
|
|
mYpos = i - screen.GetHeight() / CleanYfac / 2 + 100;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mSelection >= mResponses.Size())
|
|
|
|
{
|
|
|
|
mSelection = mResponses.Size() - 1;
|
|
|
|
}
|
|
|
|
return mYpos;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
virtual void FormatSpeakerMessage()
|
|
|
|
{
|
|
|
|
// Format the speaker's message.
|
|
|
|
String toSay = mCurNode.Dialogue;
|
|
|
|
if (toSay.Left(7) == "RANDOM_")
|
|
|
|
{
|
|
|
|
let dlgtext = String.Format("$TXT_%s_%02d", toSay, random[RandomSpeech](1, NUM_RANDOM_LINES));
|
|
|
|
toSay = Stringtable.Localize(dlgtext);
|
- fixed deprecation warnings in core scripts
Script warning, "gzdoom.pk3:zscript/ui/statscreen/statscreen.zs" line 24:
Call to deprecated function CharAt
Script warning, "gzdoom.pk3:zscript/ui/statscreen/statscreen.zs" line 24:
Accessing deprecated function CharAt - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 64:
Call to deprecated function ToLower
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 64:
Accessing deprecated function ToLower - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 65:
Call to deprecated function ToLower
Script warning, "gzdoom.pk3:zscript/ui/menu/search/query.zs" line 65:
Accessing deprecated function ToLower - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 202:
Call to deprecated function CharAt
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 202:
Accessing deprecated function CharAt - deprecated since 4.1.0
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 235:
Call to deprecated function CharAt
Script warning, "gzdoom.pk3:zscript/ui/menu/conversationmenu.zs" line 235:
Accessing deprecated function CharAt - deprecated since 4.1.0
2019-04-28 08:26:01 +00:00
|
|
|
if (toSay.Left(1) == "$") toSay = Stringtable.Localize("$TXT_GOAWAY");
|
2017-02-19 13:21:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// handle string table replacement
|
|
|
|
toSay = Stringtable.Localize(toSay);
|
|
|
|
}
|
|
|
|
if (toSay.Length() == 0)
|
|
|
|
{
|
|
|
|
toSay = ".";
|
|
|
|
}
|
2019-04-11 16:55:35 +00:00
|
|
|
mDialogueLines = displayFont.BreakLines(toSay, SpeechWidth);
|
2017-02-19 13:21:49 +00:00
|
|
|
}
|
|
|
|
|
2017-02-19 12:07:49 +00:00
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
override void OnDestroy()
|
|
|
|
{
|
2019-11-30 21:04:26 +00:00
|
|
|
if (mDialogueLines != null) mDialogueLines.Destroy();
|
2020-01-20 20:46:36 +00:00
|
|
|
SetMusicVolume (Level.MusicVolume);
|
2017-02-19 12:07:49 +00:00
|
|
|
Super.OnDestroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected int GetReplyNum()
|
|
|
|
{
|
|
|
|
// 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]
|
|
|
|
let reply = mCurNode.Children;
|
|
|
|
int replynum = mSelection;
|
|
|
|
for (int i = 0; i <= mSelection && reply != null; reply = reply.Next)
|
|
|
|
{
|
|
|
|
if (reply.ShouldSkipReply(mPlayer))
|
|
|
|
replynum++;
|
|
|
|
else
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return replynum;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
override bool MenuEvent(int mkey, bool fromcontroller)
|
|
|
|
{
|
|
|
|
if (demoplayback)
|
|
|
|
{ // During demo playback, don't let the user do anything besides close this menu.
|
|
|
|
if (mkey == MKEY_Back)
|
|
|
|
{
|
|
|
|
Close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (mkey == MKEY_Up)
|
|
|
|
{
|
|
|
|
if (--mSelection < 0) mSelection = mResponses.Size() - 1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (mkey == MKEY_Down)
|
|
|
|
{
|
|
|
|
if (++mSelection >= mResponses.Size()) mSelection = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (mkey == MKEY_Back)
|
|
|
|
{
|
|
|
|
SendConversationReply(-1, GetReplyNum());
|
|
|
|
Close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if (mkey == MKEY_Enter)
|
|
|
|
{
|
|
|
|
int replynum = GetReplyNum();
|
|
|
|
if (mSelection >= mResponses.Size())
|
|
|
|
{
|
|
|
|
SendConversationReply(-2, replynum);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Send dialogue and reply numbers across the wire.
|
|
|
|
SendConversationReply(mCurNode.ThisNodeNum, replynum);
|
|
|
|
}
|
|
|
|
Close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
|
|
|
override bool MouseEvent(int type, int x, int y)
|
|
|
|
{
|
|
|
|
int sel = -1;
|
2019-03-19 16:46:59 +00:00
|
|
|
int fh = LineHeight;
|
2017-02-19 11:28:05 +00:00
|
|
|
|
2017-02-19 12:07:49 +00:00
|
|
|
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
2019-04-11 16:55:35 +00:00
|
|
|
x = ((x - (screen.GetWidth() / 2)) / fontScale) + refWidth/2;
|
2019-08-07 18:24:45 +00:00
|
|
|
|
2020-06-04 12:11:36 +00:00
|
|
|
if (x >= 24 && x <= refWidth-24)
|
2017-02-19 12:07:49 +00:00
|
|
|
{
|
2020-06-04 12:11:36 +00:00
|
|
|
for (int i = 0; i < ypositions.Size()-1; i++)
|
2017-02-19 12:07:49 +00:00
|
|
|
{
|
2020-06-04 12:11:36 +00:00
|
|
|
if (y > ypositions[i] && y <= ypositions[i+1])
|
2017-02-19 12:07:49 +00:00
|
|
|
{
|
2020-06-04 12:11:36 +00:00
|
|
|
sel = i;
|
2017-02-19 12:07:49 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mSelection = sel;
|
|
|
|
if (type == MOUSE_Release)
|
|
|
|
{
|
|
|
|
return MenuEvent(MKEY_Enter, true);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//=============================================================================
|
|
|
|
|
2017-03-06 21:27:51 +00:00
|
|
|
override bool OnUIEvent(UIEvent ev)
|
2017-02-19 12:07:49 +00:00
|
|
|
{
|
|
|
|
if (demoplayback)
|
|
|
|
{ // No interaction during demo playback
|
|
|
|
return false;
|
|
|
|
}
|
2017-03-06 21:27:51 +00:00
|
|
|
if (ev.type == UIEvent.Type_Char && ev.KeyChar >= 48 && ev.KeyChar <= 57)
|
2017-02-19 12:07:49 +00:00
|
|
|
{ // Activate an item of type numberedmore (dialogue only)
|
2017-03-06 21:27:51 +00:00
|
|
|
mSelection = ev.KeyChar == 48 ? 9 : ev.KeyChar - 49;
|
2017-02-19 12:07:49 +00:00
|
|
|
return MenuEvent(MKEY_Enter, false);
|
|
|
|
}
|
2017-03-06 21:27:51 +00:00
|
|
|
return Super.OnUIEvent(ev);
|
2017-02-19 12:07:49 +00:00
|
|
|
}
|
|
|
|
|
2017-02-19 11:28:05 +00:00
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// Draw the backdrop, returns true if the text background should be dimmed
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
virtual bool DrawBackdrop()
|
|
|
|
{
|
2017-02-19 13:21:49 +00:00
|
|
|
let tex = TexMan.CheckForTexture (mCurNode.Backdrop, TexMan.Type_MiscPatch);
|
|
|
|
if (tex.isValid())
|
2017-02-19 11:28:05 +00:00
|
|
|
{
|
2017-02-19 13:21:49 +00:00
|
|
|
screen.DrawTexture(tex, false, 0, 0, DTA_320x200, true);
|
2017-02-19 11:28:05 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// Draw the speaker text
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
virtual void DrawSpeakerText(bool dimbg)
|
|
|
|
{
|
|
|
|
String speakerName;
|
2019-04-11 16:55:35 +00:00
|
|
|
int linesize = LineHeight * fontScale;
|
2017-02-19 11:28:05 +00:00
|
|
|
int cnt = mDialogueLines.Count();
|
|
|
|
|
|
|
|
// Who is talking to you?
|
|
|
|
if (mCurNode.SpeakerName.Length() > 0)
|
|
|
|
{
|
|
|
|
speakerName = Stringtable.Localize(mCurNode.SpeakerName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-03-03 08:16:21 +00:00
|
|
|
speakerName = players[consoleplayer].ConversationNPC.GetTag("$TXT_PERSON");
|
2017-02-19 11:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
{
|
2019-07-27 07:35:45 +00:00
|
|
|
screen.DrawText(displayFont, Font.CR_WHITE, x / fontScale, y / fontScale, speakerName, DTA_KeepRatio, !mConfineTextToBackdrop, DTA_VirtualWidth, speechDisplayWidth, DTA_VirtualHeight, displayHeight);
|
2017-02-19 11:28:05 +00:00
|
|
|
y += linesize * 3 / 2;
|
|
|
|
}
|
|
|
|
x = 24 * screen.GetWidth() / 320;
|
|
|
|
for (int i = 0; i < cnt; ++i)
|
|
|
|
{
|
2019-07-27 07:35:45 +00:00
|
|
|
screen.DrawText(displayFont, Font.CR_UNTRANSLATED, x / fontScale, y / fontScale, mDialogueLines.StringAt(i), DTA_KeepRatio, !mConfineTextToBackdrop, DTA_VirtualWidth, speechDisplayWidth, DTA_VirtualHeight, displayHeight);
|
2017-02-19 11:28:05 +00:00
|
|
|
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,
|
2019-04-11 16:55:35 +00:00
|
|
|
272 * CleanXfac, MIN(mResponseLines.Size() * ReplyLineHeight + 4, 200 - mYpos) * CleanYfac);
|
|
|
|
|
2017-02-19 11:28:05 +00:00
|
|
|
|
|
|
|
int y = mYpos;
|
|
|
|
|
|
|
|
int response = 0;
|
2020-06-04 12:11:36 +00:00
|
|
|
ypositions.Clear();
|
2017-02-19 11:28:05 +00:00
|
|
|
for (int i = 0; i < mResponseLines.Size(); i++)
|
|
|
|
{
|
2019-04-11 16:55:35 +00:00
|
|
|
int width = displayFont.StringWidth(mResponseLines[i]);
|
2017-02-19 11:28:05 +00:00
|
|
|
int x = 64;
|
|
|
|
|
2019-04-11 16:55:35 +00:00
|
|
|
double sx = (x - 160.0) * CleanXfac + (screen.GetWidth() * 0.5);
|
|
|
|
double sy = (y - 100.0) * CleanYfac + (screen.GetHeight() * 0.5);
|
|
|
|
|
|
|
|
screen.DrawText(displayFont, Font.CR_GREEN, sx / fontScale, sy / fontScale, mResponseLines[i], DTA_KeepRatio, true, DTA_VirtualWidth, displayWidth, DTA_VirtualHeight, displayHeight);
|
2017-02-19 11:28:05 +00:00
|
|
|
|
|
|
|
if (i == mResponses[response])
|
|
|
|
{
|
|
|
|
String tbuf;
|
|
|
|
|
2022-05-08 22:11:53 +00:00
|
|
|
ypositions.Push(sy);
|
2017-02-19 11:28:05 +00:00
|
|
|
response++;
|
|
|
|
tbuf = String.Format("%d.", response);
|
2019-04-11 16:55:35 +00:00
|
|
|
x = 50 - displayFont.StringWidth(tbuf);
|
|
|
|
sx = (x - 160.0) * CleanXfac + (screen.GetWidth() * 0.5);
|
|
|
|
screen.DrawText(displayFont, Font.CR_GREY, sx / fontScale, sy / fontScale, tbuf, DTA_KeepRatio, true, DTA_VirtualWidth, displayWidth, DTA_VirtualHeight, displayHeight);
|
2017-02-19 11:28:05 +00:00
|
|
|
|
|
|
|
if (response == mSelection + 1)
|
|
|
|
{
|
|
|
|
int colr = ((MenuTime() % 8) < 4) || GetCurrentMenu() != self ? Font.CR_RED : Font.CR_GREY;
|
|
|
|
|
2020-08-25 15:55:43 +00:00
|
|
|
// custom graphic cursor color
|
|
|
|
Color cursorTexColor;
|
|
|
|
if (colr == Font.CR_RED) cursorTexColor = color(0xFF, 0x00, 0x00);
|
|
|
|
else if (colr == Font.CR_GREY) cursorTexColor = color(0xCC, 0xCC, 0xCC);
|
|
|
|
|
2017-02-19 11:28:05 +00:00
|
|
|
x = (50 + 3 - 160) * CleanXfac + screen.GetWidth() / 2;
|
2019-04-11 16:55:35 +00:00
|
|
|
int yy = (y + ReplyLineHeight / 2 - 5 - 100) * CleanYfac + screen.GetHeight() / 2;
|
2020-08-25 15:55:43 +00:00
|
|
|
|
|
|
|
// use a custom graphic (intentionally long-named to reduce collision with existing mods), with the ConFont version as the fallback
|
|
|
|
let cursorTex = TexMan.CheckForTexture("graphics/DialogReplyCursor.png", TexMan.Type_MiscPatch);
|
|
|
|
if (cursorTex.IsValid())
|
|
|
|
{
|
|
|
|
screen.DrawTexture(cursorTex, true, x / fontScale, yy / fontScale, DTA_KeepRatio, true, DTA_VirtualWidth, displayWidth, DTA_VirtualHeight, displayHeight);
|
|
|
|
screen.DrawTexture(cursorTex, true, x / fontScale, yy / fontScale, DTA_KeepRatio, true, DTA_VirtualWidth, displayWidth, DTA_VirtualHeight, displayHeight, DTA_FillColor, cursorTexColor, DTA_LegacyRenderStyle, STYLE_AddShaded);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
screen.DrawText(ConFont, colr, x, yy, "\xd", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac);
|
|
|
|
}
|
2017-02-19 11:28:05 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-11 16:55:35 +00:00
|
|
|
y += ReplyLineHeight;
|
2017-02-19 11:28:05 +00:00
|
|
|
}
|
2020-06-04 12:11:36 +00:00
|
|
|
double sy = (y - 100.0) * CleanYfac + (screen.GetHeight() * 0.5);
|
|
|
|
ypositions.Push(sy);
|
2017-02-19 11:28:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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()
|
|
|
|
{
|
|
|
|
// [CW] Freeze the game depending on MAPINFO options.
|
2019-02-01 23:24:43 +00:00
|
|
|
if (ConversationPauseTic < gametic && !multiplayer && !Level.no_dlg_freeze)
|
2017-02-19 11:28:05 +00:00
|
|
|
{
|
|
|
|
menuactive = Menu.On;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|