From 1f1e39fac06acde06e1892dee847b5c1e60fa16f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 25 Nov 2019 00:02:00 +0100 Subject: [PATCH] - consolidation of texts for episode and skill menus So far without localization capability - the engine cannot handle it yet. --- source/blood/src/levels.cpp | 5 ++- source/common/gamecontrol.cpp | 47 ++++++++++++++++++++++-- source/common/menu/menu.h | 13 ++++++- source/common/menu/menudef.cpp | 5 +++ source/duke3d/src/d_menu.cpp | 34 ++++++------------ source/duke3d/src/gamedef.cpp | 54 ++++++++-------------------- source/duke3d/src/gameexec.cpp | 4 ++- source/duke3d/src/global.cpp | 7 +--- source/duke3d/src/global.h | 5 +-- source/duke3d/src/menus.cpp | 44 +---------------------- source/duke3d/src/premap.cpp | 2 +- source/duke3d/src/screens.cpp | 3 +- source/glbackend/gl_texture.cpp | 6 +--- source/rr/src/gamedef.cpp | 44 +++++------------------ source/rr/src/global.cpp | 4 --- source/rr/src/global.h | 4 --- source/rr/src/menus.cpp | 25 ++++++------- source/rr/src/premap.cpp | 3 +- source/rr/src/screens.cpp | 3 +- wadsrc/static/demolition/menudef.txt | 24 +++++++++---- 20 files changed, 144 insertions(+), 192 deletions(-) diff --git a/source/blood/src/levels.cpp b/source/blood/src/levels.cpp index c1ad24fae..e477c7265 100644 --- a/source/blood/src/levels.cpp +++ b/source/blood/src/levels.cpp @@ -43,6 +43,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sfx.h" #include "view.h" #include "eventq.h" +#include "menu/menu.h" BEGIN_BLD_NS @@ -236,7 +237,9 @@ void levelLoadDefaults(void) if (!BloodINI->SectionExists(buffer)) break; EPISODEINFO *pEpisodeInfo = &gEpisodeInfo[i]; - strncpy(pEpisodeInfo->at0, BloodINI->GetKeyString(buffer, "Title", buffer), 31); + auto ep_str = BloodINI->GetKeyString(buffer, "Title", buffer); + strncpy(pEpisodeInfo->at0, ep_str, 31); + gVolumeNames[i] = ep_str; // For the menu. strncpy(pEpisodeInfo->at8f08, BloodINI->GetKeyString(buffer, "CutSceneA", ""), BMAX_PATH); pEpisodeInfo->at9028 = BloodINI->GetKeyInt(buffer, "CutWavA", -1); if (pEpisodeInfo->at9028 == 0) diff --git a/source/common/gamecontrol.cpp b/source/common/gamecontrol.cpp index d6f32708e..12981b4c7 100644 --- a/source/common/gamecontrol.cpp +++ b/source/common/gamecontrol.cpp @@ -259,6 +259,49 @@ int GameMain() return r; } +//========================================================================== +// +// Try to keep all initializations of global string variables in this one place +// +//========================================================================== + +#define LOCALIZED_STRING(s) s // change to "${" s "}" later, once all text output functions can replace text macros + +void SetDefaultStrings() +{ + // Hard coded texts for the episode and skill selection menus. + if (g_gameType & GAMEFLAG_DUKE) + { + gVolumeNames[0] = LOCALIZED_STRING("L.A. Meltdown"); + gVolumeNames[1] = LOCALIZED_STRING("Lunar Apocalypse"); + gVolumeNames[2] = LOCALIZED_STRING("Shrapnel City"); + gSkillNames[0] = LOCALIZED_STRING("Piece Of Cake"); + gSkillNames[1] = LOCALIZED_STRING("Let's Rock"); + gSkillNames[2] = LOCALIZED_STRING("Come Get Some"); + gSkillNames[3] = LOCALIZED_STRING("Damn I'm Good"); + } + else if (g_gameType & GAMEFLAG_BLOOD) + { + gSkillNames[0] = LOCALIZED_STRING("STILL KICKING"); + gSkillNames[1] = LOCALIZED_STRING("PINK ON THE INSIDE"); + gSkillNames[2] = LOCALIZED_STRING("LIGHTLY BROILED"); + gSkillNames[3] = LOCALIZED_STRING("WELL DONE"); + gSkillNames[4] = LOCALIZED_STRING("EXTRA CRISPY"); + } + else if (g_gameType & GAMEFLAG_SW) + { + gVolumeNames[0] = LOCALIZED_STRING("Enter the Wang"); + gVolumeNames[1] = LOCALIZED_STRING("Code of Honor"); + + gVolumeSubtitles[0] = LOCALIZED_STRING("Four levels (Shareware Version)"); + gVolumeSubtitles[1] = LOCALIZED_STRING("Eighteen levels (Full Version Only)"); + + gSkillNames[0] = LOCALIZED_STRING("Tiny grasshopper"); + gSkillNames[1] = LOCALIZED_STRING("I Have No Fear"); + gSkillNames[2] = LOCALIZED_STRING("Who Wants Wang"); + gSkillNames[3] = LOCALIZED_STRING("No Pain, No Gain"); + } +} //========================================================================== // // @@ -385,9 +428,7 @@ int CONFIG_Init() Mus_Init(); InitStatistics(); M_Init(); - - - + SetDefaultStrings(); return gi->app_main(); } diff --git a/source/common/menu/menu.h b/source/common/menu/menu.h index 5214e2900..fe5c4b3e3 100644 --- a/source/common/menu/menu.h +++ b/source/common/menu/menu.h @@ -12,6 +12,17 @@ EXTERN_CVAR(Float, snd_menuvolume) EXTERN_CVAR(Int, m_use_mouse); +enum +{ + MAXSKILLS = 7, + MAXVOLUMES = 7, +}; + +// These get filled in by the map definition parsers of the front ends. +extern FString gSkillNames[MAXSKILLS]; +extern FString gVolumeNames[MAXVOLUMES]; +extern FString gVolumeSubtitles[MAXVOLUMES]; +extern int32_t gVolumeFlags[MAXVOLUMES]; const int MENU_TICRATE = 30; extern bool help_disabled, credits_disabled; @@ -654,4 +665,4 @@ template struct TMenuClassDescriptor : public MenuClassDescriptor } }; -#endif \ No newline at end of file +#endif diff --git a/source/common/menu/menudef.cpp b/source/common/menu/menudef.cpp index 33b188b07..6f479e368 100644 --- a/source/common/menu/menudef.cpp +++ b/source/common/menu/menudef.cpp @@ -49,6 +49,11 @@ void ClearSaveGames(); +FString gSkillNames[MAXSKILLS]; +FString gVolumeNames[MAXVOLUMES]; +FString gVolumeSubtitles[MAXVOLUMES]; +int32_t gVolumeFlags[MAXVOLUMES]; + MenuDescriptorList MenuDescriptors; static FListMenuDescriptor DefaultListMenuSettings; // contains common settings for all list menus static FOptionMenuDescriptor DefaultOptionMenuSettings; // contains common settings for all Option menus diff --git a/source/duke3d/src/d_menu.cpp b/source/duke3d/src/d_menu.cpp index fb94c809b..d4c6c71eb 100644 --- a/source/duke3d/src/d_menu.cpp +++ b/source/duke3d/src/d_menu.cpp @@ -128,35 +128,23 @@ void Menu_Init(void) // prepare episodes k = 0; - for (i = 0; i < g_volumeCnt; ++i) + + if (gVolumeNames[i].IsNotEmpty()) { - if (g_volumeNames[i][0]) + if (!(gVolumeFlags[i] & EF_HIDEFROMSP)) { - if (!(g_volumeFlags[i] & EF_HIDEFROMSP)) - { - MEL_EPISODE[i] = &ME_EPISODE[i]; - ME_EPISODE[i] = ME_EPISODE_TEMPLATE; - ME_EPISODE[i].name = g_volumeNames[i]; - } - - // if (!(EpisodeFlags[i] & EF_HIDEFROMMP)) - { - MEOSN_NetEpisodes[k] = g_volumeNames[i]; - MEOSV_NetEpisodes[k] = i; - - k++; - } + MEL_EPISODE[i] = &ME_EPISODE[i]; + ME_EPISODE[i] = ME_EPISODE_TEMPLATE; + ME_EPISODE[i].name = gVolumeNames[i]; } - // prepare levels - MEOS_NETOPTIONS_LEVEL[i] = MEOS_NETOPTIONS_LEVEL_TEMPLATE; - for (j = 0; j < MAXLEVELS; ++j) + // if (!(EpisodeFlags[i] & EF_HIDEFROMMP)) { - MEOSN_NetLevels[i][j] = g_mapInfo[MAXLEVELS * i + j].name; - if (g_mapInfo[i * MAXLEVELS + j].filename != NULL) - MEOS_NETOPTIONS_LEVEL[i].numOptions = j + 1; + MEOSN_NetEpisodes[k] = gVolumeNames[i]; + MEOSV_NetEpisodes[k] = i; + + k++; } - MEOS_NETOPTIONS_LEVEL[i].optionNames = MEOSN_NetLevels[i]; } M_EPISODE.numEntries = g_volumeCnt + 2; diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index c4093393d..8af2b6b0c 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -36,6 +36,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "savegame.h" #include "printf.h" #include "m_argv.h" +#include "menu/menu.h" BEGIN_DUKE_NS @@ -2033,7 +2034,7 @@ void C_DefineVolumeFlags(int32_t vol, int32_t flags) { Bassert((unsigned)vol < MAXVOLUMES); - g_volumeFlags[vol] = flags; + gVolumeFlags[vol] = flags; } void C_UndefineVolume(int32_t vol) @@ -2043,12 +2044,12 @@ void C_UndefineVolume(int32_t vol) for (bssize_t i = 0; i < MAXLEVELS; i++) C_UndefineLevel(vol, i); - g_volumeNames[vol][0] = '\0'; + gVolumeNames[vol] = ""; g_volumeCnt = 0; for (bssize_t i = MAXVOLUMES-1; i >= 0; i--) { - if (g_volumeNames[i][0]) + if (gVolumeNames[i].IsNotEmpty()) { g_volumeCnt = i+1; break; @@ -2060,12 +2061,12 @@ void C_UndefineSkill(int32_t skill) { Bassert((unsigned)skill < MAXSKILLS); - g_skillNames[skill][0] = '\0'; + gSkillNames[skill] = ""; g_skillCnt = 0; for (bssize_t i = MAXSKILLS-1; i >= 0; i--) { - if (g_skillNames[i][0]) + if (gSkillNames[i][0]) { g_skillCnt = i+1; break; @@ -5015,23 +5016,11 @@ repeatcase: continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_volumeNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_volumeNames[j])-1)) - { - initprintf("%s:%d: warning: truncating volume name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_volumeNames[j])-1); - g_warningCnt++; - scriptSkipLine(); - break; - } - } + i = strcspn(textptr, "\r\n"); + gVolumeNames[j] = FString(textptr, i); + textptr += i; + g_volumeCnt = j+1; - g_volumeNames[j][i] = '\0'; continue; case CON_DEFINEVOLUMEFLAGS: @@ -5128,27 +5117,14 @@ repeatcase: continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_skillNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_skillNames[j])-1)) - { - initprintf("%s:%d: warning: truncating skill name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_skillNames[j])-1); - g_warningCnt++; - scriptSkipLine(); - break; - } - } - - g_skillNames[j][i] = '\0'; + i = strcspn(textptr, "\r\n"); + gSkillNames[j] = FString(textptr, i); + textptr+=i; for (i=0; i 0) mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), g_skillNames[ud.m_player_skill], MF_Minifont.pal_deselected_right); @@ -2302,15 +2279,6 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) break; } -#ifdef EDUKE32_ANDROID_MENU - case MENU_SKILL: - { - static const char *s[] = { "EASY - Few enemies, and lots of stuff.", "MEDIUM - Normal difficulty.", "HARD - For experienced players.", "EXPERTS - Lots of enemies, plus they respawn!" }; - if (M_SKILL.currentEntry < ARRAY_SSIZE(s)) - mgametextcenter(origin.x, origin.y + (168<<16), s[M_SKILL.currentEntry]); - } - break; -#endif case MENU_SAVECLEANVERIFY: videoFadeToBlack(1); @@ -2334,16 +2302,6 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) Bsprintf(tempbuf, "Resume game from sequence point:\n\"%s\"", msv.brief.name); Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); } - else if (msv.isOldVer) - { -#if 1 - mgametextcenter(origin.x, origin.y + (90<<16), "You're not supposed to be here."); -#else - Bsprintf(tempbuf, "Start new game:\n%s / %s" - , g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); - Menu_DrawVerifyPrompt(origin.x, origin.y, tempbuf, 2); -#endif - } else { Bsprintf(tempbuf, "Load game:\n\"%s\"", msv.brief.name); diff --git a/source/duke3d/src/premap.cpp b/source/duke3d/src/premap.cpp index ac66b21c4..a8dc821cf 100644 --- a/source/duke3d/src/premap.cpp +++ b/source/duke3d/src/premap.cpp @@ -1339,7 +1339,7 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum) ud.secretlevel = 0; ud.skill_voice = -1; ud.volume_number = volumeNum; - STAT_StartNewGame(g_volumeNames[volumeNum], skillNum); + STAT_StartNewGame(gVolumeNames[volumeNum], skillNum); g_lastAutoSaveArbitraryID = -1; g_lastautosave.reset(); diff --git a/source/duke3d/src/screens.cpp b/source/duke3d/src/screens.cpp index d0f4d5eee..8ef72c260 100644 --- a/source/duke3d/src/screens.cpp +++ b/source/duke3d/src/screens.cpp @@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "sbar.h" #include "screens.h" #include "gamecvars.h" +#include "menu/menu.h" BEGIN_DUKE_NS @@ -961,7 +962,7 @@ void G_DisplayRest(int32_t smoothratio) if (G_HaveUserMap()) levelname = boardfilename; else if (!(G_GetLogoFlags() & LOGO_HIDEEPISODE)) - minitext(5, a+6, g_volumeNames[ud.volume_number], 0, 2+8+16+256); + minitext(5, a+6, gVolumeNames[ud.volume_number], 0, 2+8+16+256); minitext(5, a+6+6, levelname, 0, 2+8+16+256); } } diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 37cc41136..f6d153bd1 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -69,7 +69,6 @@ void FlipNonSquareBlock(T* dst, const T* src, int x, int y, int srcpitch) FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex) { auto siz = tex->GetSize(); - bool npoty = false; const uint8_t* p = tex->Get8BitPixels(); TArray store(siz.x * siz.y, true); @@ -96,9 +95,6 @@ FHardwareTexture* GLInstance::CreateIndexedTexture(FTexture* tex) FHardwareTexture* GLInstance::CreateTrueColorTexture(FTexture* tex, int palid, bool checkfulltransparency, bool rgb8bit) { - auto siz = tex->GetSize(); - bool npoty = false; - auto palette = palid < 0? nullptr : palmanager.GetPaletteData(palid); if (palette == nullptr) return nullptr; auto texbuffer = tex->CreateTexBuffer(palette, CTF_ProcessData); @@ -266,7 +262,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int auto brep = tex->FindReplacement(BRIGHTPAL); if (brep) { - auto htex = LoadTexture(brep->faces[0], TT_HICREPLACE, 0); + LoadTexture(brep->faces[0], TT_HICREPLACE, 0); UseBrightmaps(true); BindTexture(5, mtex, sampler); } diff --git a/source/rr/src/gamedef.cpp b/source/rr/src/gamedef.cpp index 992076693..da4d67fc2 100644 --- a/source/rr/src/gamedef.cpp +++ b/source/rr/src/gamedef.cpp @@ -35,6 +35,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "osd.h" #include "m_crc32.h" #include "printf.h" +#include "menu/menu.h" BEGIN_RR_NS @@ -894,7 +895,7 @@ void C_DefineVolumeFlags(int32_t vol, int32_t flags) { Bassert((unsigned)vol < MAXVOLUMES); - g_volumeFlags[vol] = flags; + gVolumeFlags[vol] = flags; } int32_t C_AllocQuote(int32_t qnum) @@ -1884,23 +1885,10 @@ static int32_t C_ParseCommand(int32_t loop) continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_volumeNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_volumeNames[j])-1)) - { - initprintf("%s:%d: warning: truncating volume name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_volumeNames[j])-1); - g_warningCnt++; - C_NextLine(); - break; - } - } + i = strcspn(textptr, "\r\n"); + gVolumeNames[j] = FString(textptr, i); + textptr+=i; g_volumeCnt = j+1; - g_volumeNames[j][i] = '\0'; continue; case CON_DEFINESKILLNAME: @@ -1921,26 +1909,12 @@ static int32_t C_ParseCommand(int32_t loop) continue; } - i = 0; - - while (*textptr != 0x0a && *textptr != 0x0d && *textptr != 0) - { - g_skillNames[j][i] = *textptr; - textptr++,i++; - if (EDUKE32_PREDICT_FALSE(i >= (signed)sizeof(g_skillNames[j])-1)) - { - initprintf("%s:%d: warning: truncating skill name to %d characters.\n", - g_scriptFileName,g_lineNumber,(int32_t)sizeof(g_skillNames[j])-1); - g_warningCnt++; - C_NextLine(); - break; - } - } - - g_skillNames[j][i] = '\0'; + i = strcspn(textptr, "\r\n"); + gSkillNames[j] = FString(textptr, i); + textptr+=i; for (i=0; i 0) - mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), g_skillNames[ud.m_player_skill], MF_Minifont.pal_deselected_right); + mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), gSkillNames[ud.m_player_skill], MF_Minifont.pal_deselected_right); else mminitext(origin.x + ((90+60)<<16), origin.y + ((90+8+8+8)<<16), "None", MF_Minifont.pal_deselected_right); if (m_coop == 0) { @@ -2199,7 +2200,7 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) { const char *name = g_mapInfo[(savehead.volnum*MAXLEVELS) + savehead.levnum].name; - Bsprintf(tempbuf, "%s / %s", name ? name : "^10unnamed^0", g_skillNames[savehead.skill-1]); + Bsprintf(tempbuf, "%s / %s", name ? name : "^10unnamed^0", gSkillNames[savehead.skill-1].GetChars()); } mgametextcenter(origin.x, origin.y + (168<<16), tempbuf); @@ -2261,7 +2262,7 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) mgametextcenter(origin.x, origin.y + (156<<16), tempbuf); } - Bsprintf(tempbuf,"%s / %s",g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); + Bsprintf(tempbuf,"%s / %s",g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, gSkillNames[ud.player_skill-1].GetChars()); mgametextcenter(origin.x, origin.y + (168<<16), tempbuf); if (ud.volume_number == 0 && ud.level_number == 7) mgametextcenter(origin.x, origin.y + (180<<16), currentboardfilename); @@ -2305,7 +2306,7 @@ static void Menu_PreDraw(MenuID_t cm, MenuEntry_t *entry, const vec2_t origin) #ifndef EDUKE32_ANDROID_MENU "\n(Y/N)" #endif - , g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, g_skillNames[ud.player_skill-1]); + , g_mapInfo[(ud.volume_number*MAXLEVELS) + ud.level_number].name, gSkillNames[ud.player_skill-1].GetChars()); mgametextcenter(origin.x, origin.y + (90<<16), tempbuf); } else diff --git a/source/rr/src/premap.cpp b/source/rr/src/premap.cpp index b7f4b9316..7b369be2b 100644 --- a/source/rr/src/premap.cpp +++ b/source/rr/src/premap.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "savegame.h" #include "cmdline.h" #include "statistics.h" +#include "menu/menu.h" BEGIN_RR_NS @@ -1900,7 +1901,7 @@ void G_NewGame(int volumeNum, int levelNum, int skillNum) ud.player_skill = skillNum; ud.secretlevel = 0; ud.from_bonus = 0; - STAT_StartNewGame(g_volumeNames[volumeNum], skillNum); + STAT_StartNewGame(gVolumeNames[volumeNum], skillNum); ud.last_level = -1; g_lastAutoSaveArbitraryID = -1; diff --git a/source/rr/src/screens.cpp b/source/rr/src/screens.cpp index 87bbf83ba..6bdcdad61 100644 --- a/source/rr/src/screens.cpp +++ b/source/rr/src/screens.cpp @@ -32,6 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "demo.h" #include "mdsprite.h" #include "gamecvars.h" +#include "menu/menu.h" BEGIN_RR_NS @@ -993,7 +994,7 @@ void G_DisplayRest(int32_t smoothratio) else { if (!G_HaveUserMap()) - minitext(5, a+6, g_volumeNames[ud.volume_number], 0, 2+8+16+256); + minitext(5, a+6, gVolumeNames[ud.volume_number], 0, 2+8+16+256); minitext(5, a+6+6, g_mapInfo[ud.volume_number*MAXLEVELS + ud.level_number].name, 0, 2+8+16+256); } } diff --git a/wadsrc/static/demolition/menudef.txt b/wadsrc/static/demolition/menudef.txt index 36b32ff4f..2be188358 100644 --- a/wadsrc/static/demolition/menudef.txt +++ b/wadsrc/static/demolition/menudef.txt @@ -134,15 +134,25 @@ LISTMENU "EpisodeMenu" { ScriptId 100 // Episode names filled in programmatically - NativeTextItem "1", "", "SkillMenu", 1 - NativeTextItem "2", "", "SkillMenu", 2 - NativeTextItem "3", "", "SkillMenu", 3 - NativeTextItem "4", "", "SkillMenu", 4 - NativeTextItem "5", "", "SkillMenu", 5 - NativeTextItem "6", "", "SkillMenu", 6 - NativeTextItem "7", "", "SkillMenu", 7 + NativeTextItem "", "", "SkillMenu", 1 + NativeStaticTextItem "" + NativeTextItem "", "", "SkillMenu", 2 + NativeStaticTextItem "" + NativeTextItem "", "", "SkillMenu", 3 + NativeStaticTextItem "" + NativeTextItem "", "", "SkillMenu", 4 + NativeStaticTextItem "" + NativeTextItem "", "", "SkillMenu", 5 + NativeStaticTextItem "" + NativeTextItem "", "", "SkillMenu", 6 + NativeStaticTextItem "" + NativeTextItem "", "", "SkillMenu", 7 //Spacer NativeTextItem "$MNU_USERMAP", "u", "UserMap" + ifgame(ShadowWarrior) + { + NativeStaticTextItem "$MNU_SELECTUSERMAP" + } } LISTMENU "SkillMenu"