mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-29 07:22:07 +00:00
This commit is contained in:
commit
11d6f46e2d
25 changed files with 934 additions and 785 deletions
|
@ -38,6 +38,7 @@ conversation
|
||||||
page
|
page
|
||||||
{
|
{
|
||||||
drop = <string>;
|
drop = <string>;
|
||||||
|
userstring = <string>; New field which can be used to pass data to custom conversation menu classes.
|
||||||
ifitem
|
ifitem
|
||||||
{
|
{
|
||||||
item = <string>;
|
item = <string>;
|
||||||
|
@ -63,10 +64,6 @@ either refuse loading dialogues with the 'ZDoom' namespace or if it does not
|
||||||
outright abort on incompatible namespaces fail with a type mismatch error on
|
outright abort on incompatible namespaces fail with a type mismatch error on
|
||||||
one of the specified propeties.
|
one of the specified propeties.
|
||||||
|
|
||||||
In addition ZDoom defines one new field in the top level of a conversation block:
|
|
||||||
|
|
||||||
id = <integer>; Assigns a conversation ID for use in Thing_SetConversation or in UDMF's 'conversation' actor property.
|
|
||||||
|
|
||||||
ZDoom-format dialogues need to start with the line:
|
ZDoom-format dialogues need to start with the line:
|
||||||
|
|
||||||
namespace = "ZDoom";
|
namespace = "ZDoom";
|
||||||
|
@ -86,6 +83,7 @@ conversation // Starts a dialog.
|
||||||
// the standard conversation ID ('actor' property) is used instead
|
// the standard conversation ID ('actor' property) is used instead
|
||||||
// for this purpose but since 'ZDoom' namespace requires the actor
|
// for this purpose but since 'ZDoom' namespace requires the actor
|
||||||
// to be a class name it needs a separate field for this.
|
// to be a class name it needs a separate field for this.
|
||||||
|
class = <string>; //Override the default conversation menu class for this conversation.
|
||||||
|
|
||||||
page
|
page
|
||||||
{
|
{
|
||||||
|
|
|
@ -1937,6 +1937,7 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND)
|
||||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS)
|
DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS)
|
||||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, frozen, LEVEL2_FROZEN)
|
DEFINE_FIELD_BIT(FLevelLocals, flags2, frozen, LEVEL2_FROZEN)
|
||||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, infinite_flight, LEVEL2_INFINITE_FLIGHT)
|
DEFINE_FIELD_BIT(FLevelLocals, flags2, infinite_flight, LEVEL2_INFINITE_FLIGHT)
|
||||||
|
DEFINE_FIELD_BIT(FLevelLocals, flags2, no_dlg_freeze, LEVEL2_CONV_SINGLE_UNFREEZE)
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -52,6 +52,7 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon2)
|
||||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gametype)
|
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gametype)
|
||||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, norandomplayerclass)
|
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, norandomplayerclass)
|
||||||
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, infoPages)
|
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, infoPages)
|
||||||
|
DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mBackButton)
|
||||||
|
|
||||||
|
|
||||||
const char *GameNames[17] =
|
const char *GameNames[17] =
|
||||||
|
@ -362,6 +363,7 @@ void FMapInfoParser::ParseGameInfo()
|
||||||
GAMEINFOKEY_INT(TextScreenX, "textscreenx")
|
GAMEINFOKEY_INT(TextScreenX, "textscreenx")
|
||||||
GAMEINFOKEY_INT(TextScreenY, "textscreeny")
|
GAMEINFOKEY_INT(TextScreenY, "textscreeny")
|
||||||
GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
|
GAMEINFOKEY_STRING(DefaultEndSequence, "defaultendsequence")
|
||||||
|
GAMEINFOKEY_STRING(DefaultConversationMenuClass, "defaultconversationmenuclass")
|
||||||
GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
|
GAMEINFOKEY_FONT(mStatscreenMapNameFont, "statscreen_mapnamefont")
|
||||||
GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
|
GAMEINFOKEY_FONT(mStatscreenFinishedFont, "statscreen_finishedfont")
|
||||||
GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
|
GAMEINFOKEY_FONT(mStatscreenEnteringFont, "statscreen_enteringfont")
|
||||||
|
|
1
src/gi.h
1
src/gi.h
|
@ -172,6 +172,7 @@ struct gameinfo_t
|
||||||
double gibfactor;
|
double gibfactor;
|
||||||
int TextScreenX;
|
int TextScreenX;
|
||||||
int TextScreenY;
|
int TextScreenY;
|
||||||
|
FName DefaultConversationMenuClass;
|
||||||
FName DefaultEndSequence;
|
FName DefaultEndSequence;
|
||||||
FString mMapArrow, mCheatMapArrow;
|
FString mMapArrow, mCheatMapArrow;
|
||||||
FString mEasyKey, mCheatKey;
|
FString mEasyKey, mCheatKey;
|
||||||
|
|
|
@ -160,56 +160,15 @@ DMenu::DMenu(DMenu *parent)
|
||||||
mParentMenu = parent;
|
mParentMenu = parent;
|
||||||
mMouseCapture = false;
|
mMouseCapture = false;
|
||||||
mBackbuttonSelected = false;
|
mBackbuttonSelected = false;
|
||||||
|
DontDim = false;
|
||||||
GC::WriteBarrier(this, parent);
|
GC::WriteBarrier(this, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DMenu::Responder (event_t *ev)
|
//=============================================================================
|
||||||
{
|
//
|
||||||
bool res = false;
|
//
|
||||||
if (ev->type == EV_GUI_Event)
|
//
|
||||||
{
|
//=============================================================================
|
||||||
if (ev->subtype == EV_GUI_LButtonDown)
|
|
||||||
{
|
|
||||||
res = MouseEventBack(MOUSE_Click, ev->data1, ev->data2);
|
|
||||||
// make the menu's mouse handler believe that the current coordinate is outside the valid range
|
|
||||||
if (res) ev->data2 = -1;
|
|
||||||
res |= CallMouseEvent(MOUSE_Click, ev->data1, ev->data2);
|
|
||||||
if (res)
|
|
||||||
{
|
|
||||||
SetCapture();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (ev->subtype == EV_GUI_MouseMove)
|
|
||||||
{
|
|
||||||
BackbuttonTime = BACKBUTTON_TIME;
|
|
||||||
if (mMouseCapture || m_use_mouse == 1)
|
|
||||||
{
|
|
||||||
res = MouseEventBack(MOUSE_Move, ev->data1, ev->data2);
|
|
||||||
if (res) ev->data2 = -1;
|
|
||||||
res |= CallMouseEvent(MOUSE_Move, ev->data1, ev->data2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ev->subtype == EV_GUI_LButtonUp)
|
|
||||||
{
|
|
||||||
if (mMouseCapture)
|
|
||||||
{
|
|
||||||
ReleaseCapture();
|
|
||||||
res = MouseEventBack(MOUSE_Release, ev->data1, ev->data2);
|
|
||||||
if (res) ev->data2 = -1;
|
|
||||||
res |= CallMouseEvent(MOUSE_Release, ev->data1, ev->data2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(DMenu, Responder)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(DMenu);
|
|
||||||
PARAM_POINTER(ev, event_t);
|
|
||||||
ACTION_RETURN_BOOL(self->Responder(ev));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DMenu::CallResponder(event_t *ev)
|
bool DMenu::CallResponder(event_t *ev)
|
||||||
{
|
{
|
||||||
|
@ -221,7 +180,7 @@ bool DMenu::CallResponder(event_t *ev)
|
||||||
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr);
|
||||||
return !!retval;
|
return !!retval;
|
||||||
}
|
}
|
||||||
else return Responder(ev);
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -230,29 +189,6 @@ bool DMenu::CallResponder(event_t *ev)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
bool DMenu::MenuEvent (int mkey, bool fromcontroller)
|
|
||||||
{
|
|
||||||
switch (mkey)
|
|
||||||
{
|
|
||||||
case MKEY_Back:
|
|
||||||
{
|
|
||||||
Close();
|
|
||||||
S_Sound (CHAN_VOICE | CHAN_UI,
|
|
||||||
CurrentMenu != nullptr? "menu/backup" : "menu/clear", snd_menuvolume, ATTN_NONE);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(DMenu, MenuEvent)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(DMenu);
|
|
||||||
PARAM_INT(key);
|
|
||||||
PARAM_BOOL(fromcontroller);
|
|
||||||
ACTION_RETURN_BOOL(self->MenuEvent(key, fromcontroller));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DMenu::CallMenuEvent(int mkey, bool fromcontroller)
|
bool DMenu::CallMenuEvent(int mkey, bool fromcontroller)
|
||||||
{
|
{
|
||||||
IFVIRTUAL(DMenu, MenuEvent)
|
IFVIRTUAL(DMenu, MenuEvent)
|
||||||
|
@ -263,7 +199,7 @@ bool DMenu::CallMenuEvent(int mkey, bool fromcontroller)
|
||||||
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
|
GlobalVMStack.Call(func, params, 3, &ret, 1, nullptr);
|
||||||
return !!retval;
|
return !!retval;
|
||||||
}
|
}
|
||||||
else return MenuEvent(mkey, fromcontroller);
|
else return false;
|
||||||
}
|
}
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
|
@ -271,6 +207,15 @@ bool DMenu::CallMenuEvent(int mkey, bool fromcontroller)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DMenu, SetMouseCapture)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_BOOL(on);
|
||||||
|
if (on) I_SetMouseCapture();
|
||||||
|
else I_ReleaseMouseCapture();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void DMenu::Close ()
|
void DMenu::Close ()
|
||||||
{
|
{
|
||||||
if (CurrentMenu == nullptr) return; // double closing can happen in the save menu.
|
if (CurrentMenu == nullptr) return; // double closing can happen in the save menu.
|
||||||
|
@ -287,108 +232,19 @@ void DMenu::Close ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
DEFINE_ACTION_FUNCTION(DMenu, Close)
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool DMenu::MouseEvent(int type, int x, int y)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(DMenu, MouseEvent)
|
|
||||||
{
|
{
|
||||||
PARAM_SELF_PROLOGUE(DMenu);
|
PARAM_SELF_PROLOGUE(DMenu);
|
||||||
PARAM_INT(type);
|
self->Close();
|
||||||
PARAM_INT(x);
|
|
||||||
PARAM_INT(y);
|
|
||||||
ACTION_RETURN_BOOL(self->MouseEvent(type, x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DMenu::CallMouseEvent(int type, int x, int y)
|
|
||||||
{
|
|
||||||
IFVIRTUAL(DMenu, MouseEvent)
|
|
||||||
{
|
|
||||||
VMValue params[] = { (DObject*)this, type, x, y };
|
|
||||||
int retval;
|
|
||||||
VMReturn ret(&retval);
|
|
||||||
GlobalVMStack.Call(func, params, 4, &ret, 1, nullptr);
|
|
||||||
return !!retval;
|
|
||||||
}
|
|
||||||
else return MouseEvent (type, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool DMenu::MouseEventBack(int type, int x, int y)
|
|
||||||
{
|
|
||||||
if (m_show_backbutton >= 0)
|
|
||||||
{
|
|
||||||
FTexture *tex = TexMan(gameinfo.mBackButton);
|
|
||||||
if (tex != nullptr)
|
|
||||||
{
|
|
||||||
if (m_show_backbutton&1) x -= screen->GetWidth() - tex->GetScaledWidth() * CleanXfac;
|
|
||||||
if (m_show_backbutton&2) y -= screen->GetHeight() - tex->GetScaledHeight() * CleanYfac;
|
|
||||||
mBackbuttonSelected = ( x >= 0 && x < tex->GetScaledWidth() * CleanXfac &&
|
|
||||||
y >= 0 && y < tex->GetScaledHeight() * CleanYfac);
|
|
||||||
if (mBackbuttonSelected && type == MOUSE_Release)
|
|
||||||
{
|
|
||||||
if (m_use_mouse == 2) mBackbuttonSelected = false;
|
|
||||||
CallMenuEvent(MKEY_Back, true);
|
|
||||||
}
|
|
||||||
return mBackbuttonSelected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void DMenu::SetCapture()
|
|
||||||
{
|
|
||||||
if (!mMouseCapture)
|
|
||||||
{
|
|
||||||
mMouseCapture = true;
|
|
||||||
I_SetMouseCapture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DMenu::ReleaseCapture()
|
|
||||||
{
|
|
||||||
if (mMouseCapture)
|
|
||||||
{
|
|
||||||
mMouseCapture = false;
|
|
||||||
I_ReleaseMouseCapture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void DMenu::Ticker ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(DMenu, Ticker)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(DMenu);
|
|
||||||
self->Ticker();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
void DMenu::CallTicker()
|
void DMenu::CallTicker()
|
||||||
{
|
{
|
||||||
IFVIRTUAL(DMenu, Ticker)
|
IFVIRTUAL(DMenu, Ticker)
|
||||||
|
@ -396,38 +252,9 @@ void DMenu::CallTicker()
|
||||||
VMValue params[] = { (DObject*)this };
|
VMValue params[] = { (DObject*)this };
|
||||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
else Ticker();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DMenu::Drawer ()
|
|
||||||
{
|
|
||||||
if (this == CurrentMenu && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
|
||||||
{
|
|
||||||
FTexture *tex = TexMan(gameinfo.mBackButton);
|
|
||||||
int w = tex->GetScaledWidth() * CleanXfac;
|
|
||||||
int h = tex->GetScaledHeight() * CleanYfac;
|
|
||||||
int x = (!(m_show_backbutton&1))? 0:screen->GetWidth() - w;
|
|
||||||
int y = (!(m_show_backbutton&2))? 0:screen->GetHeight() - h;
|
|
||||||
if (mBackbuttonSelected && (mMouseCapture || m_use_mouse == 1))
|
|
||||||
{
|
|
||||||
screen->DrawTexture(tex, x, y, DTA_CleanNoMove, true, DTA_ColorOverlay, MAKEARGB(40, 255,255,255), TAG_DONE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
screen->DrawTexture(tex, x, y, DTA_CleanNoMove, true, DTA_Alpha, BackbuttonAlpha, TAG_DONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(DMenu, Drawer)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(DMenu);
|
|
||||||
self->Drawer();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DMenu::CallDrawer()
|
void DMenu::CallDrawer()
|
||||||
{
|
{
|
||||||
IFVIRTUAL(DMenu, Drawer)
|
IFVIRTUAL(DMenu, Drawer)
|
||||||
|
@ -435,19 +262,6 @@ void DMenu::CallDrawer()
|
||||||
VMValue params[] = { (DObject*)this };
|
VMValue params[] = { (DObject*)this };
|
||||||
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
else Drawer();
|
|
||||||
}
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(DMenu, Close)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(DMenu);
|
|
||||||
self->Close();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DMenu::DimAllowed()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DMenu::TranslateKeyboardEvents()
|
bool DMenu::TranslateKeyboardEvents()
|
||||||
|
@ -504,7 +318,11 @@ void M_StartControlPanel (bool makeSound)
|
||||||
void M_ActivateMenu(DMenu *menu)
|
void M_ActivateMenu(DMenu *menu)
|
||||||
{
|
{
|
||||||
if (menuactive == MENU_Off) menuactive = MENU_On;
|
if (menuactive == MENU_Off) menuactive = MENU_On;
|
||||||
if (CurrentMenu != nullptr) CurrentMenu->ReleaseCapture();
|
if (CurrentMenu != nullptr && CurrentMenu->mMouseCapture)
|
||||||
|
{
|
||||||
|
CurrentMenu->mMouseCapture = false;
|
||||||
|
I_ReleaseMouseCapture();
|
||||||
|
}
|
||||||
CurrentMenu = menu;
|
CurrentMenu = menu;
|
||||||
GC::WriteBarrier(CurrentMenu);
|
GC::WriteBarrier(CurrentMenu);
|
||||||
}
|
}
|
||||||
|
@ -651,10 +469,15 @@ void M_SetMenu(FName menu, int param)
|
||||||
const PClass *menuclass = PClass::FindClass(menu);
|
const PClass *menuclass = PClass::FindClass(menu);
|
||||||
if (menuclass != nullptr)
|
if (menuclass != nullptr)
|
||||||
{
|
{
|
||||||
if (menuclass->IsDescendantOf(RUNTIME_CLASS(DMenu)))
|
if (menuclass->IsDescendantOf("GenericMenu"))
|
||||||
{
|
{
|
||||||
DMenu *newmenu = (DMenu*)menuclass->CreateNew();
|
DMenu *newmenu = (DMenu*)menuclass->CreateNew();
|
||||||
newmenu->mParentMenu = CurrentMenu;
|
|
||||||
|
IFVIRTUALPTRNAME(newmenu, "GenericMenu", Init)
|
||||||
|
{
|
||||||
|
VMValue params[3] = { newmenu, CurrentMenu };
|
||||||
|
GlobalVMStack.Call(func, params, 2, nullptr, 0);
|
||||||
|
}
|
||||||
M_ActivateMenu(newmenu);
|
M_ActivateMenu(newmenu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -928,7 +751,7 @@ void M_Drawer (void)
|
||||||
|
|
||||||
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
if (CurrentMenu != nullptr && menuactive != MENU_Off)
|
||||||
{
|
{
|
||||||
if (CurrentMenu->DimAllowed())
|
if (!CurrentMenu->DontDim)
|
||||||
{
|
{
|
||||||
screen->Dim(fade);
|
screen->Dim(fade);
|
||||||
V_SetBorderNeedRefresh();
|
V_SetBorderNeedRefresh();
|
||||||
|
@ -943,13 +766,14 @@ void M_Drawer (void)
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void M_ClearMenus ()
|
void M_ClearMenus()
|
||||||
{
|
{
|
||||||
M_DemoNoPlay = false;
|
M_DemoNoPlay = false;
|
||||||
if (CurrentMenu != nullptr)
|
while (CurrentMenu != nullptr)
|
||||||
{
|
{
|
||||||
|
DMenu* parent = CurrentMenu->mParentMenu;
|
||||||
CurrentMenu->Destroy();
|
CurrentMenu->Destroy();
|
||||||
CurrentMenu = nullptr;
|
CurrentMenu = parent;
|
||||||
}
|
}
|
||||||
V_SetBorderNeedRefresh();
|
V_SetBorderNeedRefresh();
|
||||||
menuactive = MENU_Off;
|
menuactive = MENU_Off;
|
||||||
|
@ -1203,6 +1027,7 @@ CCMD(undocolorpic)
|
||||||
DEFINE_FIELD(DMenu, mParentMenu)
|
DEFINE_FIELD(DMenu, mParentMenu)
|
||||||
DEFINE_FIELD(DMenu, mMouseCapture);
|
DEFINE_FIELD(DMenu, mMouseCapture);
|
||||||
DEFINE_FIELD(DMenu, mBackbuttonSelected);
|
DEFINE_FIELD(DMenu, mBackbuttonSelected);
|
||||||
|
DEFINE_FIELD(DMenu, DontDim);
|
||||||
|
|
||||||
DEFINE_FIELD(DMenuDescriptor, mMenuName)
|
DEFINE_FIELD(DMenuDescriptor, mMenuName)
|
||||||
DEFINE_FIELD(DMenuDescriptor, mNetgameMessage)
|
DEFINE_FIELD(DMenuDescriptor, mNetgameMessage)
|
||||||
|
@ -1292,7 +1117,7 @@ DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBi
|
||||||
return (DMenuItemBase*)p;
|
return (DMenuItemBase*)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID tex, FName command, int param)
|
DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotkey, FTextureID tex, FName command, int param)
|
||||||
{
|
{
|
||||||
auto c = PClass::FindClass("ListMenuItemPatchItem");
|
auto c = PClass::FindClass("ListMenuItemPatchItem");
|
||||||
auto p = c->CreateNew();
|
auto p = c->CreateNew();
|
||||||
|
@ -1302,7 +1127,7 @@ DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FT
|
||||||
return (DMenuItemBase*)p;
|
return (DMenuItemBase*)p;
|
||||||
}
|
}
|
||||||
|
|
||||||
DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param)
|
DMenuItemBase * CreateListMenuItemText(double x, double y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param)
|
||||||
{
|
{
|
||||||
auto c = PClass::FindClass("ListMenuItemTextItem");
|
auto c = PClass::FindClass("ListMenuItemTextItem");
|
||||||
auto p = c->CreateNew();
|
auto p = c->CreateNew();
|
||||||
|
|
|
@ -138,11 +138,11 @@ class DListMenuDescriptor : public DMenuDescriptor
|
||||||
public:
|
public:
|
||||||
TArray<DMenuItemBase *> mItems;
|
TArray<DMenuItemBase *> mItems;
|
||||||
int mSelectedItem;
|
int mSelectedItem;
|
||||||
int mSelectOfsX;
|
double mSelectOfsX;
|
||||||
int mSelectOfsY;
|
double mSelectOfsY;
|
||||||
FTextureID mSelector;
|
FTextureID mSelector;
|
||||||
int mDisplayTop;
|
int mDisplayTop;
|
||||||
int mXpos, mYpos;
|
double mXpos, mYpos;
|
||||||
int mWLeft, mWRight;
|
int mWLeft, mWRight;
|
||||||
int mLinespacing; // needs to be stored for dynamically created menus
|
int mLinespacing; // needs to be stored for dynamically created menus
|
||||||
int mAutoselect; // this can only be set by internal menu creation functions
|
int mAutoselect; // this can only be set by internal menu creation functions
|
||||||
|
@ -263,42 +263,19 @@ public:
|
||||||
MOUSE_Release
|
MOUSE_Release
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
BACKBUTTON_TIME = 4*TICRATE
|
|
||||||
};
|
|
||||||
|
|
||||||
TObjPtr<DMenu> mParentMenu;
|
TObjPtr<DMenu> mParentMenu;
|
||||||
bool mMouseCapture;
|
bool mMouseCapture;
|
||||||
bool mBackbuttonSelected;
|
bool mBackbuttonSelected;
|
||||||
|
bool DontDim;
|
||||||
|
|
||||||
DMenu(DMenu *parent = NULL);
|
DMenu(DMenu *parent = NULL);
|
||||||
virtual bool Responder (event_t *ev);
|
|
||||||
virtual bool MenuEvent (int mkey, bool fromcontroller);
|
|
||||||
virtual void Ticker ();
|
|
||||||
virtual void Drawer ();
|
|
||||||
virtual bool DimAllowed ();
|
|
||||||
bool TranslateKeyboardEvents();
|
bool TranslateKeyboardEvents();
|
||||||
virtual void Close();
|
virtual void Close();
|
||||||
virtual bool MouseEvent(int type, int x, int y);
|
|
||||||
|
|
||||||
virtual void SetFocus(DMenuItemBase *fc) {}
|
|
||||||
virtual bool CheckFocus(DMenuItemBase *fc) { return false; }
|
|
||||||
virtual void ReleaseFocus() {}
|
|
||||||
|
|
||||||
bool CallResponder(event_t *ev);
|
bool CallResponder(event_t *ev);
|
||||||
bool CallMenuEvent(int mkey, bool fromcontroller);
|
bool CallMenuEvent(int mkey, bool fromcontroller);
|
||||||
bool CallMouseEvent(int type, int x, int y);
|
|
||||||
void CallTicker();
|
void CallTicker();
|
||||||
void CallDrawer();
|
void CallDrawer();
|
||||||
|
|
||||||
bool MouseEventBack(int type, int x, int y);
|
|
||||||
void SetCapture();
|
|
||||||
void ReleaseCapture();
|
|
||||||
bool HasCapture()
|
|
||||||
{
|
|
||||||
return mMouseCapture;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -311,7 +288,7 @@ class DMenuItemBase : public DObject
|
||||||
{
|
{
|
||||||
DECLARE_CLASS(DMenuItemBase, DObject)
|
DECLARE_CLASS(DMenuItemBase, DObject)
|
||||||
public:
|
public:
|
||||||
int mXpos, mYpos;
|
double mXpos, mYpos;
|
||||||
FNameNoInit mAction;
|
FNameNoInit mAction;
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
|
||||||
|
@ -321,7 +298,7 @@ public:
|
||||||
bool SetValue(int i, int value);
|
bool SetValue(int i, int value);
|
||||||
bool GetValue(int i, int *pvalue);
|
bool GetValue(int i, int *pvalue);
|
||||||
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
||||||
int GetY() { return mYpos; }
|
double GetY() { return mYpos; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -378,7 +355,7 @@ DMenuItemBase * CreateOptionMenuItemStaticText(const char *name, bool v);
|
||||||
DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center);
|
DMenuItemBase * CreateOptionMenuItemSubmenu(const char *label, FName cmd, int center);
|
||||||
DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings);
|
DMenuItemBase * CreateOptionMenuItemControl(const char *label, FName cmd, FKeyBindings *bindings);
|
||||||
DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy);
|
DMenuItemBase * CreateOptionMenuItemJoyConfigMenu(const char *label, IJoystickConfig *joy);
|
||||||
DMenuItemBase * CreateListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID tex, FName command, int param);
|
DMenuItemBase * CreateListMenuItemPatch(double x, double y, int height, int hotkey, FTextureID tex, FName command, int param);
|
||||||
DMenuItemBase * CreateListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param);
|
DMenuItemBase * CreateListMenuItemText(double x, double y, int height, int hotkey, const char *text, FFont *font, PalEntry color1, PalEntry color2, FName command, int param);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -305,11 +305,11 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
desc->mSelector = GetMenuTexture(sc.String);
|
desc->mSelector = GetMenuTexture(sc.String);
|
||||||
sc.MustGetStringName(",");
|
sc.MustGetStringName(",");
|
||||||
sc.MustGetNumber();
|
sc.MustGetFloat();
|
||||||
desc->mSelectOfsX = sc.Number;
|
desc->mSelectOfsX = sc.Float;
|
||||||
sc.MustGetStringName(",");
|
sc.MustGetStringName(",");
|
||||||
sc.MustGetNumber();
|
sc.MustGetFloat();
|
||||||
desc->mSelectOfsY = sc.Number;
|
desc->mSelectOfsY = sc.Float;
|
||||||
}
|
}
|
||||||
else if (sc.Compare("Linespacing"))
|
else if (sc.Compare("Linespacing"))
|
||||||
{
|
{
|
||||||
|
@ -318,11 +318,11 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
||||||
}
|
}
|
||||||
else if (sc.Compare("Position"))
|
else if (sc.Compare("Position"))
|
||||||
{
|
{
|
||||||
sc.MustGetNumber();
|
sc.MustGetFloat();
|
||||||
desc->mXpos = sc.Number;
|
desc->mXpos = sc.Float;
|
||||||
sc.MustGetStringName(",");
|
sc.MustGetStringName(",");
|
||||||
sc.MustGetNumber();
|
sc.MustGetFloat();
|
||||||
desc->mYpos = sc.Number;
|
desc->mYpos = sc.Float;
|
||||||
}
|
}
|
||||||
else if (sc.Compare("Centermenu"))
|
else if (sc.Compare("Centermenu"))
|
||||||
{
|
{
|
||||||
|
@ -369,7 +369,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc)
|
||||||
PClass *cls = PClass::FindClass(buildname);
|
PClass *cls = PClass::FindClass(buildname);
|
||||||
if (cls != nullptr && cls->IsDescendantOf("ListMenuItem"))
|
if (cls != nullptr && cls->IsDescendantOf("ListMenuItem"))
|
||||||
{
|
{
|
||||||
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", false));
|
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", true));
|
||||||
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
|
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
|
||||||
{
|
{
|
||||||
auto &args = func->Variants[0].Proto->ArgumentTypes;
|
auto &args = func->Variants[0].Proto->ArgumentTypes;
|
||||||
|
@ -741,7 +741,7 @@ static void ParseOptionMenuBody(FScanner &sc, DOptionMenuDescriptor *desc)
|
||||||
PClass *cls = PClass::FindClass(buildname);
|
PClass *cls = PClass::FindClass(buildname);
|
||||||
if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem"))
|
if (cls != nullptr && cls->IsDescendantOf("OptionMenuItem"))
|
||||||
{
|
{
|
||||||
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", false));
|
auto func = dyn_cast<PFunction>(cls->Symbols.FindSymbol("Init", true));
|
||||||
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
|
if (func != nullptr && !(func->Variants[0].Flags & (VARF_Protected | VARF_Private))) // skip internal classes which have a protexted init method.
|
||||||
{
|
{
|
||||||
auto &args = func->Variants[0].Proto->ArgumentTypes;
|
auto &args = func->Variants[0].Proto->ArgumentTypes;
|
||||||
|
@ -973,13 +973,13 @@ static void BuildEpisodeMenu()
|
||||||
if ((*desc)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor)))
|
if ((*desc)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor)))
|
||||||
{
|
{
|
||||||
DListMenuDescriptor *ld = static_cast<DListMenuDescriptor*>(*desc);
|
DListMenuDescriptor *ld = static_cast<DListMenuDescriptor*>(*desc);
|
||||||
int posy = ld->mYpos;
|
int posy = (int)ld->mYpos;
|
||||||
int topy = posy;
|
int topy = posy;
|
||||||
|
|
||||||
// Get lowest y coordinate of any static item in the menu
|
// Get lowest y coordinate of any static item in the menu
|
||||||
for(unsigned i = 0; i < ld->mItems.Size(); i++)
|
for(unsigned i = 0; i < ld->mItems.Size(); i++)
|
||||||
{
|
{
|
||||||
int y = ld->mItems[i]->GetY();
|
int y = (int)ld->mItems[i]->GetY();
|
||||||
if (y < topy) topy = y;
|
if (y < topy) topy = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1073,13 +1073,13 @@ static void BuildPlayerclassMenu()
|
||||||
// add player display
|
// add player display
|
||||||
ld->mSelectedItem = ld->mItems.Size();
|
ld->mSelectedItem = ld->mItems.Size();
|
||||||
|
|
||||||
int posy = ld->mYpos;
|
int posy = (int)ld->mYpos;
|
||||||
int topy = posy;
|
int topy = posy;
|
||||||
|
|
||||||
// Get lowest y coordinate of any static item in the menu
|
// Get lowest y coordinate of any static item in the menu
|
||||||
for(unsigned i = 0; i < ld->mItems.Size(); i++)
|
for(unsigned i = 0; i < ld->mItems.Size(); i++)
|
||||||
{
|
{
|
||||||
int y = ld->mItems[i]->GetY();
|
int y = (int)ld->mItems[i]->GetY();
|
||||||
if (y < topy) topy = y;
|
if (y < topy) topy = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1333,8 +1333,8 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
||||||
if ((*desc)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor)))
|
if ((*desc)->IsKindOf(RUNTIME_CLASS(DListMenuDescriptor)))
|
||||||
{
|
{
|
||||||
DListMenuDescriptor *ld = static_cast<DListMenuDescriptor*>(*desc);
|
DListMenuDescriptor *ld = static_cast<DListMenuDescriptor*>(*desc);
|
||||||
int x = ld->mXpos;
|
int x = (int)ld->mXpos;
|
||||||
int y = ld->mYpos;
|
int y = (int)ld->mYpos;
|
||||||
|
|
||||||
// Delete previous contents
|
// Delete previous contents
|
||||||
for(unsigned i=0; i<ld->mItems.Size(); i++)
|
for(unsigned i=0; i<ld->mItems.Size(); i++)
|
||||||
|
@ -1363,7 +1363,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
||||||
// Get lowest y coordinate of any static item in the menu
|
// Get lowest y coordinate of any static item in the menu
|
||||||
for(unsigned i = 0; i < ld->mItems.Size(); i++)
|
for(unsigned i = 0; i < ld->mItems.Size(); i++)
|
||||||
{
|
{
|
||||||
int y = ld->mItems[i]->GetY();
|
int y = (int)ld->mItems[i]->GetY();
|
||||||
if (y < topy) topy = y;
|
if (y < topy) topy = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1380,7 +1380,7 @@ void M_StartupSkillMenu(FGameStartup *gs)
|
||||||
{
|
{
|
||||||
ld->mItems[i]->OffsetPositionY(topdelta);
|
ld->mItems[i]->OffsetPositionY(topdelta);
|
||||||
}
|
}
|
||||||
y = ld->mYpos = posy - topdelta;
|
ld->mYpos = y = posy - topdelta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -653,6 +653,7 @@ xx(Link)
|
||||||
xx(Goodbye)
|
xx(Goodbye)
|
||||||
xx(Require)
|
xx(Require)
|
||||||
xx(Exclude)
|
xx(Exclude)
|
||||||
|
xx(Userstring)
|
||||||
|
|
||||||
// Special menus
|
// Special menus
|
||||||
xx(Mainmenu)
|
xx(Mainmenu)
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
#include "virtual.h"
|
||||||
|
|
||||||
// The conversations as they exist inside a SCRIPTxx lump.
|
// The conversations as they exist inside a SCRIPTxx lump.
|
||||||
struct Response
|
struct Response
|
||||||
|
@ -112,7 +113,6 @@ static FDialogueMap ClassRoots;
|
||||||
static int ConversationMenuY;
|
static int ConversationMenuY;
|
||||||
|
|
||||||
static int ConversationPauseTic;
|
static int ConversationPauseTic;
|
||||||
static bool ShowGold;
|
|
||||||
static int StaticLastReply;
|
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);
|
||||||
|
@ -125,9 +125,6 @@ static void TerminalResponse (const char *str);
|
||||||
|
|
||||||
static FStrifeDialogueNode *PrevNode;
|
static FStrifeDialogueNode *PrevNode;
|
||||||
|
|
||||||
#define NUM_RANDOM_LINES 10
|
|
||||||
#define NUM_RANDOM_GOODBYES 3
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// GetStrifeType
|
// GetStrifeType
|
||||||
|
@ -352,7 +349,7 @@ static FStrifeDialogueNode *ReadRetailNode (FileReader *lump, DWORD &prevSpeaker
|
||||||
|
|
||||||
// The speaker's portrait, if any.
|
// The speaker's portrait, if any.
|
||||||
speech.Dialogue[0] = 0; //speech.Backdrop[8] = 0;
|
speech.Dialogue[0] = 0; //speech.Backdrop[8] = 0;
|
||||||
node->Backdrop = TexMan.CheckForTexture (speech.Backdrop, FTexture::TEX_MiscPatch);
|
node->Backdrop = speech.Backdrop;
|
||||||
|
|
||||||
// The speaker's voice for this node, if any.
|
// The speaker's voice for this node, if any.
|
||||||
speech.Backdrop[0] = 0; //speech.Sound[8] = 0;
|
speech.Backdrop[0] = 0; //speech.Sound[8] = 0;
|
||||||
|
@ -426,7 +423,7 @@ static FStrifeDialogueNode *ReadTeaserNode (FileReader *lump, DWORD &prevSpeaker
|
||||||
node->Dialogue = speech.Dialogue;
|
node->Dialogue = speech.Dialogue;
|
||||||
|
|
||||||
// The Teaser version doesn't have portraits.
|
// The Teaser version doesn't have portraits.
|
||||||
node->Backdrop.SetInvalid();
|
node->Backdrop = "";
|
||||||
|
|
||||||
// The speaker's voice for this node, if any.
|
// The speaker's voice for this node, if any.
|
||||||
if (speech.VoiceNumber != 0)
|
if (speech.VoiceNumber != 0)
|
||||||
|
@ -690,8 +687,18 @@ static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SendConversationReply(int node, int reply)
|
DEFINE_ACTION_FUNCTION(FStrifeDialogueReply, ShouldSkipReply)
|
||||||
{
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FStrifeDialogueReply);
|
||||||
|
PARAM_POINTER(player, player_t);
|
||||||
|
ACTION_RETURN_BOOL(ShouldSkipReply(self, player));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DConversationMenu, SendConversationReply)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_INT(node);
|
||||||
|
PARAM_INT(reply);
|
||||||
switch (node)
|
switch (node)
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
|
@ -709,6 +716,7 @@ static void SendConversationReply(int node, int reply)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
StaticLastReply = reply;
|
StaticLastReply = reply;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -733,438 +741,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// The conversation menu
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
class DConversationMenu : public DMenu
|
|
||||||
{
|
|
||||||
DECLARE_CLASS(DConversationMenu, DMenu)
|
|
||||||
|
|
||||||
public:
|
|
||||||
FString mSpeaker;
|
|
||||||
DBrokenLines *mDialogueLines;
|
|
||||||
TArray<FString> mResponseLines;
|
|
||||||
TArray<unsigned int> mResponses;
|
|
||||||
bool mShowGold;
|
|
||||||
FStrifeDialogueNode *mCurNode;
|
|
||||||
int mYpos;
|
|
||||||
player_t *mPlayer;
|
|
||||||
int mSelection;
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player, int activereply)
|
|
||||||
{
|
|
||||||
mCurNode = CurNode;
|
|
||||||
mPlayer = player;
|
|
||||||
mDialogueLines = NULL;
|
|
||||||
mShowGold = false;
|
|
||||||
|
|
||||||
// Format the speaker's message.
|
|
||||||
const char * toSay = CurNode->Dialogue;
|
|
||||||
if (strncmp (toSay, "RANDOM_", 7) == 0)
|
|
||||||
{
|
|
||||||
FString dlgtext;
|
|
||||||
|
|
||||||
dlgtext.Format("TXT_%s_%02d", toSay, 1+(pr_randomspeech() % NUM_RANDOM_LINES));
|
|
||||||
toSay = GStrings[dlgtext];
|
|
||||||
if (toSay == NULL)
|
|
||||||
{
|
|
||||||
toSay = GStrings["TXT_GOAWAY"]; // Ok, it's lame - but it doesn't look like an error to the player. ;)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// handle string table replacement
|
|
||||||
if (toSay[0] == '$')
|
|
||||||
{
|
|
||||||
toSay = GStrings(toSay + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (toSay == NULL)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
int r = -1;
|
|
||||||
int i,j;
|
|
||||||
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
|
|
||||||
{
|
|
||||||
r++;
|
|
||||||
if (ShouldSkipReply(reply, mPlayer))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (activereply == r) mSelection = i - 1;
|
|
||||||
|
|
||||||
mShowGold |= reply->NeedsGold;
|
|
||||||
|
|
||||||
const char *ReplyText = reply->Reply;
|
|
||||||
if (ReplyText[0] == '$')
|
|
||||||
{
|
|
||||||
ReplyText = GStrings(ReplyText + 1);
|
|
||||||
}
|
|
||||||
FString ReplyString = ReplyText;
|
|
||||||
if (reply->NeedsGold) ReplyString.AppendFormat(" for %u", reply->PrintAmount);
|
|
||||||
|
|
||||||
FBrokenLines *ReplyLines = V_BreakLines (SmallFont, 320-50-10, ReplyString);
|
|
||||||
|
|
||||||
mResponses.Push(mResponseLines.Size());
|
|
||||||
for (j = 0; ReplyLines[j].Width >= 0; ++j)
|
|
||||||
{
|
|
||||||
mResponseLines.Push(ReplyLines[j].Text);
|
|
||||||
}
|
|
||||||
|
|
||||||
++i;
|
|
||||||
V_FreeBrokenLines (ReplyLines);
|
|
||||||
}
|
|
||||||
if (mSelection == -1)
|
|
||||||
{
|
|
||||||
mSelection = r < activereply ? r + 1 : 0;
|
|
||||||
}
|
|
||||||
const char *goodbyestr = CurNode->Goodbye;
|
|
||||||
if (*goodbyestr == 0)
|
|
||||||
{
|
|
||||||
char goodbye[25];
|
|
||||||
mysnprintf(goodbye, countof(goodbye), "TXT_RANDOMGOODBYE_%d", 1 + (pr_randomspeech() % NUM_RANDOM_GOODBYES));
|
|
||||||
goodbyestr = GStrings[goodbye];
|
|
||||||
}
|
|
||||||
else if (strncmp(goodbyestr, "RANDOM_", 7) == 0)
|
|
||||||
{
|
|
||||||
FString byetext;
|
|
||||||
|
|
||||||
byetext.Format("TXT_%s_%02d", goodbyestr, 1 + (pr_randomspeech() % NUM_RANDOM_LINES));
|
|
||||||
goodbyestr = GStrings[byetext];
|
|
||||||
}
|
|
||||||
else if (goodbyestr[0] == '$')
|
|
||||||
{
|
|
||||||
goodbyestr = GStrings(goodbyestr + 1);
|
|
||||||
}
|
|
||||||
if (goodbyestr == nullptr) goodbyestr = "Bye.";
|
|
||||||
mResponses.Push(mResponseLines.Size());
|
|
||||||
mResponseLines.Push(FString(goodbyestr));
|
|
||||||
|
|
||||||
// Determine where the top of the reply list should be positioned.
|
|
||||||
mYpos = MIN<int> (140, 192 - mResponseLines.Size() * OptionSettings.mLinespacing);
|
|
||||||
i = 44 + count * (OptionSettings.mLinespacing + 2);
|
|
||||||
if (mYpos - 100 < i - screen->GetHeight() / CleanYfac / 2)
|
|
||||||
{
|
|
||||||
mYpos = i - screen->GetHeight() / CleanYfac / 2 + 100;
|
|
||||||
}
|
|
||||||
ConversationMenuY = mYpos;
|
|
||||||
//ConversationMenu.indent = 50;
|
|
||||||
|
|
||||||
// Because replies can be selectively hidden mResponses.Size() won't be consistent.
|
|
||||||
// So make sure mSelection doesn't exceed mResponses.Size(). [FishyClockwork]
|
|
||||||
if (mSelection >= (int)mResponses.Size())
|
|
||||||
{
|
|
||||||
mSelection = mResponses.Size() - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
void OnDestroy() override
|
|
||||||
{
|
|
||||||
mDialogueLines->Destroy();
|
|
||||||
mDialogueLines = NULL;
|
|
||||||
I_SetMusicVolume (1.f);
|
|
||||||
Super::OnDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DimAllowed()
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
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 >= (int)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 ((unsigned)mSelection >= mResponses.Size())
|
|
||||||
{
|
|
||||||
SendConversationReply(-1, replynum);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Send dialogue and reply numbers across the wire.
|
|
||||||
SendConversationReply(mCurNode->ThisNodeNum, replynum);
|
|
||||||
}
|
|
||||||
Close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool MouseEvent(int type, int x, int y)
|
|
||||||
{
|
|
||||||
int sel = -1;
|
|
||||||
int fh = OptionSettings.mLinespacing;
|
|
||||||
|
|
||||||
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
|
||||||
x = ((x - (screen->GetWidth() / 2)) / CleanXfac) + 160;
|
|
||||||
y = ((y - (screen->GetHeight() / 2)) / CleanYfac) + 100;
|
|
||||||
|
|
||||||
if (x >= 24 && x <= 320-24 && y >= mYpos && y < mYpos + fh * (int)mResponseLines.Size())
|
|
||||||
{
|
|
||||||
sel = (y - mYpos) / fh;
|
|
||||||
for(unsigned i=0;i<mResponses.Size(); i++)
|
|
||||||
{
|
|
||||||
if ((int)mResponses[i] > sel)
|
|
||||||
{
|
|
||||||
sel = i-1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sel != -1 && sel != mSelection)
|
|
||||||
{
|
|
||||||
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
|
||||||
}
|
|
||||||
mSelection = sel;
|
|
||||||
if (type == MOUSE_Release)
|
|
||||||
{
|
|
||||||
return MenuEvent(MKEY_Enter, true);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool Responder(event_t *ev)
|
|
||||||
{
|
|
||||||
if (demoplayback)
|
|
||||||
{ // No interaction during demo playback
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (ev->type == EV_GUI_Event && ev->subtype == EV_GUI_Char && ev->data1 >= '0' && ev->data1 <= '9')
|
|
||||||
{ // Activate an item of type numberedmore (dialogue only)
|
|
||||||
mSelection = ev->data1 == '0' ? 9 : ev->data1 - '1';
|
|
||||||
return MenuEvent(MKEY_Enter, false);
|
|
||||||
}
|
|
||||||
return Super::Responder(ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// DrawConversationMenu
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
void Drawer()
|
|
||||||
{
|
|
||||||
const char *speakerName;
|
|
||||||
int x, y, linesize;
|
|
||||||
int width, fontheight;
|
|
||||||
|
|
||||||
player_t *cp = &players[consoleplayer];
|
|
||||||
|
|
||||||
assert (mDialogueLines != NULL);
|
|
||||||
assert (mCurNode != NULL);
|
|
||||||
|
|
||||||
FStrifeDialogueNode *CurNode = mCurNode;
|
|
||||||
|
|
||||||
if (CurNode == NULL)
|
|
||||||
{
|
|
||||||
Close ();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// [CW] Freeze the game depending on MAPINFO options.
|
|
||||||
if (ConversationPauseTic < gametic && !multiplayer && !(level.flags2 & LEVEL2_CONV_SINGLE_UNFREEZE))
|
|
||||||
{
|
|
||||||
menuactive = MENU_On;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurNode->Backdrop.isValid())
|
|
||||||
{
|
|
||||||
screen->DrawTexture (TexMan(CurNode->Backdrop), 0, 0, DTA_320x200, true, TAG_DONE);
|
|
||||||
}
|
|
||||||
x = 16 * screen->GetWidth() / 320;
|
|
||||||
y = 16 * screen->GetHeight() / 200;
|
|
||||||
linesize = 10 * CleanYfac;
|
|
||||||
|
|
||||||
// Who is talking to you?
|
|
||||||
if (CurNode->SpeakerName.IsNotEmpty())
|
|
||||||
{
|
|
||||||
speakerName = CurNode->SpeakerName;
|
|
||||||
if (speakerName[0] == '$') speakerName = GStrings(speakerName+1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
speakerName = cp->ConversationNPC->GetTag("Person");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dim the screen behind the dialogue (but only if there is no backdrop).
|
|
||||||
if (!CurNode->Backdrop.isValid())
|
|
||||||
{
|
|
||||||
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 == NULL ? linesize * i + 6 * CleanYfac
|
|
||||||
: linesize * i + 6 * CleanYfac + linesize * 3/2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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<int>(mResponseLines.Size() * OptionSettings.mLinespacing + 4, 200 - mYpos) * CleanYfac);
|
|
||||||
|
|
||||||
if (speakerName != NULL)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ShowGold)
|
|
||||||
{
|
|
||||||
auto cointype = PClass::FindActor("Coin");
|
|
||||||
if (cointype)
|
|
||||||
{
|
|
||||||
AInventory *coin = cp->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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
y = mYpos;
|
|
||||||
fontheight = OptionSettings.mLinespacing;
|
|
||||||
|
|
||||||
int response = 0;
|
|
||||||
for (unsigned i = 0; i < mResponseLines.Size(); i++, y += fontheight)
|
|
||||||
{
|
|
||||||
width = SmallFont->StringWidth(mResponseLines[i]);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(DConversationMenu, true, false)
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// P_FreeStrifeConversations
|
// P_FreeStrifeConversations
|
||||||
|
@ -1184,7 +760,7 @@ void P_FreeStrifeConversations ()
|
||||||
ClassRoots.Clear();
|
ClassRoots.Clear();
|
||||||
|
|
||||||
PrevNode = NULL;
|
PrevNode = NULL;
|
||||||
if (CurrentMenu != NULL && CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
if (CurrentMenu != NULL && CurrentMenu->IsKindOf("ConversationMenu"))
|
||||||
{
|
{
|
||||||
CurrentMenu->Close();
|
CurrentMenu->Close();
|
||||||
}
|
}
|
||||||
|
@ -1282,8 +858,21 @@ 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, StaticLastReply);
|
// Create the menu. This may be a user-defined class so check if it is good to use.
|
||||||
|
FName cls = CurNode->MenuClassName;
|
||||||
|
if (cls == NAME_None) cls = gameinfo.DefaultConversationMenuClass;
|
||||||
|
if (cls == NAME_None) cls = "ConversationMenu";
|
||||||
|
auto mcls = PClass::FindClass(cls);
|
||||||
|
if (mcls == nullptr || !mcls->IsDescendantOf("ConversationMenu")) mcls = PClass::FindClass("ConversationMenu");
|
||||||
|
assert(mcls);
|
||||||
|
|
||||||
|
auto cmenu = mcls->CreateNew();
|
||||||
|
IFVIRTUALPTRNAME(cmenu, "ConversationMenu", Init)
|
||||||
|
{
|
||||||
|
VMValue params[] = { cmenu, CurNode, pc->player, StaticLastReply };
|
||||||
|
VMReturn ret(&ConversationMenuY);
|
||||||
|
GlobalVMStack.Call(func, params, countof(params), &ret, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (CurNode != PrevNode)
|
if (CurNode != PrevNode)
|
||||||
{ // Only reset the selection if showing a different menu.
|
{ // Only reset the selection if showing a different menu.
|
||||||
|
@ -1293,8 +882,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
|
||||||
|
|
||||||
// And open the menu
|
// And open the menu
|
||||||
M_StartControlPanel (false);
|
M_StartControlPanel (false);
|
||||||
M_ActivateMenu(cmenu);
|
M_ActivateMenu((DMenu*)cmenu);
|
||||||
ConversationPauseTic = gametic + 20;
|
|
||||||
menuactive = MENU_OnNoPause;
|
menuactive = MENU_OnNoPause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1531,8 +1119,7 @@ void P_ConversationCommand (int netcode, int pnum, BYTE **stream)
|
||||||
|
|
||||||
// The conversation menus are normally closed by the menu code, but that
|
// The conversation menus are normally closed by the menu code, but that
|
||||||
// doesn't happen during demo playback, so we need to do it here.
|
// doesn't happen during demo playback, so we need to do it here.
|
||||||
if (demoplayback && CurrentMenu != NULL &&
|
if (demoplayback && CurrentMenu != NULL && CurrentMenu->IsKindOf("ConversationMenu"))
|
||||||
CurrentMenu->IsKindOf(RUNTIME_CLASS(DConversationMenu)))
|
|
||||||
{
|
{
|
||||||
CurrentMenu->Close();
|
CurrentMenu->Close();
|
||||||
}
|
}
|
||||||
|
@ -1598,3 +1185,28 @@ static void TerminalResponse (const char *str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, DropType);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, ThisNodeNum);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, ItemCheckNode);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, SpeakerType);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, SpeakerName);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, SpeakerVoice);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, Backdrop);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, Dialogue);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, Goodbye);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, Children);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, MenuClassName);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueNode, UserData);
|
||||||
|
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, Next);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, GiveType);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, ActionSpecial);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, Args);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, PrintAmount);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, Reply);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, QuickYes);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, QuickNo);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, LogString);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, NextNode);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, LogNumber);
|
||||||
|
DEFINE_FIELD(FStrifeDialogueReply, NeedsGold);
|
||||||
|
|
|
@ -28,11 +28,13 @@ struct FStrifeDialogueNode
|
||||||
PClassActor *SpeakerType;
|
PClassActor *SpeakerType;
|
||||||
FString SpeakerName;
|
FString SpeakerName;
|
||||||
FSoundID SpeakerVoice;
|
FSoundID SpeakerVoice;
|
||||||
FTextureID Backdrop;
|
FString Backdrop;
|
||||||
FString Dialogue;
|
FString Dialogue;
|
||||||
FString Goodbye; // must init to null for binary scripts to work as intended
|
FString Goodbye; // must init to null for binary scripts to work as intended
|
||||||
|
|
||||||
FStrifeDialogueReply *Children;
|
FStrifeDialogueReply *Children;
|
||||||
|
FName MenuClassName;
|
||||||
|
FString UserData;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FStrifeDialogueReply holds responses the player can give to the NPC
|
// FStrifeDialogueReply holds responses the player can give to the NPC
|
||||||
|
|
|
@ -316,7 +316,14 @@ class USDFParser : public UDMFParserBase
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Panel:
|
case NAME_Panel:
|
||||||
node->Backdrop = TexMan.CheckForTexture (CheckString(key), FTexture::TEX_MiscPatch);
|
node->Backdrop = CheckString(key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_Userstring:
|
||||||
|
if (namespace_bits == Zd)
|
||||||
|
{
|
||||||
|
node->UserData = CheckString(key);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NAME_Voice:
|
case NAME_Voice:
|
||||||
|
@ -391,6 +398,7 @@ class USDFParser : public UDMFParserBase
|
||||||
{
|
{
|
||||||
PClassActor *type = NULL;
|
PClassActor *type = NULL;
|
||||||
int dlgid = -1;
|
int dlgid = -1;
|
||||||
|
FName clsid;
|
||||||
unsigned int startpos = StrifeDialogues.Size();
|
unsigned int startpos = StrifeDialogues.Size();
|
||||||
|
|
||||||
while (!sc.CheckToken('}'))
|
while (!sc.CheckToken('}'))
|
||||||
|
@ -415,6 +423,13 @@ class USDFParser : public UDMFParserBase
|
||||||
dlgid = CheckInt(key);
|
dlgid = CheckInt(key);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NAME_Class:
|
||||||
|
if (namespace_bits == Zd)
|
||||||
|
{
|
||||||
|
clsid = CheckString(key);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -440,6 +455,7 @@ class USDFParser : public UDMFParserBase
|
||||||
for(;startpos < StrifeDialogues.Size(); startpos++)
|
for(;startpos < StrifeDialogues.Size(); startpos++)
|
||||||
{
|
{
|
||||||
StrifeDialogues[startpos]->SpeakerType = type;
|
StrifeDialogues[startpos]->SpeakerType = type;
|
||||||
|
StrifeDialogues[startpos]->MenuClassName = clsid;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,9 @@
|
||||||
static TArray<FPropertyInfo*> properties;
|
static TArray<FPropertyInfo*> properties;
|
||||||
static TArray<AFuncDesc> AFTable;
|
static TArray<AFuncDesc> AFTable;
|
||||||
static TArray<FieldDesc> FieldTable;
|
static TArray<FieldDesc> FieldTable;
|
||||||
|
extern int BackbuttonTime;
|
||||||
|
extern float BackbuttonAlpha;
|
||||||
|
static AWeapon *wpnochg;
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -909,11 +912,20 @@ void InitThingdef()
|
||||||
fieldptr = new PField("gametic", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gametic);
|
fieldptr = new PField("gametic", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gametic);
|
||||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||||
|
|
||||||
|
fieldptr = new PField("demoplayback", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&demoplayback);
|
||||||
|
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||||
|
|
||||||
|
fieldptr = new PField("BackbuttonTime", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&BackbuttonTime);
|
||||||
|
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||||
|
|
||||||
|
fieldptr = new PField("BackbuttonAlpha", TypeFloat32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&BackbuttonAlpha);
|
||||||
|
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||||
|
|
||||||
|
|
||||||
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
|
// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag.
|
||||||
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
|
// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution'
|
||||||
// is to create a static variable from it and reference that in the script. Yuck!!!
|
// is to create a static variable from it and reference that in the script. Yuck!!!
|
||||||
static AWeapon *wpnochg = WP_NOCHANGE;
|
wpnochg = WP_NOCHANGE;
|
||||||
fieldptr = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg);
|
fieldptr = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg);
|
||||||
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
|
||||||
|
|
||||||
|
@ -1216,6 +1228,14 @@ DEFINE_ACTION_FUNCTION(FStringStruct, Mid)
|
||||||
ACTION_RETURN_STRING(s);
|
ACTION_RETURN_STRING(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(FStringStruct, Left)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||||
|
PARAM_UINT(len);
|
||||||
|
FString s = self->Left(len);
|
||||||
|
ACTION_RETURN_STRING(s);
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(FStringStruct, Truncate)
|
DEFINE_ACTION_FUNCTION(FStringStruct, Truncate)
|
||||||
{
|
{
|
||||||
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
PARAM_SELF_STRUCT_PROLOGUE(FString);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "zscript/menu/textentermenu.txt"
|
#include "zscript/menu/textentermenu.txt"
|
||||||
#include "zscript/menu/videomenu.txt"
|
#include "zscript/menu/videomenu.txt"
|
||||||
#include "zscript/menu/readthis.txt"
|
#include "zscript/menu/readthis.txt"
|
||||||
|
#include "zscript/menu/conversationmenu.txt"
|
||||||
|
|
||||||
#include "zscript/inventory/inventory.txt"
|
#include "zscript/inventory/inventory.txt"
|
||||||
#include "zscript/inventory/inv_misc.txt"
|
#include "zscript/inventory/inv_misc.txt"
|
||||||
|
|
|
@ -300,6 +300,7 @@ struct GameInfoStruct native
|
||||||
native int gametype;
|
native int gametype;
|
||||||
native bool norandomplayerclass;
|
native bool norandomplayerclass;
|
||||||
native Array<Name> infoPages;
|
native Array<Name> infoPages;
|
||||||
|
native String mBackButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Object native
|
class Object native
|
||||||
|
@ -463,6 +464,7 @@ struct LevelLocals native
|
||||||
native bool nomonsters;
|
native bool nomonsters;
|
||||||
native bool frozen;
|
native bool frozen;
|
||||||
native bool infinite_flight;
|
native bool infinite_flight;
|
||||||
|
native bool no_dlg_freeze;
|
||||||
// level_info_t *info cannot be done yet.
|
// level_info_t *info cannot be done yet.
|
||||||
|
|
||||||
native String GetUDMFString(int type, int index, Name key);
|
native String GetUDMFString(int type, int index, Name key);
|
||||||
|
@ -579,6 +581,7 @@ struct StringStruct native
|
||||||
native vararg void AppendFormat(String fmt, ...);
|
native vararg void AppendFormat(String fmt, ...);
|
||||||
|
|
||||||
native void Replace(String pattern, String replacement);
|
native void Replace(String pattern, String replacement);
|
||||||
|
native String Left(int len);
|
||||||
native String Mid(int pos = 0, int len = 2147483647);
|
native String Mid(int pos = 0, int len = 2147483647);
|
||||||
native void Truncate(int newlen);
|
native void Truncate(int newlen);
|
||||||
native String CharAt(int pos);
|
native String CharAt(int pos);
|
||||||
|
|
516
wadsrc/static/zscript/menu/conversationmenu.txt
Normal file
516
wadsrc/static/zscript/menu/conversationmenu.txt
Normal file
|
@ -0,0 +1,516 @@
|
||||||
|
/*
|
||||||
|
** 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<Actor> DropType;
|
||||||
|
native int ThisNodeNum;
|
||||||
|
native int ItemCheckNode;
|
||||||
|
|
||||||
|
native Class<Actor> SpeakerType;
|
||||||
|
native String SpeakerName;
|
||||||
|
native Sound SpeakerVoice;
|
||||||
|
native String 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<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;
|
||||||
|
|
||||||
|
native bool ShouldSkipReply(PlayerInfo player);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ConversationMenu : Menu
|
||||||
|
{
|
||||||
|
String mSpeaker;
|
||||||
|
BrokenLines mDialogueLines;
|
||||||
|
Array<String> mResponseLines;
|
||||||
|
Array<uint> mResponses;
|
||||||
|
bool mShowGold;
|
||||||
|
StrifeDialogueNode mCurNode;
|
||||||
|
int mYpos;
|
||||||
|
PlayerInfo mPlayer;
|
||||||
|
int mSelection;
|
||||||
|
int ConversationPauseTic;
|
||||||
|
|
||||||
|
int SpeechWidth;
|
||||||
|
int ReplyWidth;
|
||||||
|
|
||||||
|
native static void SendConversationReply(int node, int reply);
|
||||||
|
|
||||||
|
const NUM_RANDOM_LINES = 10;
|
||||||
|
const NUM_RANDOM_GOODBYES = 3;
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
// returns the y position of the replies boy for positioning the terminal response.
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
virtual int Init(StrifeDialogueNode CurNode, PlayerInfo player, int activereply)
|
||||||
|
{
|
||||||
|
mCurNode = CurNode;
|
||||||
|
mPlayer = player;
|
||||||
|
mShowGold = false;
|
||||||
|
ConversationPauseTic = gametic + 20;
|
||||||
|
DontDim = true;
|
||||||
|
|
||||||
|
ReplyWidth = 320-50-10;
|
||||||
|
SpeechWidth = screen.GetWidth()/CleanXfac - 24*2;
|
||||||
|
|
||||||
|
FormatSpeakerMessage();
|
||||||
|
return FormatReplies(activereply);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
virtual int FormatReplies(int activereply)
|
||||||
|
{
|
||||||
|
mSelection = -1;
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (reply.NeedsGold) ReplyText.AppendFormat(" for %u", reply.PrintAmount);
|
||||||
|
|
||||||
|
let ReplyLines = SmallFont.BreakLines (ReplyText, ReplyWidth);
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (goodbyestr.Length() == 0 || goodbyestr.CharAt(0) == "$") goodbyestr = "Bye.";
|
||||||
|
mResponses.Push(mResponseLines.Size());
|
||||||
|
mResponseLines.Push(goodbyestr);
|
||||||
|
|
||||||
|
// Determine where the top of the reply list should be positioned.
|
||||||
|
mYpos = MIN (140, 192 - mResponseLines.Size() * OptionMenuSettings.mLinespacing);
|
||||||
|
i = 44 + mResponseLines.Size() * OptionMenuSettings.mLinespacing;
|
||||||
|
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);
|
||||||
|
if (toSay.CharAt(0) == "$") toSay = Stringtable.Localize("$TXT_GOAWAY");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// handle string table replacement
|
||||||
|
toSay = Stringtable.Localize(toSay);
|
||||||
|
}
|
||||||
|
if (toSay.Length() == 0)
|
||||||
|
{
|
||||||
|
toSay = ".";
|
||||||
|
}
|
||||||
|
mDialogueLines = SmallFont.BreakLines(toSay, SpeechWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
override void OnDestroy()
|
||||||
|
{
|
||||||
|
mDialogueLines.Destroy();
|
||||||
|
SetMusicVolume (1);
|
||||||
|
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;
|
||||||
|
int fh = OptionMenuSettings.mLinespacing;
|
||||||
|
|
||||||
|
// convert x/y from screen to virtual coordinates, according to CleanX/Yfac use in DrawTexture
|
||||||
|
x = ((x - (screen.GetWidth() / 2)) / CleanXfac) + 160;
|
||||||
|
y = ((y - (screen.GetHeight() / 2)) / CleanYfac) + 100;
|
||||||
|
|
||||||
|
if (x >= 24 && x <= 320-24 && y >= mYpos && y < mYpos + fh * mResponseLines.Size())
|
||||||
|
{
|
||||||
|
sel = (y - mYpos) / fh;
|
||||||
|
for(int i = 0; i < mResponses.Size(); i++)
|
||||||
|
{
|
||||||
|
if (mResponses[i] > sel)
|
||||||
|
{
|
||||||
|
sel = i-1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sel != -1 && sel != mSelection)
|
||||||
|
{
|
||||||
|
//S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", snd_menuvolume, ATTN_NONE);
|
||||||
|
}
|
||||||
|
mSelection = sel;
|
||||||
|
if (type == MOUSE_Release)
|
||||||
|
{
|
||||||
|
return MenuEvent(MKEY_Enter, true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
override bool Responder(InputEventData ev)
|
||||||
|
{
|
||||||
|
if (demoplayback)
|
||||||
|
{ // No interaction during demo playback
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (ev.type == InputEventData.GUI_Event && ev.subtype == InputEventData.GUI_Char && ev.data1 >= 48 && ev.data1 <= 57)
|
||||||
|
{ // Activate an item of type numberedmore (dialogue only)
|
||||||
|
mSelection = ev.data1 == 48 ? 9 : ev.data1 - 49;
|
||||||
|
return MenuEvent(MKEY_Enter, false);
|
||||||
|
}
|
||||||
|
return Super.Responder(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// Draw the backdrop, returns true if the text background should be dimmed
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
virtual bool DrawBackdrop()
|
||||||
|
{
|
||||||
|
let tex = TexMan.CheckForTexture (mCurNode.Backdrop, TexMan.Type_MiscPatch);
|
||||||
|
if (tex.isValid())
|
||||||
|
{
|
||||||
|
screen.DrawTexture(tex, 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()
|
||||||
|
{
|
||||||
|
// [CW] Freeze the game depending on MAPINFO options.
|
||||||
|
if (ConversationPauseTic < gametic && !multiplayer && !level.no_dlg_freeze)
|
||||||
|
{
|
||||||
|
menuactive = Menu.On;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,11 +4,11 @@ class ListMenuDescriptor : MenuDescriptor native
|
||||||
{
|
{
|
||||||
native Array<ListMenuItem> mItems;
|
native Array<ListMenuItem> mItems;
|
||||||
native int mSelectedItem;
|
native int mSelectedItem;
|
||||||
native int mSelectOfsX;
|
native double mSelectOfsX;
|
||||||
native int mSelectOfsY;
|
native double mSelectOfsY;
|
||||||
native TextureID mSelector;
|
native TextureID mSelector;
|
||||||
native int mDisplayTop;
|
native int mDisplayTop;
|
||||||
native int mXpos, mYpos;
|
native double mXpos, mYpos;
|
||||||
native int mWLeft, mWRight;
|
native int mWLeft, mWRight;
|
||||||
native int mLinespacing; // needs to be stored for dynamically created menus
|
native int mLinespacing; // needs to be stored for dynamically created menus
|
||||||
native int mAutoselect; // this can only be set by internal menu creation functions
|
native int mAutoselect; // this can only be set by internal menu creation functions
|
||||||
|
@ -47,20 +47,20 @@ class ListMenu : Menu
|
||||||
|
|
||||||
virtual void Init(Menu parent = NULL, ListMenuDescriptor desc = NULL)
|
virtual void Init(Menu parent = NULL, ListMenuDescriptor desc = NULL)
|
||||||
{
|
{
|
||||||
mParentMenu = parent;
|
Super.Init(parent);
|
||||||
mDesc = desc;
|
mDesc = desc;
|
||||||
if (desc.mCenter)
|
if (desc.mCenter)
|
||||||
{
|
{
|
||||||
int center = 160;
|
double center = 160;
|
||||||
for(int i=0; i < mDesc.mItems.Size(); i++)
|
for(int i=0; i < mDesc.mItems.Size(); i++)
|
||||||
{
|
{
|
||||||
int xpos = mDesc.mItems[i].GetX();
|
double xpos = mDesc.mItems[i].GetX();
|
||||||
int width = mDesc.mItems[i].GetWidth();
|
int width = mDesc.mItems[i].GetWidth();
|
||||||
int curx = mDesc.mSelectOfsX;
|
double curx = mDesc.mSelectOfsX;
|
||||||
|
|
||||||
if (width > 0 && mDesc.mItems[i].Selectable())
|
if (width > 0 && mDesc.mItems[i].Selectable())
|
||||||
{
|
{
|
||||||
int left = 160 - (width - curx) / 2 - curx;
|
double left = 160 - (width - curx) / 2 - curx;
|
||||||
if (left < center) center = left;
|
if (left < center) center = left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
class ListMenuItem : MenuItemBase
|
class ListMenuItem : MenuItemBase
|
||||||
{
|
{
|
||||||
void DrawSelector(int xofs, int yofs, TextureID tex)
|
void DrawSelector(double xofs, double yofs, TextureID tex)
|
||||||
{
|
{
|
||||||
if (tex.isNull())
|
if (tex.isNull())
|
||||||
{
|
{
|
||||||
|
@ -68,7 +68,7 @@ class ListMenuItemStaticPatch : ListMenuItem
|
||||||
TextureID mTexture;
|
TextureID mTexture;
|
||||||
bool mCentered;
|
bool mCentered;
|
||||||
|
|
||||||
void Init(int x, int y, TextureID patch, bool centered = false)
|
void Init(double x, double y, TextureID patch, bool centered = false)
|
||||||
{
|
{
|
||||||
Super.Init(x, y);
|
Super.Init(x, y);
|
||||||
mTexture = patch;
|
mTexture = patch;
|
||||||
|
@ -82,17 +82,17 @@ class ListMenuItemStaticPatch : ListMenuItem
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = mXpos;
|
double x = mXpos;
|
||||||
Vector2 vec = TexMan.GetScaledSize(mTexture);
|
Vector2 vec = TexMan.GetScaledSize(mTexture);
|
||||||
if (mYpos >= 0)
|
if (mYpos >= 0)
|
||||||
{
|
{
|
||||||
if (mCentered) x -= int(vec.X) / 2;
|
if (mCentered) x -= vec.X / 2;
|
||||||
screen.DrawTexture (mTexture, true, x, mYpos, DTA_Clean, true);
|
screen.DrawTexture (mTexture, true, x, mYpos, DTA_Clean, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth()>>1);
|
x = (mXpos - 160) * CleanXfac + (Screen.GetWidth()>>1);
|
||||||
if (mCentered) x -= (int(vec.X) * CleanXfac)/2;
|
if (mCentered) x -= (vec.X * CleanXfac)/2;
|
||||||
screen.DrawTexture (mTexture, true, x, -mYpos*CleanYfac, DTA_CleanNoMove, true);
|
screen.DrawTexture (mTexture, true, x, -mYpos*CleanYfac, DTA_CleanNoMove, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ class ListMenuItemStaticPatch : ListMenuItem
|
||||||
|
|
||||||
class ListMenuItemStaticPatchCentered : ListMenuItemStaticPatch
|
class ListMenuItemStaticPatchCentered : ListMenuItemStaticPatch
|
||||||
{
|
{
|
||||||
void Init(int x, int y, TextureID patch)
|
void Init(double x, double y, TextureID patch)
|
||||||
{
|
{
|
||||||
Super.Init(x, y, patch, true);
|
Super.Init(x, y, patch, true);
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ class ListMenuItemStaticText : ListMenuItem
|
||||||
int mColor;
|
int mColor;
|
||||||
bool mCentered;
|
bool mCentered;
|
||||||
|
|
||||||
void Init(ListMenuDescriptor desc, int x, int y, String text, int color = Font.CR_UNTRANSLATED)
|
void Init(ListMenuDescriptor desc, double x, double y, String text, int color = Font.CR_UNTRANSLATED)
|
||||||
{
|
{
|
||||||
Super.Init(x, y);
|
Super.Init(x, y);
|
||||||
mText = text;
|
mText = text;
|
||||||
|
@ -128,7 +128,7 @@ class ListMenuItemStaticText : ListMenuItem
|
||||||
mCentered = false;
|
mCentered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitDirect(int x, int y, String text, Font font, int color = Font.CR_UNTRANSLATED, bool centered = false)
|
void InitDirect(double x, double y, String text, Font font, int color = Font.CR_UNTRANSLATED, bool centered = false)
|
||||||
{
|
{
|
||||||
Super.Init(x, y);
|
Super.Init(x, y);
|
||||||
mText = text;
|
mText = text;
|
||||||
|
@ -144,13 +144,13 @@ class ListMenuItemStaticText : ListMenuItem
|
||||||
String text = Stringtable.Localize(mText);
|
String text = Stringtable.Localize(mText);
|
||||||
if (mYpos >= 0)
|
if (mYpos >= 0)
|
||||||
{
|
{
|
||||||
int x = mXpos;
|
double x = mXpos;
|
||||||
if (mCentered) x -= mFont.StringWidth(text)/2;
|
if (mCentered) x -= mFont.StringWidth(text)/2;
|
||||||
screen.DrawText(mFont, mColor, x, mYpos, text, DTA_Clean, true);
|
screen.DrawText(mFont, mColor, x, mYpos, text, DTA_Clean, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth() >> 1);
|
double x = (mXpos - 160) * CleanXfac + (Screen.GetWidth() >> 1);
|
||||||
if (mCentered) x -= (mFont.StringWidth(text) * CleanXfac)/2;
|
if (mCentered) x -= (mFont.StringWidth(text) * CleanXfac)/2;
|
||||||
screen.DrawText (mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true);
|
screen.DrawText (mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true);
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ class ListMenuItemStaticText : ListMenuItem
|
||||||
|
|
||||||
class ListMenuItemStaticTextCentered : ListMenuItemStaticText
|
class ListMenuItemStaticTextCentered : ListMenuItemStaticText
|
||||||
{
|
{
|
||||||
void Init(ListMenuDescriptor desc, int x, int y, String text, int color = -1)
|
void Init(ListMenuDescriptor desc, double x, double y, String text, int color = -1)
|
||||||
{
|
{
|
||||||
Super.Init(desc, x, y, text, color);
|
Super.Init(desc, x, y, text, color);
|
||||||
mCentered = true;
|
mCentered = true;
|
||||||
|
@ -179,7 +179,7 @@ class ListMenuItemSelectable : ListMenuItem
|
||||||
int mHeight;
|
int mHeight;
|
||||||
int mParam;
|
int mParam;
|
||||||
|
|
||||||
protected void Init(int x, int y, int height, Name childmenu, int param = -1)
|
protected void Init(double x, double y, int height, Name childmenu, int param = -1)
|
||||||
{
|
{
|
||||||
Super.Init(x, y, childmenu);
|
Super.Init(x, y, childmenu);
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
|
@ -250,7 +250,7 @@ class ListMenuItemTextItem : ListMenuItemSelectable
|
||||||
mHotkey = hotkey.CharCodeAt(0);
|
mHotkey = hotkey.CharCodeAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitDirect(int x, int y, int height, String hotkey, String text, Font font, int color, int color2, Name child, int param = 0)
|
void InitDirect(double x, double y, int height, String hotkey, String text, Font font, int color, int color2, Name child, int param = 0)
|
||||||
{
|
{
|
||||||
Super.Init(x, y, height, child, param);
|
Super.Init(x, y, height, child, param);
|
||||||
mText = text;
|
mText = text;
|
||||||
|
@ -288,7 +288,7 @@ class ListMenuItemPatchItem : ListMenuItemSelectable
|
||||||
mTexture = patch;
|
mTexture = patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitDirect(int x, int y, int height, TextureID patch, String hotkey, Name child, int param = 0)
|
void InitDirect(double x, double y, int height, TextureID patch, String hotkey, Name child, int param = 0)
|
||||||
{
|
{
|
||||||
Super.Init(x, y, height, child, param);
|
Super.Init(x, y, height, child, param);
|
||||||
mHotkey = hotkey.CharCodeAt(0);
|
mHotkey = hotkey.CharCodeAt(0);
|
||||||
|
|
|
@ -89,31 +89,191 @@ class Menu : Object native
|
||||||
native Menu mParentMenu;
|
native Menu mParentMenu;
|
||||||
native bool mMouseCapture;
|
native bool mMouseCapture;
|
||||||
native bool mBackbuttonSelected;
|
native bool mBackbuttonSelected;
|
||||||
|
native bool DontDim;
|
||||||
void Init(Menu parent)
|
|
||||||
{
|
|
||||||
mParentMenu = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
native static int MenuTime();
|
native static int MenuTime();
|
||||||
native static void SetVideoMode();
|
native static void SetVideoMode();
|
||||||
native static Menu GetCurrentMenu();
|
native static Menu GetCurrentMenu();
|
||||||
native static void SetMenu(Name mnu, int param = 0);
|
native static void SetMenu(Name mnu, int param = 0);
|
||||||
native static void StartMessage(String msg, int mode = 0, Name command = 'none');
|
native static void StartMessage(String msg, int mode = 0, Name command = 'none');
|
||||||
|
native static void SetMouseCapture(bool on);
|
||||||
|
native void Close();
|
||||||
|
native void ActivateMenu();
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void Init(Menu parent)
|
||||||
|
{
|
||||||
|
mParentMenu = parent;
|
||||||
|
mMouseCapture = false;
|
||||||
|
mBackbuttonSelected = false;
|
||||||
|
DontDim = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
virtual bool MenuEvent (int mkey, bool fromcontroller)
|
||||||
|
{
|
||||||
|
switch (mkey)
|
||||||
|
{
|
||||||
|
case MKEY_Back:
|
||||||
|
Close();
|
||||||
|
MenuSound (GetCurrentMenu() != null? "menu/backup" : "menu/clear");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
protected bool MouseEventBack(int type, int x, int y)
|
||||||
|
{
|
||||||
|
if (m_show_backbutton >= 0)
|
||||||
|
{
|
||||||
|
let tex = TexMan.CheckForTexture(gameinfo.mBackButton, TexMan.Type_MiscPatch);
|
||||||
|
if (tex.IsValid())
|
||||||
|
{
|
||||||
|
Vector2 v = TexMan.GetScaledSize(tex);
|
||||||
|
int w = int(v.X + 0.5) * CleanXfac;
|
||||||
|
int h = int(v.Y + 0.5) * CleanYfac;
|
||||||
|
if (m_show_backbutton&1) x -= screen.GetWidth() - w;
|
||||||
|
if (m_show_backbutton&2) y -= screen.GetHeight() - h;
|
||||||
|
mBackbuttonSelected = ( x >= 0 && x < w && y >= 0 && y < h);
|
||||||
|
if (mBackbuttonSelected && type == MOUSE_Release)
|
||||||
|
{
|
||||||
|
if (m_use_mouse == 2) mBackbuttonSelected = false;
|
||||||
|
MenuEvent(MKEY_Back, true);
|
||||||
|
}
|
||||||
|
return mBackbuttonSelected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
virtual bool Responder(InputEventData ev)
|
||||||
|
{
|
||||||
|
bool res = false;
|
||||||
|
if (ev.type == InputEventData.GUI_Event)
|
||||||
|
{
|
||||||
|
if (ev.subtype == InputEventData.GUI_LButtonDown)
|
||||||
|
{
|
||||||
|
res = MouseEventBack(MOUSE_Click, ev.data1, ev.data2);
|
||||||
|
// make the menu's mouse handler believe that the current coordinate is outside the valid range
|
||||||
|
if (res) ev.data2 = -1;
|
||||||
|
res |= MouseEvent(MOUSE_Click, ev.data1, ev.data2);
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
SetCapture(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (ev.subtype == InputEventData.GUI_MouseMove)
|
||||||
|
{
|
||||||
|
BackbuttonTime = 4*Thinker.TICRATE;
|
||||||
|
if (mMouseCapture || m_use_mouse == 1)
|
||||||
|
{
|
||||||
|
res = MouseEventBack(MOUSE_Move, ev.data1, ev.data2);
|
||||||
|
if (res) ev.data2 = -1;
|
||||||
|
res |= MouseEvent(MOUSE_Move, ev.data1, ev.data2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ev.subtype == InputEventData.GUI_LButtonUp)
|
||||||
|
{
|
||||||
|
if (mMouseCapture)
|
||||||
|
{
|
||||||
|
SetCapture(false);
|
||||||
|
res = MouseEventBack(MOUSE_Release, ev.data1, ev.data2);
|
||||||
|
if (res) ev.data2 = -1;
|
||||||
|
res |= MouseEvent(MOUSE_Release, ev.data1, ev.data2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
virtual void Drawer ()
|
||||||
|
{
|
||||||
|
if (self == GetCurrentMenu() && BackbuttonAlpha > 0 && m_show_backbutton >= 0 && m_use_mouse)
|
||||||
|
{
|
||||||
|
let tex = TexMan.CheckForTexture(gameinfo.mBackButton, TexMan.Type_MiscPatch);
|
||||||
|
if (tex.IsValid())
|
||||||
|
{
|
||||||
|
Vector2 v = TexMan.GetScaledSize(tex);
|
||||||
|
int w = int(v.X + 0.5) * CleanXfac;
|
||||||
|
int h = int(v.Y + 0.5) * CleanYfac;
|
||||||
|
int x = (!(m_show_backbutton&1))? 0:screen.GetWidth() - w;
|
||||||
|
int y = (!(m_show_backbutton&2))? 0:screen.GetHeight() - h;
|
||||||
|
if (mBackbuttonSelected && (mMouseCapture || m_use_mouse == 1))
|
||||||
|
{
|
||||||
|
screen.DrawTexture(tex, true, x, y, DTA_CleanNoMove, true, DTA_ColorOverlay, Color(40, 255,255,255));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
screen.DrawTexture(tex, true, x, y, DTA_CleanNoMove, true, DTA_Alpha, BackbuttonAlpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
void SetCapture(bool on)
|
||||||
|
{
|
||||||
|
if (mMouseCapture != on)
|
||||||
|
{
|
||||||
|
mMouseCapture = on;
|
||||||
|
SetMouseCapture(on);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
virtual bool TranslateKeyboardEvents() { return true; }
|
virtual bool TranslateKeyboardEvents() { return true; }
|
||||||
virtual void SetFocus(MenuItemBase fc) {}
|
virtual void SetFocus(MenuItemBase fc) {}
|
||||||
virtual bool CheckFocus(MenuItemBase fc) { return false; }
|
virtual bool CheckFocus(MenuItemBase fc) { return false; }
|
||||||
virtual void ReleaseFocus() {}
|
virtual void ReleaseFocus() {}
|
||||||
virtual void ResetColor() {}
|
virtual void ResetColor() {}
|
||||||
|
virtual bool MouseEvent(int type, int mx, int my) { return false; }
|
||||||
|
virtual void Ticker() {}
|
||||||
|
|
||||||
native virtual bool Responder(InputEventData ev);
|
//=============================================================================
|
||||||
native virtual bool MenuEvent (int mkey, bool fromcontroller);
|
//
|
||||||
native virtual bool MouseEvent(int type, int mx, int my);
|
//
|
||||||
native virtual void Ticker();
|
//
|
||||||
native virtual void Drawer();
|
//=============================================================================
|
||||||
native void Close();
|
|
||||||
native void ActivateMenu();
|
|
||||||
|
|
||||||
static void MenuSound(Sound snd)
|
static void MenuSound(Sound snd)
|
||||||
{
|
{
|
||||||
|
@ -136,3 +296,11 @@ class MenuDescriptor : Object native
|
||||||
native static MenuDescriptor GetDescriptor(Name n);
|
native static MenuDescriptor GetDescriptor(Name n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This class is only needed to give it a virtual Init method that doesn't belong to Menu itself
|
||||||
|
class GenericMenu : Menu
|
||||||
|
{
|
||||||
|
virtual void Init(Menu parent)
|
||||||
|
{
|
||||||
|
Super.Init(parent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
class MenuItemBase : Object native
|
class MenuItemBase : Object native
|
||||||
{
|
{
|
||||||
protected native int mXpos, mYpos;
|
protected native double mXpos, mYpos;
|
||||||
protected native Name mAction;
|
protected native Name mAction;
|
||||||
native bool mEnabled;
|
native bool mEnabled;
|
||||||
|
|
||||||
void Init(int xpos = 0, int ypos = 0, Name actionname = 'None')
|
void Init(double xpos = 0, double ypos = 0, Name actionname = 'None')
|
||||||
{
|
{
|
||||||
mXpos = xpos;
|
mXpos = xpos;
|
||||||
mYpos = ypos;
|
mYpos = ypos;
|
||||||
|
@ -36,10 +36,10 @@ class MenuItemBase : Object native
|
||||||
virtual int GetIndent() { return 0; }
|
virtual int GetIndent() { return 0; }
|
||||||
virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { return indent; }
|
virtual int Draw(OptionMenuDescriptor desc, int y, int indent, bool selected) { return indent; }
|
||||||
|
|
||||||
void OffsetPositionY(int ydelta) { mYpos += ydelta; }
|
void OffsetPositionY(double ydelta) { mYpos += ydelta; }
|
||||||
int GetY() { return mYpos; }
|
double GetY() { return mYpos; }
|
||||||
int GetX() { return mXpos; }
|
double GetX() { return mXpos; }
|
||||||
void SetX(int x) { mXpos = x; }
|
void SetX(double x) { mXpos = x; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is only used to parse font color ranges in MENUDEF
|
// this is only used to parse font color ranges in MENUDEF
|
||||||
|
|
|
@ -181,12 +181,12 @@ class MessageBoxMenu : Menu
|
||||||
int ch = ev.data1;
|
int ch = ev.data1;
|
||||||
ch = ch >= 65 && ch <91? ch + 32 : ch;
|
ch = ch >= 65 && ch <91? ch + 32 : ch;
|
||||||
|
|
||||||
if (ch == 78 /*'n'*/ || ch == 32)
|
if (ch == 110 /*'n'*/ || ch == 32)
|
||||||
{
|
{
|
||||||
HandleResult(false);
|
HandleResult(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (ch == 89 /*'y'*/)
|
else if (ch == 121 /*'y'*/)
|
||||||
{
|
{
|
||||||
HandleResult(true);
|
HandleResult(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -104,6 +104,7 @@ class OptionMenu : Menu
|
||||||
{
|
{
|
||||||
mParentMenu = parent;
|
mParentMenu = parent;
|
||||||
mDesc = desc;
|
mDesc = desc;
|
||||||
|
DontDim = desc.mDontDim;
|
||||||
if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable();
|
if (mDesc != NULL && mDesc.mSelectedItem == -1) mDesc.mSelectedItem = FirstSelectable();
|
||||||
mDesc.CalcIndent();
|
mDesc.CalcIndent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1129,6 +1129,7 @@ class OptionMenuItemTextField : OptionMenuFieldBase
|
||||||
{
|
{
|
||||||
Menu.MenuSound("menu/choose");
|
Menu.MenuSound("menu/choose");
|
||||||
mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), GetCVarString(), -1, 2, fromcontroller);
|
mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), GetCVarString(), -1, 2, fromcontroller);
|
||||||
|
mEnter.ActivateMenu();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (mkey == Menu.MKEY_Input)
|
else if (mkey == Menu.MKEY_Input)
|
||||||
|
|
|
@ -71,7 +71,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void InitDirect(int x, int y, int height, int frameofs, String text, Font font, int color, Name command)
|
void InitDirect(double x, double y, int height, int frameofs, String text, Font font, int color, Name command)
|
||||||
{
|
{
|
||||||
Super.Init(x, y, height, command);
|
Super.Init(x, y, height, command);
|
||||||
mText = text;
|
mText = text;
|
||||||
|
@ -113,7 +113,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
protected void DrawBorder (int x, int y, int len)
|
protected void DrawBorder (double x, double y, int len)
|
||||||
{
|
{
|
||||||
let left = TexMan.CheckForTexture("M_LSLEFT", TexMan.Type_MiscPatch);
|
let left = TexMan.CheckForTexture("M_LSLEFT", TexMan.Type_MiscPatch);
|
||||||
let mid = TexMan.CheckForTexture("M_LSCNTR", TexMan.Type_MiscPatch);
|
let mid = TexMan.CheckForTexture("M_LSCNTR", TexMan.Type_MiscPatch);
|
||||||
|
@ -141,7 +141,9 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
screen.Clear(x, y, x + len, y + SmallFont.GetHeight() * 3/2, 0);
|
int xx = int(x - 160) * CleanXfac + screen.GetWidth()/2;
|
||||||
|
int yy = int(y - 100) * CleanXfac + screen.GetHeight()/2;
|
||||||
|
screen.Clear(xx, yy, xx + len*CleanXfac, yy + SmallFont.GetHeight() * CleanYfac * 3/2, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +163,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw player name box
|
// Draw player name box
|
||||||
int x = mXpos + mFont.StringWidth(text) + 16 + mFrameSize;
|
double x = mXpos + mFont.StringWidth(text) + 16 + mFrameSize;
|
||||||
DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1);
|
DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1);
|
||||||
if (!mEnter)
|
if (!mEnter)
|
||||||
{
|
{
|
||||||
|
@ -186,6 +188,7 @@ class ListMenuItemPlayerNameBox : ListMenuItemSelectable
|
||||||
{
|
{
|
||||||
Menu.MenuSound ("menu/choose");
|
Menu.MenuSound ("menu/choose");
|
||||||
mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), mPlayerName, MAXPLAYERNAME, 2, fromcontroller);
|
mEnter = TextEnterMenu.Open(Menu.GetCurrentMenu(), mPlayerName, MAXPLAYERNAME, 2, fromcontroller);
|
||||||
|
mEnter.ActivateMenu();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (mkey == Menu.MKEY_Input)
|
else if (mkey == Menu.MKEY_Input)
|
||||||
|
@ -246,7 +249,7 @@ class ListMenuItemValueText : ListMenuItemSelectable
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void InitDirect(int x, int y, int height, String text, Font font, int color, int valuecolor, Name command, Name values)
|
void InitDirect(double x, double y, int height, String text, Font font, int color, int valuecolor, Name command, Name values)
|
||||||
{
|
{
|
||||||
Super.Init(x, y, height, command);
|
Super.Init(x, y, height, command);
|
||||||
mText = text;
|
mText = text;
|
||||||
|
@ -337,7 +340,7 @@ class ListMenuItemValueText : ListMenuItemSelectable
|
||||||
String text = Stringtable.Localize(mText);
|
String text = Stringtable.Localize(mText);
|
||||||
screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true);
|
screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true);
|
||||||
|
|
||||||
int x = mXpos + mFont.StringWidth(text) + 8;
|
double x = mXpos + mFont.StringWidth(text) + 8;
|
||||||
if (mSelections.Size() > 0)
|
if (mSelections.Size() > 0)
|
||||||
{
|
{
|
||||||
screen.DrawText(mFont, mFontColor2, x, mYpos, mSelections[mSelection], DTA_Clean, true);
|
screen.DrawText(mFont, mFontColor2, x, mYpos, mSelections[mSelection], DTA_Clean, true);
|
||||||
|
@ -385,7 +388,7 @@ class ListMenuItemSlider : ListMenuItemSelectable
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
void InitDirect(int x, int y, int height, String text, Font font, int color, Name command, int min, int max, int step)
|
void InitDirect(double x, double y, int height, String text, Font font, int color, Name command, int min, int max, int step)
|
||||||
{
|
{
|
||||||
Super.Init(x, y, height, command);
|
Super.Init(x, y, height, command);
|
||||||
mText = text;
|
mText = text;
|
||||||
|
@ -463,7 +466,7 @@ class ListMenuItemSlider : ListMenuItemSelectable
|
||||||
lm.ReleaseFocus();
|
lm.ReleaseFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
int slide_left = SmallFont.StringWidth ("Green") + 8 + mXpos;
|
int slide_left = SmallFont.StringWidth ("Green") + 8 + int(mXpos);
|
||||||
int slide_right = slide_left + 12*8; // 12 char cells with 8 pixels each.
|
int slide_right = slide_left + 12*8; // 12 char cells with 8 pixels each.
|
||||||
|
|
||||||
if (type == Menu.MOUSE_Click)
|
if (type == Menu.MOUSE_Click)
|
||||||
|
@ -491,7 +494,7 @@ class ListMenuItemSlider : ListMenuItemSelectable
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
protected void DrawSlider (int x, int y)
|
protected void DrawSlider (double x, double y)
|
||||||
{
|
{
|
||||||
int range = mMaxrange - mMinrange;
|
int range = mMaxrange - mMinrange;
|
||||||
int cur = mSelection - mMinrange;
|
int cur = mSelection - mMinrange;
|
||||||
|
@ -515,8 +518,8 @@ class ListMenuItemSlider : ListMenuItemSelectable
|
||||||
|
|
||||||
screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true);
|
screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true);
|
||||||
|
|
||||||
int x = SmallFont.StringWidth ("Green") + 8 + mXpos;
|
double x = SmallFont.StringWidth ("Green") + 8 + mXpos;
|
||||||
int x2 = SmallFont.StringWidth (text) + 8 + mXpos;
|
double x2 = SmallFont.StringWidth (text) + 8 + mXpos;
|
||||||
DrawSlider (MAX(x2, x), mYpos);
|
DrawSlider (MAX(x2, x), mYpos);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -252,8 +252,8 @@ class ListMenuItemPlayerDisplay : ListMenuItem
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int x = (mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1);
|
int x = int(mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1);
|
||||||
int y = (mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1);
|
int y = int(mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1);
|
||||||
|
|
||||||
screen.DrawTexture(mBackdrop, false, x, y - 1,
|
screen.DrawTexture(mBackdrop, false, x, y - 1,
|
||||||
DTA_DestWidth, 72 * CleanXfac,
|
DTA_DestWidth, 72 * CleanXfac,
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ReadThisMenu : Menu
|
class ReadThisMenu : GenericMenu
|
||||||
{
|
{
|
||||||
int mScreen;
|
int mScreen;
|
||||||
int mInfoTic;
|
int mInfoTic;
|
||||||
|
@ -44,17 +44,18 @@ class ReadThisMenu : Menu
|
||||||
//
|
//
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
|
override void Init(Menu parent)
|
||||||
|
{
|
||||||
|
Super.Init(parent);
|
||||||
|
mScreen = 1;
|
||||||
|
mInfoTic = gametic;
|
||||||
|
}
|
||||||
|
|
||||||
override void Drawer()
|
override void Drawer()
|
||||||
{
|
{
|
||||||
double alpha;
|
double alpha;
|
||||||
TextureID tex, prevpic;
|
TextureID tex, prevpic;
|
||||||
|
|
||||||
if (mScreen == 0)
|
|
||||||
{
|
|
||||||
mScreen = 1;
|
|
||||||
mInfoTic = gametic;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Did the mapper choose a custom help page via MAPINFO?
|
// Did the mapper choose a custom help page via MAPINFO?
|
||||||
if (level.F1Pic.Length() != 0)
|
if (level.F1Pic.Length() != 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue