diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 25e27b8468..1e6211976d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3167,11 +3167,14 @@ void PClass::InitializeDefaults() assert(ParentClass != nullptr); ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); - for (const PField *field : Fields) + if (Defaults != nullptr) { - if (!(field->Flags & VARF_Native)) + for (const PField *field : Fields) { - field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); + if (!(field->Flags & VARF_Native)) + { + field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); + } } } } diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index 2ade7d2201..b039f46e0d 100644 --- a/src/menu/listmenu.cpp +++ b/src/menu/listmenu.cpp @@ -389,16 +389,16 @@ int DMenuItemBase::GetWidth() // static patch // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemStaticPatch, false, false) +IMPLEMENT_CLASS(DListMenuItemStaticPatch_, false, false) -DListMenuItemStaticPatch::DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered) +DListMenuItemStaticPatch_::DListMenuItemStaticPatch_(int x, int y, FTextureID patch, bool centered) : DMenuItemBase(x, y) { mTexture = patch; mCentered = centered; } -void DListMenuItemStaticPatch::Drawer(bool selected) +void DListMenuItemStaticPatch_::Drawer(bool selected) { if (!mTexture.Exists()) { @@ -425,9 +425,9 @@ void DListMenuItemStaticPatch::Drawer(bool selected) // static text // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemStaticText, false, false) +IMPLEMENT_CLASS(DListMenuItemStaticText_, false, false) -DListMenuItemStaticText::DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered) +DListMenuItemStaticText_::DListMenuItemStaticText_(int x, int y, const char *text, FFont *font, EColorRange color, bool centered) : DMenuItemBase(x, y) { mText = text; @@ -436,7 +436,7 @@ DListMenuItemStaticText::DListMenuItemStaticText(int x, int y, const char *text, mCentered = centered; } -void DListMenuItemStaticText::Drawer(bool selected) +void DListMenuItemStaticText_::Drawer(bool selected) { if (mText.IsNotEmpty()) { @@ -462,9 +462,9 @@ void DListMenuItemStaticText::Drawer(bool selected) // base class for selectable items // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemSelectable, false, false) +IMPLEMENT_CLASS(DListMenuItemSelectable_, false, false) -DListMenuItemSelectable::DListMenuItemSelectable(int x, int y, int height, FName action, int param) +DListMenuItemSelectable_::DListMenuItemSelectable_(int x, int y, int height, FName action, int param) : DMenuItemBase(x, y, action) { mHeight = height; @@ -472,34 +472,34 @@ DListMenuItemSelectable::DListMenuItemSelectable(int x, int y, int height, FName mHotkey = 0; } -bool DListMenuItemSelectable::CheckCoordinate(int x, int y) +bool DListMenuItemSelectable_::CheckCoordinate(int x, int y) { return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here } -bool DListMenuItemSelectable::Selectable() +bool DListMenuItemSelectable_::Selectable() { return mEnabled; } -bool DListMenuItemSelectable::Activate() +bool DListMenuItemSelectable_::Activate() { M_SetMenu(mAction, mParam); return true; } -FName DListMenuItemSelectable::GetAction(int *pparam) +FName DListMenuItemSelectable_::GetAction(int *pparam) { if (pparam != NULL) *pparam = mParam; return mAction; } -bool DListMenuItemSelectable::CheckHotkey(int c) +bool DListMenuItemSelectable_::CheckHotkey(int c) { return c == tolower(mHotkey); } -bool DListMenuItemSelectable::MouseEvent(int type, int x, int y) +bool DListMenuItemSelectable_::MouseEvent(int type, int x, int y) { if (type == DMenu::MOUSE_Release) { @@ -516,10 +516,10 @@ bool DListMenuItemSelectable::MouseEvent(int type, int x, int y) // text item // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemText, false, false) +IMPLEMENT_CLASS(DListMenuItemText_, false, false) -DListMenuItemText::DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param) -: DListMenuItemSelectable(x, y, height, child, param) +DListMenuItemText_::DListMenuItemText_(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param) +: DListMenuItemSelectable_(x, y, height, child, param) { mText = ncopystring(text); mFont = font; @@ -528,7 +528,7 @@ DListMenuItemText::DListMenuItemText(int x, int y, int height, int hotkey, const mHotkey = hotkey; } -void DListMenuItemText::OnDestroy() +void DListMenuItemText_::OnDestroy() { if (mText != NULL) { @@ -536,7 +536,7 @@ void DListMenuItemText::OnDestroy() } } -void DListMenuItemText::Drawer(bool selected) +void DListMenuItemText_::Drawer(bool selected) { const char *text = mText; if (text != NULL) @@ -546,7 +546,7 @@ void DListMenuItemText::Drawer(bool selected) } } -int DListMenuItemText::GetWidth() +int DListMenuItemText_::GetWidth() { const char *text = mText; if (text != NULL) @@ -563,21 +563,21 @@ int DListMenuItemText::GetWidth() // patch item // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemPatch, false, false) +IMPLEMENT_CLASS(DListMenuItemPatch_, false, false) -DListMenuItemPatch::DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param) -: DListMenuItemSelectable(x, y, height, child, param) +DListMenuItemPatch_::DListMenuItemPatch_(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param) +: DListMenuItemSelectable_(x, y, height, child, param) { mHotkey = hotkey; mTexture = patch; } -void DListMenuItemPatch::Drawer(bool selected) +void DListMenuItemPatch_::Drawer(bool selected) { screen->DrawTexture (TexMan(mTexture), mXpos, mYpos, DTA_Clean, true, TAG_DONE); } -int DListMenuItemPatch::GetWidth() +int DListMenuItemPatch_::GetWidth() { return mTexture.isValid() ? TexMan[mTexture]->GetScaledWidth() diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 62ea9daa31..d28bc54963 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -78,6 +78,11 @@ DEFINE_ACTION_FUNCTION(DMenu, GetCurrentMenu) int DMenu::MenuTime; +DEFINE_ACTION_FUNCTION(DMenu, MenuTime) +{ + ACTION_RETURN_INT(DMenu::MenuTime); +} + FGameStartup GameStartupInfo; EMenuState menuactive; bool M_DemoNoPlay; @@ -1099,6 +1104,23 @@ DEFINE_FIELD(DMenuItemBase, mYpos) DEFINE_FIELD(DMenuItemBase, mAction) DEFINE_FIELD(DMenuItemBase, mEnabled) +DEFINE_FIELD(DListMenuDescriptor, mItems) +DEFINE_FIELD(DListMenuDescriptor, mSelectedItem) +DEFINE_FIELD(DListMenuDescriptor, mSelectOfsX) +DEFINE_FIELD(DListMenuDescriptor, mSelectOfsY) +DEFINE_FIELD(DListMenuDescriptor, mSelector) +DEFINE_FIELD(DListMenuDescriptor, mDisplayTop) +DEFINE_FIELD(DListMenuDescriptor, mXpos) +DEFINE_FIELD(DListMenuDescriptor, mYpos) +DEFINE_FIELD(DListMenuDescriptor, mWLeft) +DEFINE_FIELD(DListMenuDescriptor, mWRight) +DEFINE_FIELD(DListMenuDescriptor, mLinespacing) +DEFINE_FIELD(DListMenuDescriptor, mAutoselect) +DEFINE_FIELD(DListMenuDescriptor, mFont) +DEFINE_FIELD(DListMenuDescriptor, mFontColor) +DEFINE_FIELD(DListMenuDescriptor, mFontColor2) +DEFINE_FIELD(DListMenuDescriptor, mCenter) + DEFINE_FIELD(DOptionMenuDescriptor, mItems) DEFINE_FIELD(DOptionMenuDescriptor, mTitle) DEFINE_FIELD(DOptionMenuDescriptor, mSelectedItem) diff --git a/src/menu/menu.h b/src/menu/menu.h index e8d5b9a823..3af5e0efbc 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -243,6 +243,11 @@ public: 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 CallMenuEvent(int mkey, bool fromcontroller); bool CallMouseEvent(int type, int x, int y); void CallDrawer(); @@ -301,31 +306,31 @@ public: void SetX(int x) { mXpos = x; } }; -class DListMenuItemStaticPatch : public DMenuItemBase +class DListMenuItemStaticPatch_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemStaticPatch, DMenuItemBase) + DECLARE_CLASS(DListMenuItemStaticPatch_, DMenuItemBase) protected: FTextureID mTexture; bool mCentered; - DListMenuItemStaticPatch() {} + DListMenuItemStaticPatch_() {} public: - DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered); + DListMenuItemStaticPatch_(int x, int y, FTextureID patch, bool centered); void Drawer(bool selected); }; -class DListMenuItemStaticText : public DMenuItemBase +class DListMenuItemStaticText_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemStaticText, DMenuItemBase) + DECLARE_CLASS(DListMenuItemStaticText_, DMenuItemBase) protected: FString mText; FFont *mFont; EColorRange mColor; bool mCentered; - DListMenuItemStaticText() {} + DListMenuItemStaticText_() {} public: - DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered); + DListMenuItemStaticText_(int x, int y, const char *text, FFont *font, EColorRange color, bool centered); void Drawer(bool selected); }; @@ -335,9 +340,9 @@ public: // //============================================================================= -class DListMenuItemPlayerDisplay : public DMenuItemBase +class DListMenuItemPlayerDisplay_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemPlayerDisplay, DMenuItemBase) + DECLARE_CLASS(DListMenuItemPlayerDisplay_, DMenuItemBase) DListMenuDescriptor *mOwner; FTexture *mBackdrop; @@ -359,7 +364,7 @@ class DListMenuItemPlayerDisplay : public DMenuItemBase void UpdateRandomClass(); void UpdateTranslation(); - DListMenuItemPlayerDisplay() {} + DListMenuItemPlayerDisplay_() {} public: enum @@ -371,7 +376,7 @@ public: PDF_TRANSLATE = 0x10005, }; - DListMenuItemPlayerDisplay(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action); + DListMenuItemPlayerDisplay_(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action); void OnDestroy() override; virtual void Ticker(); virtual void Drawer(bool selected); @@ -385,17 +390,17 @@ public: // //============================================================================= -class DListMenuItemSelectable : public DMenuItemBase +class DListMenuItemSelectable_ : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemSelectable, DMenuItemBase) + DECLARE_CLASS(DListMenuItemSelectable_, DMenuItemBase) protected: int mHotkey; int mHeight; int mParam; - DListMenuItemSelectable() {} + DListMenuItemSelectable_() {} public: - DListMenuItemSelectable(int x, int y, int height, FName childmenu, int mParam = -1); + DListMenuItemSelectable_(int x, int y, int height, FName childmenu, int mParam = -1); bool CheckCoordinate(int x, int y); bool Selectable(); bool CheckHotkey(int c); @@ -404,30 +409,30 @@ public: FName GetAction(int *pparam); }; -class DListMenuItemText : public DListMenuItemSelectable +class DListMenuItemText_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DListMenuItemText, DListMenuItemSelectable) + DECLARE_CLASS(DListMenuItemText_, DListMenuItemSelectable_) const char *mText; FFont *mFont; EColorRange mColor; EColorRange mColorSelected; - DListMenuItemText() {} + DListMenuItemText_() {} public: - DListMenuItemText(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0); + DListMenuItemText_(int x, int y, int height, int hotkey, const char *text, FFont *font, EColorRange color, EColorRange color2, FName child, int param = 0); void OnDestroy() override; void Drawer(bool selected); int GetWidth(); }; -class DListMenuItemPatch : public DListMenuItemSelectable +class DListMenuItemPatch_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DListMenuItemPatch, DListMenuItemSelectable) + DECLARE_CLASS(DListMenuItemPatch_, DListMenuItemSelectable_) FTextureID mTexture; - DListMenuItemPatch() {} + DListMenuItemPatch_() {} public: - DListMenuItemPatch(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0); + DListMenuItemPatch_(int x, int y, int height, int hotkey, FTextureID patch, FName child, int param = 0); void Drawer(bool selected); int GetWidth(); }; @@ -438,9 +443,9 @@ public: // //============================================================================= -class DPlayerNameBox : public DListMenuItemSelectable +class DPlayerNameBox_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DPlayerNameBox, DListMenuItemSelectable) + DECLARE_CLASS(DPlayerNameBox_, DListMenuItemSelectable_) FString mText; FFont *mFont; EColorRange mFontColor; @@ -451,10 +456,10 @@ class DPlayerNameBox : public DListMenuItemSelectable void DrawBorder (int x, int y, int len); - DPlayerNameBox() {} + DPlayerNameBox_() {} public: - DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action); + DPlayerNameBox_(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action); bool SetString(int i, const char *s); bool GetString(int i, char *s, int len); void Drawer(bool selected); @@ -467,9 +472,9 @@ public: // //============================================================================= -class DValueTextItem : public DListMenuItemSelectable +class DValueTextItem_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DValueTextItem, DListMenuItemSelectable) + DECLARE_CLASS(DValueTextItem_, DListMenuItemSelectable_) TArray mSelections; FString mText; int mSelection; @@ -477,10 +482,10 @@ class DValueTextItem : public DListMenuItemSelectable EColorRange mFontColor; EColorRange mFontColor2; - DValueTextItem() {} + DValueTextItem_() {} public: - DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values); + DValueTextItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values); bool SetString(int i, const char *s); bool SetValue(int i, int value); bool GetValue(int i, int *pvalue); @@ -494,9 +499,9 @@ public: // //============================================================================= -class DSliderItem : public DListMenuItemSelectable +class DSliderItem_ : public DListMenuItemSelectable_ { - DECLARE_CLASS(DSliderItem, DListMenuItemSelectable) + DECLARE_CLASS(DSliderItem_, DListMenuItemSelectable_) FString mText; FFont *mFont; EColorRange mFontColor; @@ -506,10 +511,10 @@ class DSliderItem : public DListMenuItemSelectable void DrawSlider (int x, int y); - DSliderItem() {} + DSliderItem_() {} public: - DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step); + DSliderItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step); bool SetValue(int i, int value); bool GetValue(int i, int *pvalue); bool MenuEvent (int mkey, bool fromcontroller); diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 1a76576764..05bb16007e 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -348,7 +348,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetString(); FTextureID tex = GetMenuTexture(sc.String); - DMenuItemBase *it = new DListMenuItemStaticPatch(x, y, tex, centered); + DMenuItemBase *it = new DListMenuItemStaticPatch_(x, y, tex, centered); desc->mItems.Push(it); } else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered")) @@ -369,7 +369,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) cr = V_FindFontColor(sc.String); if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated")) cr = desc->mFontColor; } - DMenuItemBase *it = new DListMenuItemStaticText(x, y, label, desc->mFont, cr, centered); + DMenuItemBase *it = new DListMenuItemStaticText_(x, y, label, desc->mFont, cr, centered); desc->mItems.Push(it); } else if (sc.Compare("PatchItem")) @@ -389,7 +389,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) param = sc.Number; } - DMenuItemBase *it = new DListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); + DMenuItemBase *it = new DListMenuItemPatch_(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -411,7 +411,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) param = sc.Number; } - DMenuItemBase *it = new DListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); + DMenuItemBase *it = new DListMenuItemText_(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -468,7 +468,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) action = sc.String; } } - DListMenuItemPlayerDisplay *it = new DListMenuItemPlayerDisplay(desc, x, y, c1, c2, noportrait, action); + DListMenuItemPlayerDisplay_ *it = new DListMenuItemPlayerDisplay_(desc, x, y, c1, c2, noportrait, action); desc->mItems.Push(it); } else if (sc.Compare("PlayerNameBox")) @@ -480,7 +480,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) int ofs = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); - DMenuItemBase *it = new DPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); + DMenuItemBase *it = new DPlayerNameBox_(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -498,7 +498,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetString(); values = sc.String; } - DMenuItemBase *it = new DValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); + DMenuItemBase *it = new DValueTextItem_(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -519,7 +519,7 @@ static void ParseListMenuBody(FScanner &sc, DListMenuDescriptor *desc) sc.MustGetStringName(","); sc.MustGetNumber(); int step = sc.Number; - DMenuItemBase *it = new DSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); + DMenuItemBase *it = new DSliderItem_(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -1144,12 +1144,12 @@ static void BuildEpisodeMenu() if (AllEpisodes[i].mPicName.IsNotEmpty()) { FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName); - it = new DListMenuItemPatch(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, + it = new DListMenuItemPatch_(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, tex, NAME_Skillmenu, i); } else { - it = new DListMenuItemText(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, + it = new DListMenuItemText_(ld->mXpos, posy, ld->mLinespacing, AllEpisodes[i].mShortcut, AllEpisodes[i].mEpisodeName, ld->mFont, ld->mFontColor, ld->mFontColor2, NAME_Skillmenu, i); } ld->mItems.Push(it); @@ -1242,7 +1242,7 @@ static void BuildPlayerclassMenu() if (numclassitems <= 1) { // create a dummy item that auto-chooses the default class. - DListMenuItemText *it = new DListMenuItemText(0, 0, 0, 'p', "player", + DListMenuItemText_ *it = new DListMenuItemText_(0, 0, 0, 'p', "player", ld->mFont,ld->mFontColor, ld->mFontColor2, NAME_Episodemenu, -1000); ld->mAutoselect = ld->mItems.Push(it); success = true; @@ -1268,7 +1268,7 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[i].Type); if (pname != nullptr) { - DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, + DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, i); ld->mItems.Push(it); ld->mYpos += ld->mLinespacing; @@ -1278,7 +1278,7 @@ static void BuildPlayerclassMenu() } if (n > 1 && !gameinfo.norandomplayerclass) { - DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r', + DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, 'r', "$MNU_RANDOM", ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, -1); ld->mItems.Push(it); } @@ -1287,7 +1287,7 @@ static void BuildPlayerclassMenu() const char *pname = GetPrintableDisplayName(PlayerClasses[0].Type); if (pname != nullptr) { - DListMenuItemText *it = new DListMenuItemText(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, + DListMenuItemText_ *it = new DListMenuItemText_(ld->mXpos, ld->mYpos, ld->mLinespacing, *pname, pname, ld->mFont,ld->mFontColor,ld->mFontColor2, NAME_Episodemenu, 0); ld->mItems.Push(it); } @@ -1548,13 +1548,13 @@ void M_StartupSkillMenu(FGameStartup *gs) if (skill.PicName.Len() != 0 && pItemText == nullptr) { FTextureID tex = GetMenuTexture(skill.PicName); - li = new DListMenuItemPatch(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i); + li = new DListMenuItemPatch_(ld->mXpos, y, ld->mLinespacing, skill.Shortcut, tex, action, i); } else { EColorRange color = (EColorRange)skill.GetTextColor(); if (color == CR_UNTRANSLATED) color = ld->mFontColor; - li = new DListMenuItemText(x, y, ld->mLinespacing, skill.Shortcut, + li = new DListMenuItemText_(x, y, ld->mLinespacing, skill.Shortcut, pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i); } ld->mItems.Push(li); diff --git a/src/menu/playerdisplay.cpp b/src/menu/playerdisplay.cpp index 4b01ab3988..5cd0f78159 100644 --- a/src/menu/playerdisplay.cpp +++ b/src/menu/playerdisplay.cpp @@ -54,8 +54,8 @@ // // //============================================================================= -IMPLEMENT_CLASS(DListMenuItemPlayerDisplay, false, false) -DListMenuItemPlayerDisplay::DListMenuItemPlayerDisplay(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action) +IMPLEMENT_CLASS(DListMenuItemPlayerDisplay_, false, false) +DListMenuItemPlayerDisplay_::DListMenuItemPlayerDisplay_(DListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action) : DMenuItemBase(x, y, action) { mOwner = menu; @@ -90,7 +90,7 @@ DListMenuItemPlayerDisplay::DListMenuItemPlayerDisplay(DListMenuDescriptor *menu // //============================================================================= -void DListMenuItemPlayerDisplay::OnDestroy() +void DListMenuItemPlayerDisplay_::OnDestroy() { } @@ -100,7 +100,7 @@ void DListMenuItemPlayerDisplay::OnDestroy() // //============================================================================= -void DListMenuItemPlayerDisplay::UpdateRandomClass() +void DListMenuItemPlayerDisplay_::UpdateRandomClass() { if (--mRandomTimer < 0) { @@ -126,7 +126,7 @@ void DListMenuItemPlayerDisplay::UpdateRandomClass() // //============================================================================= -void DListMenuItemPlayerDisplay::UpdateTranslation() +void DListMenuItemPlayerDisplay_::UpdateTranslation() { int PlayerColor = players[consoleplayer].userinfo.GetColor(); int PlayerSkin = players[consoleplayer].userinfo.GetSkin(); @@ -146,7 +146,7 @@ void DListMenuItemPlayerDisplay::UpdateTranslation() // //============================================================================= -void DListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force) +void DListMenuItemPlayerDisplay_::SetPlayerClass(int classnum, bool force) { if (classnum < 0 || classnum >= (int)PlayerClasses.Size ()) { @@ -176,7 +176,7 @@ void DListMenuItemPlayerDisplay::SetPlayerClass(int classnum, bool force) // //============================================================================= -bool DListMenuItemPlayerDisplay::UpdatePlayerClass() +bool DListMenuItemPlayerDisplay_::UpdatePlayerClass() { if (mOwner->mSelectedItem >= 0) { @@ -198,7 +198,7 @@ bool DListMenuItemPlayerDisplay::UpdatePlayerClass() // //============================================================================= -bool DListMenuItemPlayerDisplay::SetValue(int i, int value) +bool DListMenuItemPlayerDisplay_::SetValue(int i, int value) { switch (i) { @@ -230,7 +230,7 @@ bool DListMenuItemPlayerDisplay::SetValue(int i, int value) // //============================================================================= -void DListMenuItemPlayerDisplay::Ticker() +void DListMenuItemPlayerDisplay_::Ticker() { if (mClassNum < 0) UpdateRandomClass(); @@ -250,7 +250,7 @@ void DListMenuItemPlayerDisplay::Ticker() // //============================================================================= -void DListMenuItemPlayerDisplay::Drawer(bool selected) +void DListMenuItemPlayerDisplay_::Drawer(bool selected) { if (mMode == 0 && !UpdatePlayerClass()) { diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index ee8ea18533..1621e3eba5 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -60,10 +60,10 @@ EXTERN_CVAR (Bool, cl_run) // Player's name // //============================================================================= -IMPLEMENT_CLASS(DPlayerNameBox, false, false) +IMPLEMENT_CLASS(DPlayerNameBox_, false, false) -DPlayerNameBox::DPlayerNameBox(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action) -: DListMenuItemSelectable(x, y, height, action) +DPlayerNameBox_::DPlayerNameBox_(int x, int y, int height, int frameofs, const char *text, FFont *font, EColorRange color, FName action) +: DListMenuItemSelectable_(x, y, height, action) { mText = text; mFont = font; @@ -79,7 +79,7 @@ DPlayerNameBox::DPlayerNameBox(int x, int y, int height, int frameofs, const cha // //============================================================================= -bool DPlayerNameBox::SetString(int i, const char *s) +bool DPlayerNameBox_::SetString(int i, const char *s) { if (i == 0) { @@ -90,8 +90,8 @@ bool DPlayerNameBox::SetString(int i, const char *s) return false; } -bool DPlayerNameBox::GetString(int i, char *s, int len) -{ +bool DPlayerNameBox_::GetString(int i, char *s, int len) +{ if (i == 0) { strncpy(s, mPlayerName, len); @@ -107,7 +107,7 @@ bool DPlayerNameBox::GetString(int i, char *s, int len) // //============================================================================= -void DPlayerNameBox::DrawBorder (int x, int y, int len) +void DPlayerNameBox_::DrawBorder (int x, int y, int len) { FTexture *left = TexMan[TexMan.CheckForTexture("M_LSLEFT", FTexture::TEX_MiscPatch)]; FTexture *mid = TexMan[TexMan.CheckForTexture("M_LSCNTR", FTexture::TEX_MiscPatch)]; @@ -146,7 +146,7 @@ void DPlayerNameBox::DrawBorder (int x, int y, int len) // //============================================================================= -void DPlayerNameBox::Drawer(bool selected) +void DPlayerNameBox_::Drawer(bool selected) { const char *text = mText; if (text != NULL) @@ -182,7 +182,7 @@ void DPlayerNameBox::Drawer(bool selected) // //============================================================================= -bool DPlayerNameBox::MenuEvent(int mkey, bool fromcontroller) +bool DPlayerNameBox_::MenuEvent(int mkey, bool fromcontroller) { if (mkey == MKEY_Enter) { @@ -212,10 +212,10 @@ bool DPlayerNameBox::MenuEvent(int mkey, bool fromcontroller) // items for the player menu // //============================================================================= -IMPLEMENT_CLASS(DValueTextItem, false, false) +IMPLEMENT_CLASS(DValueTextItem_, false, false) -DValueTextItem::DValueTextItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values) -: DListMenuItemSelectable(x, y, height, action) +DValueTextItem_::DValueTextItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, EColorRange valuecolor, FName action, FName values) +: DListMenuItemSelectable_(x, y, height, action) { mText = text; mFont = font; @@ -241,7 +241,7 @@ DValueTextItem::DValueTextItem(int x, int y, int height, const char *text, FFont // //============================================================================= -bool DValueTextItem::SetString(int i, const char *s) +bool DValueTextItem_::SetString(int i, const char *s) { // should actually use the index... FString str = s; @@ -256,7 +256,7 @@ bool DValueTextItem::SetString(int i, const char *s) // //============================================================================= -bool DValueTextItem::SetValue(int i, int value) +bool DValueTextItem_::SetValue(int i, int value) { if (i == 0) { @@ -266,7 +266,7 @@ bool DValueTextItem::SetValue(int i, int value) return false; } -bool DValueTextItem::GetValue(int i, int *pvalue) +bool DValueTextItem_::GetValue(int i, int *pvalue) { if (i == 0) { @@ -282,7 +282,7 @@ bool DValueTextItem::GetValue(int i, int *pvalue) // //============================================================================= -bool DValueTextItem::MenuEvent (int mkey, bool fromcontroller) +bool DValueTextItem_::MenuEvent (int mkey, bool fromcontroller) { if (mSelections.Size() > 1) { @@ -308,7 +308,7 @@ bool DValueTextItem::MenuEvent (int mkey, bool fromcontroller) // //============================================================================= -void DValueTextItem::Drawer(bool selected) +void DValueTextItem_::Drawer(bool selected) { const char *text = mText; @@ -329,10 +329,10 @@ void DValueTextItem::Drawer(bool selected) // items for the player menu // //============================================================================= -IMPLEMENT_CLASS(DSliderItem, false, false) +IMPLEMENT_CLASS(DSliderItem_, false, false) -DSliderItem::DSliderItem(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step) -: DListMenuItemSelectable(x, y, height, action) +DSliderItem_::DSliderItem_(int x, int y, int height, const char *text, FFont *font, EColorRange color, FName action, int min, int max, int step) +: DListMenuItemSelectable_(x, y, height, action) { mText = text; mFont = font; @@ -349,7 +349,7 @@ DSliderItem::DSliderItem(int x, int y, int height, const char *text, FFont *font // //============================================================================= -bool DSliderItem::SetValue(int i, int value) +bool DSliderItem_::SetValue(int i, int value) { if (i == 0) { @@ -359,7 +359,7 @@ bool DSliderItem::SetValue(int i, int value) return false; } -bool DSliderItem::GetValue(int i, int *pvalue) +bool DSliderItem_::GetValue(int i, int *pvalue) { if (i == 0) { @@ -375,7 +375,7 @@ bool DSliderItem::GetValue(int i, int *pvalue) // //============================================================================= -bool DSliderItem::MenuEvent (int mkey, bool fromcontroller) +bool DSliderItem_::MenuEvent (int mkey, bool fromcontroller) { if (mkey == MKEY_Left) { @@ -398,7 +398,7 @@ bool DSliderItem::MenuEvent (int mkey, bool fromcontroller) // //============================================================================= -bool DSliderItem::MouseEvent(int type, int x, int y) +bool DSliderItem_::MouseEvent(int type, int x, int y) { DListMenu *lm = static_cast(DMenu::CurrentMenu); if (type != DMenu::MOUSE_Click) @@ -438,7 +438,7 @@ bool DSliderItem::MouseEvent(int type, int x, int y) // //============================================================================= -void DSliderItem::DrawSlider (int x, int y) +void DSliderItem_::DrawSlider (int x, int y) { int range = mMaxrange - mMinrange; int cur = mSelection - mMinrange; @@ -464,7 +464,7 @@ void DSliderItem::DrawSlider (int x, int y) // //============================================================================= -void DSliderItem::Drawer(bool selected) +void DSliderItem_::Drawer(bool selected) { const char *text = mText; @@ -536,14 +536,14 @@ void DPlayerMenu::Init(DMenu *parent, DListMenuDescriptor *desc) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, 0); - li->SetValue(DListMenuItemPlayerDisplay::PDF_MODE, 1); - li->SetValue(DListMenuItemPlayerDisplay::PDF_TRANSLATE, 1); - li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_ROTATION, 0); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_MODE, 1); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_TRANSLATE, 1); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); if (PlayerClass != NULL && !(GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN) && players[consoleplayer].userinfo.GetPlayerClassNum() != -1) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, players[consoleplayer].userinfo.GetSkin()); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, players[consoleplayer].userinfo.GetSkin()); } } @@ -658,7 +658,7 @@ bool DPlayerMenu::Responder (event_t *ev) DMenuItemBase *li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, mRotation); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_ROTATION, mRotation); } return true; } @@ -812,7 +812,7 @@ void DPlayerMenu::UpdateSkins() li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, skin); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, skin); } } UpdateTranslation(); @@ -908,7 +908,7 @@ void DPlayerMenu::ClassChanged (DMenuItemBase *li) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_CLASS, players[consoleplayer].userinfo.GetPlayerClassNum()); } } } @@ -939,7 +939,7 @@ void DPlayerMenu::SkinChanged (DMenuItemBase *li) li = GetItem(NAME_Playerdisplay); if (li != NULL) { - li->SetValue(DListMenuItemPlayerDisplay::PDF_SKIN, sel); + li->SetValue(DListMenuItemPlayerDisplay_::PDF_SKIN, sel); } } } diff --git a/src/p_states.cpp b/src/p_states.cpp index 221ff6cedf..3602cfc81e 100644 --- a/src/p_states.cpp +++ b/src/p_states.cpp @@ -51,6 +51,40 @@ FStateLabelStorage StateLabels; // actor. States are archived by recording the actor they belong // to and the index into that actor's list of states. + +//========================================================================== +// +// This wraps everything needed to get a current sprite from a state into +// one single script function. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(FState, GetSpriteTexture) +{ + PARAM_SELF_STRUCT_PROLOGUE(FState); + PARAM_INT(rotation); + PARAM_INT_DEF(skin); + PARAM_FLOAT_DEF(scalex); + PARAM_FLOAT_DEF(scaley); + + spriteframe_t *sprframe; + if (skin == 0) + { + sprframe = &SpriteFrames[sprites[self->sprite].spriteframes + self->GetFrame()]; + } + else + { + sprframe = &SpriteFrames[sprites[skins[skin].sprite].spriteframes + self->GetFrame()]; + scalex = skins[skin].Scale.X; + scaley = skins[skin].Scale.Y; + } + if (numret > 0) ret[0].SetInt(sprframe->Texture[rotation].GetIndex()); + if (numret > 1) ret[1].SetInt(!!(sprframe->Flip & (1 << rotation))); + if (numret > 2) ret[2].SetVector2(DVector2(scalex, scaley)); + return MIN(3, numret); +} + + //========================================================================== // // Find the actor that a state belongs to. diff --git a/src/p_user.cpp b/src/p_user.cpp index 0860796ef5..6e7d7c8ec7 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -60,6 +60,7 @@ #include "p_spec.h" #include "virtual.h" #include "g_levellocals.h" +#include "r_data/r_translate.h" static FRandom pr_skullpop ("SkullPop"); @@ -142,6 +143,13 @@ bool FPlayerClass::CheckSkin (int skin) return false; } +DEFINE_ACTION_FUNCTION(FPlayerClass, CheckSkin) +{ + PARAM_SELF_STRUCT_PROLOGUE(FPlayerClass); + PARAM_INT(skin); + ACTION_RETURN_BOOL(self->CheckSkin(skin)); +} + //=========================================================================== // // GetDisplayName @@ -3341,3 +3349,7 @@ DEFINE_FIELD_X(PlayerInfo, player_t, cmd) DEFINE_FIELD_X(PlayerInfo, player_t, original_cmd) DEFINE_FIELD_X(PlayerInfo, player_t, userinfo) DEFINE_FIELD_X(PlayerInfo, player_t, weapons) + +DEFINE_FIELD(FPlayerClass, Type) +DEFINE_FIELD(FPlayerClass, Flags) +DEFINE_FIELD(FPlayerClass, Skins) diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 64f490b302..bd31d9a30a 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -1200,6 +1200,63 @@ void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayer R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL, NULL); } + +DEFINE_ACTION_FUNCTION(_Translation, SetPlayerTranslation) +{ + PARAM_PROLOGUE; + PARAM_UINT(tgroup); + PARAM_UINT(tnum); + PARAM_UINT(pnum); + PARAM_POINTER(cls, FPlayerClass); + + if (pnum >= MAXPLAYERS || tgroup >= NUM_TRANSLATION_TABLES || tnum >= translationtables[tgroup].Size()) + { + ACTION_RETURN_BOOL(false); + } + auto self = &players[pnum]; + int PlayerColor = self->userinfo.GetColor(); + int PlayerSkin = self->userinfo.GetSkin(); + int PlayerColorset = self->userinfo.GetColorSet(); + + if (cls != nullptr) + { + PlayerSkin = R_FindSkin(skins[PlayerSkin].name, int(cls - &PlayerClasses[0])); + R_GetPlayerTranslation(PlayerColor, GetColorSet(cls->Type, PlayerColorset), + &skins[PlayerSkin], translationtables[tgroup][tnum]); + } + ACTION_RETURN_BOOL(true); +} + +//---------------------------------------------------------------------------- +// +// +// +//---------------------------------------------------------------------------- + +struct FTranslation +{ + PalEntry colors[256]; +}; + +DEFINE_ACTION_FUNCTION(_Translation, SetTranslation) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTranslation); + PARAM_UINT(tgroup); + PARAM_UINT(tnum); + if (tgroup >= NUM_TRANSLATION_TABLES || tnum >= translationtables[tgroup].Size()) + { + ACTION_RETURN_BOOL(false); + } + auto remap = translationtables[tgroup][tnum]; + int i = 0; + for (auto p : self->colors) + { + remap->Palette[i] = p; + remap->Remap[i] = ColorMatcher.Pick(p); + } + ACTION_RETURN_BOOL(true); +} + //---------------------------------------------------------------------------- // // diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index eb4ed2e47f..d6b89c1a0b 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -2456,7 +2456,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) ExpEmit FxAssign::Emit(VMFunctionBuilder *build) { static const BYTE loadops[] = { OP_LK, OP_LKF, OP_LKS, OP_LKP }; - assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); + assert(Base->ValueType->GetRegType() == Right->ValueType->GetRegType()); ExpEmit pointer = Base->Emit(build); Address = pointer; @@ -2974,6 +2974,12 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx) delete this; return nullptr; } + if (!left->ValueType || !right->ValueType) + { + ScriptPosition.Message(MSG_ERROR, "ValueType not set"); + delete this; + return nullptr; + } if (left->IsVector() || right->IsVector()) { @@ -3552,6 +3558,16 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx) goto error; } } + else if (left->IsPointer() && static_cast(left->ValueType)->PointedType == right->ValueType) + { + bool writable; + if (!right->RequestAddress(ctx, &writable)) goto error; + } + else if (right->IsPointer() && static_cast(right->ValueType)->PointedType == left->ValueType) + { + bool writable; + if (!left->RequestAddress(ctx, &writable)) goto error; + } else { goto error; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 8cd10b75d3..c736b5487e 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -754,6 +754,10 @@ void InitThingdef() sectorportalstruct->Size = sizeof(FSectorPortal); sectorportalstruct->Align = alignof(FSectorPortal); + auto playerclassstruct = NewNativeStruct("PlayerClass", nullptr); + playerclassstruct->Size = sizeof(FPlayerClass); + playerclassstruct->Align = alignof(FPlayerClass); + // set up the lines array in the sector struct. This is a bit messy because the type system is not prepared to handle a pointer to an array of pointers to a native struct even remotely well... // As a result, the size has to be set to something large and arbritrary because it can change between maps. This will need some serious improvement when things get cleaned up. sectorstruct->AddNativeField("lines", NewPointer(NewResizableArray(NewPointer(linestruct, false)), false), myoffsetof(sector_t, Lines), VARF_Native); @@ -789,6 +793,10 @@ void InitThingdef() PField *aacf = new PField("AllActorClasses", aact, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PClassActor::AllActorClasses); Namespaces.GlobalNamespace->Symbols.AddSymbol(aacf); + auto plrcls = NewPointer(NewResizableArray(playerclassstruct), false); + PField *plrclsf = new PField("PlayerClasses", plrcls, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&PlayerClasses); + Namespaces.GlobalNamespace->Symbols.AddSymbol(plrclsf); + // set up a variable for the DEH data PStruct *dstruct = NewNativeStruct("DehInfo", nullptr); PField *dehf = new PField("deh", dstruct, VARF_Native | VARF_Static, (intptr_t)&deh); diff --git a/src/scripting/zscript/zcc-parse.lemon b/src/scripting/zscript/zcc-parse.lemon index bae8284931..6d3e8a856c 100644 --- a/src/scripting/zscript/zcc-parse.lemon +++ b/src/scripting/zscript/zcc-parse.lemon @@ -12,6 +12,10 @@ static void SetNodeLine(ZCC_TreeNode *name, ZCCToken &tok) static void SetNodeLine(ZCC_TreeNode *name, ZCC_TreeNode *node) { + if (name == nullptr || node == nullptr) + { + I_Error("Fatal parse error"); + } name->SourceLoc = node->SourceLoc; } diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 114919df9f..bbbb016ea0 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -1189,6 +1189,40 @@ int FTextureManager::CountLumpTextures (int lumpnum) return 0; } +//========================================================================== +// +// +// +//========================================================================== + +DEFINE_ACTION_FUNCTION(_TexMan, GetSize) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + auto tex = TexMan[FSetTextureID(texid)]; + int x, y; + if (tex != nullptr) + { + x = tex->GetWidth(); + y = tex->GetHeight(); + } + else x = y = -1; + if (numret > 0) ret[0].SetInt(x); + if (numret > 1) ret[1].SetInt(x); + return MIN(numret, 2); +} + +DEFINE_ACTION_FUNCTION(_TexMan, GetScaledSize) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + auto tex = TexMan[FSetTextureID(texid)]; + if (tex != nullptr) + { + ACTION_RETURN_VEC2(DVector2(tex->GetScaledWidthDouble(), tex->GetScaledHeightDouble())); + } + ACTION_RETURN_VEC2(DVector2(-1, -1)); +} //========================================================================== // diff --git a/src/v_draw.cpp b/src/v_draw.cpp index d2b09b0d10..ca5e1fa372 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -1716,6 +1716,17 @@ void V_DrawFrame (int left, int top, int width, int height) screen->DrawTexture (TexMan[border->br], left+width, top+height, TAG_DONE); } +DEFINE_ACTION_FUNCTION(_Screen, DrawFrame) +{ + PARAM_PROLOGUE; + PARAM_INT(x); + PARAM_INT(y); + PARAM_INT(w); + PARAM_INT(h); + V_DrawFrame(x, y, w, h); + return 0; +} + //========================================================================== // // V_DrawBorder diff --git a/src/v_font.cpp b/src/v_font.cpp index 6690540015..a82bd16c17 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -2739,3 +2739,8 @@ void V_ClearFonts() SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = NULL; } +DEFINE_ACTION_FUNCTION(FFont, GetCursor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + ACTION_RETURN_STRING(FString(self->GetCursor())); +} \ No newline at end of file diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 551d909c5e..8774f2a7b7 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -6,11 +6,13 @@ #include "zscript/actor.txt" #include "zscript/actor_checks.txt" -#include "zscript/menu/menu.txt" #include "zscript/menu/menuitembase.txt" -#include "zscript/menu/optionmenuitems.txt" +#include "zscript/menu/menu.txt" +#include "zscript/menu/listmenuitems.txt" #include "zscript/menu/optionmenuitems.txt" #include "zscript/menu/joystickmenu.txt" +#include "zscript/menu/playerdisplay.txt" +#include "zscript/menu/playermenu.txt" #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 2fe42d31a0..1465f5b3ac 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -42,6 +42,8 @@ struct TexMan native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny); native static void ReplaceTextures(String from, String to, int flags); + native static int, int GetSize(TextureID tex); + native static Vector2 GetScaledSize(TextureID tex); } enum DrawTextureTags @@ -118,7 +120,7 @@ struct Screen native native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...); native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...); native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...); - + native static void DrawFrame(int x, int y, int w, int h); } class BrokenLines : Object native @@ -193,6 +195,7 @@ struct Font native native int GetCharWidth(int code); native int StringWidth(String code); native int GetHeight(); + native String GetCursor(); native static int FindFontColor(Name color); native static Font FindFont(Name fontname); @@ -200,6 +203,18 @@ struct Font native native static BrokenLines BreakLines(String text, int maxlen); } +struct Translation +{ + Color colors[256]; + + native bool SetTranslation(int group, int num); + native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass); + static int MakeID(int group, int num) + { + return (group << 16) + num; + } +} + struct Console native { native static void HideConsole(); @@ -429,6 +444,7 @@ struct State native native int DistanceTo(state other); native bool ValidateSpriteFrame(); + native TextureID, bool, Vector2 GetSpriteTexture(int rotation, int skin = 0, Vector2 scale = (0,0)); } struct F3DFloor native diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index f31493077e..ef2c4521f1 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1,6 +1,7 @@ // for flag changer functions. const FLAG_NO_CHANGE = -1; const MAXPLAYERS = 8; +const MAXPLAYERNAME = 15; enum EStateUseFlags { diff --git a/wadsrc/static/zscript/menu/joystickmenu.txt b/wadsrc/static/zscript/menu/joystickmenu.txt index 3d40854675..57f5226e7f 100644 --- a/wadsrc/static/zscript/menu/joystickmenu.txt +++ b/wadsrc/static/zscript/menu/joystickmenu.txt @@ -1,3 +1,37 @@ +/* +** joystickmenu.cpp +** The joystick configuration menus +** +**--------------------------------------------------------------------------- +** 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. +**--------------------------------------------------------------------------- +** +*/ + //============================================================================= // // @@ -129,7 +163,7 @@ class OptionMenuItemJoyMap : OptionMenuItemOptionBase } else { - selection = OptionValues.GetValue(mValues, selection); + selection = int(OptionValues.GetValue(mValues, selection)); } Menu.GetCurrentJoystickConfig().SetAxisMap(mAxis, selection); } diff --git a/wadsrc/static/zscript/menu/listmenuitems.txt b/wadsrc/static/zscript/menu/listmenuitems.txt new file mode 100644 index 0000000000..ddf7b6f470 --- /dev/null +++ b/wadsrc/static/zscript/menu/listmenuitems.txt @@ -0,0 +1,266 @@ +/* +** listmenu.cpp +** A simple menu consisting of a list of items +** +**--------------------------------------------------------------------------- +** 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. +**--------------------------------------------------------------------------- +** +*/ + + +class ListMenuItem : MenuItemBase +{ + void DrawSelector(int xofs, int yofs, TextureID tex) + { + if (tex.isNull()) + { + if ((Menu.MenuTime() % 8) < 6) + { + screen.DrawText(ConFont, OptionMenuSettings.mFontColorSelection, + (mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2, + (mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2, + "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac + ); + } + } + else + { + screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true); + } + } +} + +//============================================================================= +// +// static patch +// +//============================================================================= + +class ListMenuItemStaticPatch : ListMenuItem +{ + TextureID mTexture; + bool mCentered; + + void Init(int x, int y, TextureID patch, bool centered) + { + Super.Init(x, y); + mTexture = patch; + mCentered = centered; + } + + override void Drawer(bool selected) + { + if (!mTexture.Exists()) + { + return; + } + + int x = mXpos; + Vector2 vec = TexMan.GetScaledSize(mTexture); + if (mYpos >= 0) + { + if (mCentered) x -= int(vec.X) / 2; + screen.DrawTexture (mTexture, true, x, mYpos, DTA_Clean, true); + } + else + { + int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth()>>1); + if (mCentered) x -= (int(vec.X) * CleanXfac)/2; + screen.DrawTexture (mTexture, true, x, -mYpos*CleanYfac, DTA_CleanNoMove, true); + } + } +} + +//============================================================================= +// +// static text +// +//============================================================================= + +class ListMenuItemStaticText : ListMenuItem +{ + String mText; + Font mFont; + int mColor; + bool mCentered; + + void Init(int x, int y, String text, Font font, int color, bool centered) + { + Super.Init(x, y); + mText = text; + mFont = font; + mColor = color; + mCentered = centered; + } + + override void Drawer(bool selected) + { + if (mText.Length() != 0) + { + String text = Stringtable.Localize(mText); + if (mYpos >= 0) + { + int x = mXpos; + if (mCentered) x -= mFont.StringWidth(text)/2; + screen.DrawText(mFont, mColor, x, mYpos, text, DTA_Clean, true); + } + else + { + int x = (mXpos - 160) * CleanXfac + (Screen.GetWidth() >> 1); + if (mCentered) x -= (mFont.StringWidth(text) * CleanXfac)/2; + screen.DrawText (mFont, mColor, x, -mYpos*CleanYfac, text, DTA_CleanNoMove, true); + } + } + } +} + +//============================================================================= +// +// selectable items +// +//============================================================================= + +class ListMenuItemSelectable : ListMenuItem +{ + int mHotkey; + int mHeight; + int mParam; + + void Init(int x, int y, int height, Name childmenu, int param = -1) + { + Super.Init(x, y, childmenu); + mHeight = height; + mParam = param; + mHotkey = 0; + } + + override bool CheckCoordinate(int x, int y) + { + return mEnabled && y >= mYpos && y < mYpos + mHeight; // no x check here + } + + override bool Selectable() + { + return mEnabled; + } + + override bool CheckHotkey(int c) + { + return c == mHotkey; + } + + override bool Activate() + { + Menu.SetMenu(mAction, mParam); + return true; + } + + override bool MouseEvent(int type, int x, int y) + { + if (type == Menu.MOUSE_Release) + { + let m = Menu.GetCurrentMenu(); + if (m != NULL && m.MenuEvent(Menu.MKEY_Enter, true)) + { + return true; + } + } + return false; + } + + override Name, int GetAction() + { + return mAction, mParam; + } +} + +//============================================================================= +// +// text item +// +//============================================================================= + +class ListMenuItemText : ListMenuItemSelectable +{ + String mText; + Font mFont; + int mColor; + int mColorSelected; + + void Init(int x, int y, int height, int hotkey, String text, Font font, int color, int color2, Name child, int param = 0) + { + Super.Init(x, y, height, child, param); + mText = text; + mFont = font; + mColor = color; + mColorSelected = color2; + mHotkey = hotkey; + } + + override void Drawer(bool selected) + { + screen.DrawText(mFont, selected ? mColorSelected : mColor, mXpos, mYpos, mText, DTA_Clean, true); + } + + override int GetWidth() + { + return min(1, mFont.StringWidth(StringTable.Localize(mText))); + } +} + +//============================================================================= +// +// patch item +// +//============================================================================= + +class ListMenuItemPatch : ListMenuItemSelectable +{ + TextureID mTexture; + + void Init(int x, int y, int height, int hotkey, TextureID patch, Name child, int param = 0) + { + Super.Init(x, y, height, child, param); + mHotkey = hotkey; + mTexture = patch; + } + + override void Drawer(bool selected) + { + screen.DrawTexture (mTexture, true, mXpos, mYpos, DTA_Clean, true); + } + + override int GetWidth() + { + return TexMan.GetSize(mTexture); + } + +} + diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt index 85cf747c3e..511615fea0 100644 --- a/wadsrc/static/zscript/menu/menu.txt +++ b/wadsrc/static/zscript/menu/menu.txt @@ -73,13 +73,16 @@ class Menu : Object native MOUSE_Release }; - //native static int MenuTime(); + native static int MenuTime(); native static void SetVideoMode(); native static Menu GetCurrentMenu(); native static JoystickConfig GetCurrentJoystickConfig(); native static void SetMenu(Name mnu, int param = 0); native static void StartMessage(String msg, int mode = 0, Name command = 'none'); + virtual void SetFocus(MenuItemBase fc) {} + virtual bool CheckFocus(MenuItemBase fc) { return false; } + virtual void ReleaseFocus() {} native virtual bool MenuEvent (int mkey, bool fromcontroller); native virtual bool MouseEvent(int type, int mx, int my); @@ -104,6 +107,40 @@ class MenuDescriptor : Object native native Class mClass; } +class ListMenuDescriptor : MenuDescriptor native +{ + native Array mItems; + native int mSelectedItem; + native int mSelectOfsX; + native int mSelectOfsY; + native TextureID mSelector; + native int mDisplayTop; + native int mXpos, mYpos; + native int mWLeft, mWRight; + 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 Font mFont; + native int mFontColor; + native int mFontColor2; + native bool mCenter; + + void Reset() + { + // Reset the default settings (ignore all other values in the struct) + mSelectOfsX = 0; + mSelectOfsY = 0; + mSelector.SetInvalid(); + mDisplayTop = 0; + mXpos = 0; + mYpos = 0; + mLinespacing = 0; + mNetgameMessage = ""; + mFont = NULL; + mFontColor = Font.CR_UNTRANSLATED; + mFontColor2 = Font.CR_UNTRANSLATED; + } +} + struct FOptionMenuSettings { int mTitleColor; @@ -148,20 +185,17 @@ class OptionMenu : Menu native native OptionMenuItem mFocusControl; native OptionMenuDescriptor mDesc; - - void SetFocus(OptionMenuItem fc) + override void SetFocus(MenuItemBase fc) { - mFocusControl = fc; + mFocusControl = OptionMenuItem(fc); } - - bool CheckFocus(OptionMenuItem fc) + override bool CheckFocus(MenuItemBase fc) { return mFocusControl == fc; } - - void ReleaseFocus() + override void ReleaseFocus() { - mFocusControl = null; + mFocusControl = NULL; } } diff --git a/wadsrc/static/zscript/menu/menuitembase.txt b/wadsrc/static/zscript/menu/menuitembase.txt index 9015aa758f..2840b41b99 100644 --- a/wadsrc/static/zscript/menu/menuitembase.txt +++ b/wadsrc/static/zscript/menu/menuitembase.txt @@ -38,29 +38,5 @@ native virtual bool MenuEvent (int mkey, bool fromcontroller);// { return false; virtual int GetY() { return mYpos; } virtual int GetX() { return mXpos; } virtual void SetX(int x) { mXpos = x; } - - /* - virtual void DrawSelector(int xofs, int yofs, TextureID tex) - { - if (tex.isNull()) - { - if ((Menu.MenuTime() % 8) < 6) - { - screen.DrawText(ConFont, OptionSettings.mFontColorSelection, - (mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2, - (mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2, - "\xd", - DTA_CellX, 8 * CleanXfac, - DTA_CellY, 8 * CleanYfac, - TAG_DONE); - } - } - else - { - screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE); - } - } - */ - } diff --git a/wadsrc/static/zscript/menu/optionmenuitems.txt b/wadsrc/static/zscript/menu/optionmenuitems.txt index 9205768789..85687d7156 100644 --- a/wadsrc/static/zscript/menu/optionmenuitems.txt +++ b/wadsrc/static/zscript/menu/optionmenuitems.txt @@ -1043,7 +1043,7 @@ class OptionMenuTextField : OptionMenuFieldBase override String Represent() { - if (mEntering) return mEditName .. ((gameinfo.gametype & GAME_DoomStrifeChex) ? "_" : "["); + if (mEntering) return mEditName .. SmallFont.GetCursor(); else return GetCVarString(); } diff --git a/wadsrc/static/zscript/menu/playerdisplay.txt b/wadsrc/static/zscript/menu/playerdisplay.txt new file mode 100644 index 0000000000..7665df516c --- /dev/null +++ b/wadsrc/static/zscript/menu/playerdisplay.txt @@ -0,0 +1,286 @@ +/* +** playerdisplay.cpp +** The player display for the player setup and class selection screen +** +**--------------------------------------------------------------------------- +** 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. +**--------------------------------------------------------------------------- +** +*/ + +//============================================================================= +// +// the player sprite window +// +//============================================================================= + +class ListMenuItemPlayerDisplay : ListMenuItem +{ + ListMenuDescriptor mOwner; + TextureID mBackdrop; + PlayerClass mPlayerClass; + State mPlayerState; + int mPlayerTics; + bool mNoportrait; + int8 mRotation; + int8 mMode; // 0: automatic (used by class selection), 1: manual (used by player setup) + int8 mTranslate; + int mSkin; + int mRandomClass; + int mRandomTimer; + int mClassNum; + + enum EPDFlags + { + PDF_ROTATION = 0x10001, + PDF_SKIN = 0x10002, + PDF_CLASS = 0x10003, + PDF_MODE = 0x10004, + PDF_TRANSLATE = 0x10005, + }; + + //============================================================================= + // + // + // + //============================================================================= + void Init(ListMenuDescriptor menu, int x, int y, Color c1, Color c2, bool np, Name command) + { + Super.Init(x, y, command); + mOwner = menu; + + Translation trans; + for (int i = 0; i < 256; i++) + { + int r = c1.r + c2.r * i / 255; + int g = c1.g + c2.g * i / 255; + int b = c1.b + c2.b * i / 255; + trans.colors[i] = Color(255, r, g, b); + } + trans.SetTranslation(TRANSLATION_Players, MAXPLAYERS + 1); + + mBackdrop = TexMan.CheckForTexture("PlayerBackdrop", TexMan.Type_MiscPatch); + mPlayerClass = NULL; + mPlayerState = NULL; + mNoportrait = np; + mMode = 0; + mRotation = 0; + mTranslate = false; + mSkin = 0; + mRandomClass = 0; + mRandomTimer = 0; + mClassNum = -1; + } + + private void UpdatePlayer(int classnum) + { + mPlayerClass = PlayerClasses[classnum]; + mPlayerState = GetDefaultByType (mPlayerClass.Type).SeeState; + if (mPlayerState == NULL) + { // No see state, so try spawn state. + mPlayerState = GetDefaultByType (mPlayerClass.Type).SpawnState; + } + mPlayerTics = mPlayerState != NULL ? mPlayerState.Tics : -1; + } + + //============================================================================= + // + // + // + //============================================================================= + + private void UpdateRandomClass() + { + if (--mRandomTimer < 0) + { + if (++mRandomClass >= PlayerClasses.Size ()) mRandomClass = 0; + UpdatePlayer(mRandomClass); + mPlayerTics = mPlayerState != NULL ? mPlayerState.Tics : -1; + mRandomTimer = 6; + + // Since the newly displayed class may use a different translation + // range than the old one, we need to update the translation, too. + Translation.SetPlayerTranslation(TRANSLATION_Players, MAXPLAYERS, consoleplayer, mPlayerClass); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + void SetPlayerClass(int classnum, bool force = false) + { + if (classnum < 0 || classnum >= PlayerClasses.Size ()) + { + if (mClassNum != -1) + { + mClassNum = -1; + mRandomTimer = 0; + UpdateRandomClass(); + } + } + else if (mPlayerClass != PlayerClasses[classnum] || force) + { + UpdatePlayer(classnum); + mClassNum = classnum; + } + } + + //============================================================================= + // + // + // + //============================================================================= + + bool UpdatePlayerClass() + { + if (mOwner.mSelectedItem >= 0) + { + int classnum; + Name seltype; + + [seltype, classnum] = mOwner.mItems[mOwner.mSelectedItem].GetAction(); + + if (seltype != 'Episodemenu') return false; + if (PlayerClasses.Size() == 0) return false; + + SetPlayerClass(classnum); + return true; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetValue(int i, int value) + { + switch (i) + { + case PDF_MODE: + mMode = value; + return true; + + case PDF_ROTATION: + mRotation = value; + return true; + + case PDF_TRANSLATE: + mTranslate = value; + + case PDF_CLASS: + SetPlayerClass(value, true); + break; + + case PDF_SKIN: + mSkin = value; + break; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Ticker() + { + if (mClassNum < 0) UpdateRandomClass(); + + if (mPlayerState != NULL && mPlayerState.Tics != -1 && mPlayerState.NextState != NULL) + { + if (--mPlayerTics <= 0) + { + mPlayerState = mPlayerState.NextState; + mPlayerTics = mPlayerState.Tics; + } + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + if (mMode == 0 && !UpdatePlayerClass()) + { + return; + } + let playdef = GetDefaultByType((class)(mPlayerClass.Type)); + + Name portrait = playdef.Portrait; + + if (portrait != 'None' && !mNoportrait) + { + TextureID texid = TexMan.CheckForTexture(portrait, TexMan.Type_MiscPatch); + screen.DrawTexture (texid, true, mXpos, mYpos, DTA_Clean, true); + } + int x = (mXpos - 160) * CleanXfac + (screen.GetWidth() >> 1); + int y = (mYpos - 100) * CleanYfac + (screen.GetHeight() >> 1); + + screen.DrawTexture(mBackdrop, false, x, y - 1, + DTA_DestWidth, 72 * CleanXfac, + DTA_DestHeight, 80 * CleanYfac, + DTA_TranslationIndex, Translation.MakeID(TRANSLATION_Players, MAXPLAYERS + 1), + DTA_Masked, true); + + Screen.DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1); + + if (mPlayerState != NULL) + { + Vector2 Scale; + TextureID sprite; + bool flip; + + [sprite, flip, Scale] = mPlayerState.GetSpriteTexture(mRotation, mSkin, playdef.Scale); + + if (sprite.IsValid()) + { + int trans = mTranslate? Translation.MakeID(TRANSLATION_Players, MAXPLAYERS) : 0; + let tscale = TexMan.GetScaledSize(sprite); + Scale.X *= CleanXfac * tscale.X; + Scale.Y *= CleanYfac * tscale.Y; + + screen.DrawTexture (sprite, false, + x + 36*CleanXfac, y + 71*CleanYfac, + DTA_DestWidthF, Scale.X, DTA_DestHeightF, Scale.Y, + DTA_TranslationIndex, trans, + DTA_FlipX, flip); + } + } + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/menu/playermenu.txt b/wadsrc/static/zscript/menu/playermenu.txt new file mode 100644 index 0000000000..338772b6bc --- /dev/null +++ b/wadsrc/static/zscript/menu/playermenu.txt @@ -0,0 +1,470 @@ +/* +** playermenu.txt +** The player setup menu +** +**--------------------------------------------------------------------------- +** Copyright 2001-2010 Randy Heit +** 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. +**--------------------------------------------------------------------------- +** +*/ + +//============================================================================= +// +// items for the player menu +// +//============================================================================= + +class PlayerNameBox : ListMenuItemSelectable +{ + String mText; + Font mFont; + int mFontColor; + int mFrameSize; + String mPlayerName; + String mEditName; + bool mEntering; + + //============================================================================= + // + // Player's name + // + //============================================================================= + + void Init(int x, int y, int height, int frameofs, String text, Font font, int color, Name command) + { + Super.Init(x, y, height, command); + mText = text; + mFont = font; + mFontColor = color; + mFrameSize = frameofs; + mPlayerName = ""; + mEntering = false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetString(int i, String s) + { + if (i == 0) + { + mPlayerName = s.Mid(0, MAXPLAYERNAME); + return true; + } + return false; + } + + override bool, String GetString(int i) + { + if (i == 0) + { + return true, mPlayerName; + } + return false, ""; + } + + //============================================================================= + // + // [RH] Width of the border is variable + // + //============================================================================= + + protected void DrawBorder (int x, int y, int len) + { + let left = TexMan.CheckForTexture("M_LSLEFT", TexMan.Type_MiscPatch); + let mid = TexMan.CheckForTexture("M_LSCNTR", TexMan.Type_MiscPatch); + let right = TexMan.CheckForTexture("M_LSRGHT", TexMan.Type_MiscPatch); + if (left.IsValid() && right.IsValid() && mid.IsValid()) + { + int i; + + screen.DrawTexture (left, false, x-8, y+7, DTA_Clean, true); + + for (i = 0; i < len; i++) + { + screen.DrawTexture (mid, false, x, y+7, DTA_Clean, true); + x += 8; + } + + screen.DrawTexture (right, false, x, y+7, DTA_Clean, true); + } + else + { + let slot = TexMan.CheckForTexture("M_FSLOT", TexMan.Type_MiscPatch); + if (slot.IsValid()) + { + screen.DrawTexture (slot, false, x, y+1, DTA_Clean, true); + } + else + { + screen.Clear(x, y, x + len, y + SmallFont.GetHeight() * 3/2, 0); + } + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + String text = StringTable.Localize(mText); + if (text.Length() > 0) + { + screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true); + } + + // Draw player name box + int x = mXpos + mFont.StringWidth(text) + 16 + mFrameSize; + DrawBorder (x, mYpos - mFrameSize, MAXPLAYERNAME+1); + if (!mEntering) + { + screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, mPlayerName, DTA_Clean, true); + } + else + { + let printit = mEditName .. SmallFont.GetCursor(); + screen.DrawText (SmallFont, Font.CR_UNTRANSLATED, x + mFrameSize, mYpos, printit, DTA_Clean, true); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent(int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Enter) + { + Menu.MenuSound ("menu/choose"); + mEditName = mPlayerName; + mEntering = true; + //DMenu *input = new DTextEnterMenu(Menu.CurrentMenu, mEditName, MAXPLAYERNAME, 2, fromcontroller); + //M_ActivateMenu(input); + return true; + } + else if (mkey == Menu.MKEY_Input) + { + mPlayerName = mEditName; + mEntering = false; + return true; + } + else if (mkey == Menu.MKEY_Abort) + { + mEntering = false; + return true; + } + return false; + } + +} + +//============================================================================= +// +// items for the player menu +// +//============================================================================= + +class DValueTextItem : ListMenuItemSelectable +{ + Array mSelections; + String mText; + int mSelection; + Font mFont; + int mFontColor; + int mFontColor2; + + //============================================================================= + // + // items for the player menu + // + //============================================================================= + + void Init(int x, int y, int height, String text, Font font, int color, int valuecolor, Name command, Name values) + { + Super.Init(x, y, height, command); + mText = text; + mFont = font; + mFontColor = color; + mFontColor2 = valuecolor; + mSelection = 0; + let cnt = OptionValues.GetCount(values); + for(int i = 0; i < cnt; i++) + { + SetString(i, OptionValues.GetText(values, i)); + } + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetString(int i, String s) + { + // should actually use the index... + if (i==0) mSelections.Clear(); + mSelections.Push(s); + return true; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetValue(int i, int value) + { + if (i == 0) + { + mSelection = value; + return true; + } + return false; + } + + override bool, int GetValue(int i) + { + if (i == 0) + { + return true, mSelection; + } + return false, 0; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mSelections.Size() > 1) + { + if (mkey == Menu.MKEY_Left) + { + Menu.MenuSound("menu/change"); + if (--mSelection < 0) mSelection = mSelections.Size() - 1; + return true; + } + else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter) + { + Menu.MenuSound("menu/change"); + if (++mSelection >= mSelections.Size()) mSelection = 0; + return true; + } + } + return (mkey == Menu.MKEY_Enter); // needs to eat enter keys so that Activate won't get called + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + String text = Stringtable.Localize(mText); + screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true); + + int x = mXpos + mFont.StringWidth(text) + 8; + if (mSelections.Size() > 0) + { + screen.DrawText(mFont, mFontColor2, x, mYpos, mSelections[mSelection], DTA_Clean, true); + } + } + +} + +//============================================================================= +// +// items for the player menu +// +//============================================================================= + +class DSliderItem : ListMenuItemSelectable +{ + String mText; + Font mFont; + int mFontColor; + int mMinrange, mMaxrange; + int mStep; + int mSelection; + + //============================================================================= + // + // items for the player menu + // + //============================================================================= + + void Init(int x, int y, int height, String text, Font font, int color, Name command, int min, int max, int step) + { + Super.Init(x, y, height, command); + mText = text; + mFont = font; + mFontColor = color; + mSelection = 0; + mMinrange = min; + mMaxrange = max; + mStep = step; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool SetValue(int i, int value) + { + if (i == 0) + { + mSelection = value; + return true; + } + return false; + } + + override bool, int GetValue(int i) + { + if (i == 0) + { + return true, mSelection; + } + return false, 0; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MenuEvent (int mkey, bool fromcontroller) + { + if (mkey == Menu.MKEY_Left) + { + Menu.MenuSound("menu/change"); + if ((mSelection -= mStep) < mMinrange) mSelection = mMinrange; + return true; + } + else if (mkey == Menu.MKEY_Right || mkey == Menu.MKEY_Enter) + { + Menu.MenuSound("menu/change"); + if ((mSelection += mStep) > mMaxrange) mSelection = mMaxrange; + return true; + } + return false; + } + + //============================================================================= + // + // + // + //============================================================================= + + override bool MouseEvent(int type, int x, int y) + { + let lm = Menu.GetCurrentMenu(); + if (type != Menu.MOUSE_Click) + { + if (!lm.CheckFocus(self)) return false; + } + if (type == Menu.MOUSE_Release) + { + lm.ReleaseFocus(); + } + + int slide_left = SmallFont.StringWidth ("Green") + 8 + mXpos; + int slide_right = slide_left + 12*8; // 12 char cells with 8 pixels each. + + if (type == Menu.MOUSE_Click) + { + if (x < slide_left || x >= slide_right) return true; + } + + x = clamp(x, slide_left, slide_right); + int v = mMinrange + (x - slide_left) * (mMaxrange - mMinrange) / (slide_right - slide_left); + if (v != mSelection) + { + mSelection = v; + Menu.MenuSound("menu/change"); + } + if (type == Menu.MOUSE_Click) + { + lm.SetFocus(self); + } + return true; + } + + //============================================================================= + // + // + // + //============================================================================= + + protected void DrawSlider (int x, int y) + { + int range = mMaxrange - mMinrange; + int cur = mSelection - mMinrange; + + x = (x - 160) * CleanXfac + screen.GetWidth() / 2; + y = (y - 100) * CleanYfac + screen.GetHeight() / 2; + + screen.DrawText (ConFont, Font.CR_WHITE, x, y, "\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); + screen.DrawText (ConFont, Font.CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y, "\x13", DTA_CellX, 8 * CleanXfac, DTA_CellY, 8 * CleanYfac); + } + + //============================================================================= + // + // + // + //============================================================================= + + override void Drawer(bool selected) + { + String text = StringTable.Localize(mText); + + screen.DrawText(mFont, selected? OptionMenuSettings.mFontColorSelection : mFontColor, mXpos, mYpos, text, DTA_Clean, true); + + int x = SmallFont.StringWidth ("Green") + 8 + mXpos; + int x2 = SmallFont.StringWidth (text) + 8 + mXpos; + DrawSlider (MAX(x2, x), mYpos); + } +} \ No newline at end of file diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index dc1d1ba1d4..7b8ba8f307 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -313,3 +313,12 @@ userinfo_t userinfo; native void BringUpWeapon(); } + +struct PlayerClass native +{ + native class Type; + native uint Flags; + native Array Skins; + + native bool CheckSkin(int skin); +}