2006-02-24 04:48:15 +00:00
|
|
|
// Emacs style mode select -*- C++ -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// $Id:$
|
|
|
|
//
|
|
|
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
|
|
|
//
|
|
|
|
// This source is available for distribution and/or modification
|
|
|
|
// only under the terms of the DOOM Source Code License as
|
|
|
|
// published by id Software. All rights reserved.
|
|
|
|
//
|
|
|
|
// The source is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
|
|
|
// for more details.
|
|
|
|
//
|
|
|
|
// $Log:$
|
|
|
|
//
|
|
|
|
// DESCRIPTION:
|
|
|
|
// DOOM selection menu, options, episode etc.
|
|
|
|
// Sliders and icons. Kinda widget stuff.
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <zlib.h>
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
#include <io.h>
|
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "doomdef.h"
|
|
|
|
#include "gstrings.h"
|
|
|
|
#include "c_console.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "d_main.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "i_video.h"
|
|
|
|
#include "v_video.h"
|
2008-09-15 14:11:05 +00:00
|
|
|
#include "v_palette.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
#include "w_wad.h"
|
|
|
|
#include "r_local.h"
|
|
|
|
#include "hu_stuff.h"
|
|
|
|
#include "g_game.h"
|
|
|
|
#include "m_argv.h"
|
|
|
|
#include "m_swap.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "m_menu.h"
|
|
|
|
#include "v_text.h"
|
|
|
|
#include "st_stuff.h"
|
|
|
|
#include "d_gui.h"
|
|
|
|
#include "version.h"
|
|
|
|
#include "m_png.h"
|
|
|
|
#include "templates.h"
|
|
|
|
#include "lists.h"
|
|
|
|
#include "gi.h"
|
2006-05-21 02:10:16 +00:00
|
|
|
#include "p_tick.h"
|
2007-01-06 12:30:34 +00:00
|
|
|
#include "st_start.h"
|
2007-12-20 20:22:31 +00:00
|
|
|
#include "teaminfo.h"
|
2007-12-26 16:06:03 +00:00
|
|
|
#include "r_translate.h"
|
2008-09-14 23:54:38 +00:00
|
|
|
#include "g_level.h"
|
|
|
|
#include "d_event.h"
|
|
|
|
#include "colormatcher.h"
|
2008-09-15 00:47:31 +00:00
|
|
|
#include "d_netinf.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// MACROS ------------------------------------------------------------------
|
|
|
|
|
|
|
|
#define SKULLXOFF -32
|
|
|
|
#define SELECTOR_XOFFSET (-28)
|
|
|
|
#define SELECTOR_YOFFSET (-1)
|
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
#define KEY_REPEAT_DELAY (TICRATE*5/12)
|
|
|
|
#define KEY_REPEAT_RATE (3)
|
|
|
|
|
2010-01-23 19:07:18 +00:00
|
|
|
#define INPUTGRID_WIDTH 13
|
|
|
|
#define INPUTGRID_HEIGHT 5
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// TYPES -------------------------------------------------------------------
|
|
|
|
|
|
|
|
struct FSaveGameNode : public Node
|
|
|
|
{
|
|
|
|
char Title[SAVESTRINGSIZE];
|
2006-05-03 22:45:01 +00:00
|
|
|
FString Filename;
|
2006-02-24 04:48:15 +00:00
|
|
|
bool bOldVersion;
|
|
|
|
bool bMissingWads;
|
|
|
|
};
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
struct FBackdropTexture : public FTexture
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FBackdropTexture();
|
|
|
|
|
|
|
|
const BYTE *GetColumn(unsigned int column, const Span **spans_out);
|
|
|
|
const BYTE *GetPixels();
|
|
|
|
void Unload();
|
|
|
|
bool CheckModified();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
BYTE Pixels[144*160];
|
|
|
|
static const Span DummySpan[2];
|
|
|
|
int LastRenderTic;
|
|
|
|
|
|
|
|
angle_t time1, time2, time3, time4;
|
|
|
|
angle_t t1ang, t2ang, z1ang, z2ang;
|
|
|
|
|
|
|
|
void Render();
|
|
|
|
};
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayerSkin *skin, FRemapTable *table);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
|
|
|
|
|
|
int M_StringHeight (const char *string);
|
|
|
|
void M_ClearMenus ();
|
|
|
|
|
|
|
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
|
|
|
|
|
|
static void M_NewGame (int choice);
|
|
|
|
static void M_Episode (int choice);
|
|
|
|
static void M_ChooseSkill (int choice);
|
|
|
|
static void M_LoadGame (int choice);
|
|
|
|
static void M_SaveGame (int choice);
|
|
|
|
static void M_Options (int choice);
|
|
|
|
static void M_EndGame (int choice);
|
|
|
|
static void M_ReadThis (int choice);
|
|
|
|
static void M_ReadThisMore (int choice);
|
2008-01-26 16:42:16 +00:00
|
|
|
static void M_QuitGame (int choice);
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_GameFiles (int choice);
|
|
|
|
static void M_ClearSaveStuff ();
|
|
|
|
|
|
|
|
static void SCClass (int choice);
|
2006-07-13 10:17:56 +00:00
|
|
|
static void M_ChooseClass (int choice);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static void M_FinishReadThis (int choice);
|
|
|
|
static void M_QuickSave ();
|
|
|
|
static void M_QuickLoad ();
|
|
|
|
static void M_LoadSelect (const FSaveGameNode *file);
|
|
|
|
static void M_SaveSelect (const FSaveGameNode *file);
|
|
|
|
static void M_ReadSaveStrings ();
|
2006-05-12 03:14:40 +00:00
|
|
|
static void M_UnloadSaveStrings ();
|
|
|
|
static FSaveGameNode *M_RemoveSaveSlot (FSaveGameNode *file);
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_ExtractSaveData (const FSaveGameNode *file);
|
|
|
|
static void M_UnloadSaveData ();
|
|
|
|
static void M_InsertSaveNode (FSaveGameNode *node);
|
2006-09-14 00:02:31 +00:00
|
|
|
static bool M_SaveLoadResponder (event_t *ev);
|
2009-07-26 03:25:18 +00:00
|
|
|
static void M_SaveLoadButtonHandler(EMenuKey key);
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_DeleteSaveResponse (int choice);
|
|
|
|
|
|
|
|
static void M_DrawMainMenu ();
|
|
|
|
static void M_DrawReadThis ();
|
|
|
|
static void M_DrawNewGame ();
|
|
|
|
static void M_DrawEpisode ();
|
|
|
|
static void M_DrawLoad ();
|
|
|
|
static void M_DrawSave ();
|
|
|
|
static void DrawClassMenu ();
|
|
|
|
static void DrawHexenSkillMenu ();
|
2006-07-13 10:17:56 +00:00
|
|
|
static void M_DrawClassMenu ();
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static void M_DrawHereticMainMenu ();
|
|
|
|
static void M_DrawFiles ();
|
|
|
|
|
|
|
|
void M_DrawFrame (int x, int y, int width, int height);
|
|
|
|
static void M_DrawSaveLoadBorder (int x,int y, int len);
|
|
|
|
static void M_DrawSaveLoadCommon ();
|
2010-01-23 19:07:18 +00:00
|
|
|
static void M_DrawInputGrid();
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_SetupNextMenu (oldmenu_t *menudef);
|
2009-08-07 03:30:51 +00:00
|
|
|
static void M_StartMessage (const char *string, void(*routine)(int));
|
|
|
|
static void M_EndMessage (int key);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// [RH] For player setup menu.
|
|
|
|
void M_PlayerSetup ();
|
|
|
|
static void M_PlayerSetupTicker ();
|
|
|
|
static void M_PlayerSetupDrawer ();
|
|
|
|
static void M_EditPlayerName (int choice);
|
|
|
|
static void M_ChangePlayerTeam (int choice);
|
|
|
|
static void M_PlayerNameChanged (FSaveGameNode *dummy);
|
2007-02-28 16:49:19 +00:00
|
|
|
static void M_PlayerNameNotChanged ();
|
2010-03-06 02:51:23 +00:00
|
|
|
static void M_ChangeColorSet (int choice);
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_SlidePlayerRed (int choice);
|
|
|
|
static void M_SlidePlayerGreen (int choice);
|
|
|
|
static void M_SlidePlayerBlue (int choice);
|
2006-07-13 10:17:56 +00:00
|
|
|
static void M_ChangeClass (int choice);
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_ChangeGender (int choice);
|
|
|
|
static void M_ChangeSkin (int choice);
|
|
|
|
static void M_ChangeAutoAim (int choice);
|
|
|
|
static void PickPlayerClass ();
|
|
|
|
|
|
|
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
|
|
|
|
|
|
|
EXTERN_CVAR (String, playerclass)
|
|
|
|
EXTERN_CVAR (String, name)
|
|
|
|
EXTERN_CVAR (Int, team)
|
|
|
|
|
|
|
|
extern bool sendpause;
|
|
|
|
extern int flagsvar;
|
|
|
|
|
|
|
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
|
|
|
|
|
|
EMenuState menuactive;
|
|
|
|
menustack_t MenuStack[16];
|
|
|
|
int MenuStackDepth;
|
|
|
|
int skullAnimCounter; // skull animation counter
|
|
|
|
bool drawSkull; // [RH] don't always draw skull
|
|
|
|
bool M_DemoNoPlay;
|
|
|
|
bool OptionsActive;
|
2009-07-26 03:25:18 +00:00
|
|
|
FButtonStatus MenuButtons[NUM_MKEYS];
|
|
|
|
int MenuButtonTickers[NUM_MKEYS];
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
|
|
|
|
|
|
|
static char tempstring[80];
|
|
|
|
static char underscore[2];
|
|
|
|
|
|
|
|
static FSaveGameNode *quickSaveSlot; // NULL = no quicksave slot picked!
|
2006-04-20 14:21:27 +00:00
|
|
|
static FSaveGameNode *lastSaveSlot; // Used for highlighting the most recently used slot in the menu
|
2006-02-24 04:48:15 +00:00
|
|
|
static int messageToPrint; // 1 = message to be printed
|
|
|
|
static const char *messageString; // ...and here is the message string!
|
|
|
|
static EMenuState messageLastMenuActive;
|
2009-08-07 03:30:51 +00:00
|
|
|
static void (*messageRoutine)(int response); // Non-NULL if only Y/N should close message
|
2006-02-24 04:48:15 +00:00
|
|
|
static int showSharewareMessage;
|
2009-08-07 03:30:51 +00:00
|
|
|
static int messageSelection; // 0 {Yes) or 1 (No) [if messageRoutine is non-NULL]
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static int genStringEnter; // we are going to be entering a savegame string
|
|
|
|
static size_t genStringLen; // [RH] Max # of chars that can be entered
|
|
|
|
static void (*genStringEnd)(FSaveGameNode *);
|
2007-02-28 16:49:19 +00:00
|
|
|
static void (*genStringCancel)();
|
2006-02-24 04:48:15 +00:00
|
|
|
static int saveSlot; // which slot to save in
|
|
|
|
static size_t saveCharIndex; // which char we're editing
|
|
|
|
|
|
|
|
static int LINEHEIGHT;
|
2010-01-05 02:56:27 +00:00
|
|
|
static const int PLAYERSETUP_LINEHEIGHT = 16;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static char savegamestring[SAVESTRINGSIZE];
|
2007-05-01 07:57:08 +00:00
|
|
|
static FString EndString;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static short itemOn; // menu item skull is on
|
|
|
|
static int MenuTime;
|
|
|
|
static int InfoType;
|
|
|
|
static int InfoTic;
|
|
|
|
|
|
|
|
static oldmenu_t *currentMenu; // current menudef
|
|
|
|
static oldmenu_t *TopLevelMenu; // The main menu everything hangs off of
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
static FBackdropTexture *FireTexture;
|
|
|
|
static FRemapTable FireRemap(256);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-12-29 03:38:37 +00:00
|
|
|
static const char *genders[3] = { "male", "female", "other" };
|
2006-07-13 10:17:56 +00:00
|
|
|
static FPlayerClass *PlayerClass;
|
|
|
|
static int PlayerSkin;
|
|
|
|
static FState *PlayerState;
|
|
|
|
static int PlayerTics;
|
|
|
|
static int PlayerRotation;
|
2010-03-06 02:51:23 +00:00
|
|
|
static TArray<int> PlayerColorSets;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2007-12-28 01:54:14 +00:00
|
|
|
static FTexture *SavePic;
|
2006-08-31 00:16:12 +00:00
|
|
|
static FBrokenLines *SaveComment;
|
2006-02-24 04:48:15 +00:00
|
|
|
static List SaveGames;
|
|
|
|
static FSaveGameNode *TopSaveGame;
|
|
|
|
static FSaveGameNode *SelSaveGame;
|
|
|
|
static FSaveGameNode NewSaveNode;
|
|
|
|
|
|
|
|
static int epi; // Selected episode
|
|
|
|
|
2008-12-27 20:18:31 +00:00
|
|
|
static const char *saved_playerclass = NULL;
|
|
|
|
|
2010-01-23 19:07:18 +00:00
|
|
|
// Heretic and Hexen do not, by default, come with glyphs for all of these
|
|
|
|
// characters. Oh well. Doom and Strife do.
|
|
|
|
static const char InputGridChars[INPUTGRID_WIDTH * INPUTGRID_HEIGHT] =
|
|
|
|
"ABCDEFGHIJKLM"
|
|
|
|
"NOPQRSTUVWXYZ"
|
|
|
|
"0123456789+-="
|
|
|
|
".,!?@'\":;[]()"
|
|
|
|
"<>^#$%&*/_ \b";
|
|
|
|
static int InputGridX = INPUTGRID_WIDTH - 1;
|
|
|
|
static int InputGridY = INPUTGRID_HEIGHT - 1;
|
|
|
|
static bool InputGridOkay; // Last input was with a controller.
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// PRIVATE MENU DEFINITIONS ------------------------------------------------
|
|
|
|
|
|
|
|
//
|
|
|
|
// DOOM MENU
|
|
|
|
//
|
|
|
|
static oldmenuitem_t MainMenu[]=
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
{1,0,'n',"M_NGAME",M_NewGame, CR_UNTRANSLATED},
|
|
|
|
{1,0,'l',"M_LOADG",M_LoadGame, CR_UNTRANSLATED},
|
|
|
|
{1,0,'s',"M_SAVEG",M_SaveGame, CR_UNTRANSLATED},
|
|
|
|
{1,0,'o',"M_OPTION",M_Options, CR_UNTRANSLATED}, // [RH] Moved
|
|
|
|
{1,0,'r',"M_RDTHIS",M_ReadThis, CR_UNTRANSLATED}, // Another hickup with Special edition.
|
2008-01-26 16:42:16 +00:00
|
|
|
{1,0,'q',"M_QUITG",M_QuitGame, CR_UNTRANSLATED}
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static oldmenu_t MainDef =
|
|
|
|
{
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
countof(MainMenu),
|
2006-02-24 04:48:15 +00:00
|
|
|
MainMenu,
|
|
|
|
M_DrawMainMenu,
|
|
|
|
97,64,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// HERETIC MENU
|
|
|
|
//
|
|
|
|
static oldmenuitem_t HereticMainMenu[] =
|
|
|
|
{
|
2008-02-18 22:40:39 +00:00
|
|
|
{1,1,'n',"$MNU_NEWGAME",M_NewGame, CR_UNTRANSLATED},
|
|
|
|
{1,1,'o',"$MNU_OPTIONS",M_Options, CR_UNTRANSLATED},
|
|
|
|
{1,1,'f',"$MNU_GAMEFILES",M_GameFiles, CR_UNTRANSLATED},
|
|
|
|
{1,1,'i',"$MNU_INFO",M_ReadThis, CR_UNTRANSLATED},
|
|
|
|
{1,1,'q',"$MNU_QUITGAME",M_QuitGame, CR_UNTRANSLATED}
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static oldmenu_t HereticMainDef =
|
|
|
|
{
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
countof(HereticMainMenu),
|
2006-02-24 04:48:15 +00:00
|
|
|
HereticMainMenu,
|
|
|
|
M_DrawHereticMainMenu,
|
|
|
|
110, 56,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// HEXEN "NEW GAME" MENU
|
|
|
|
//
|
2006-06-03 12:30:11 +00:00
|
|
|
static oldmenuitem_t ClassItems[] =
|
|
|
|
{
|
2008-02-18 22:40:39 +00:00
|
|
|
{ 1,1, 'f', "$MNU_FIGHTER", SCClass, CR_UNTRANSLATED },
|
|
|
|
{ 1,1, 'c', "$MNU_CLERIC", SCClass, CR_UNTRANSLATED },
|
|
|
|
{ 1,1, 'm', "$MNU_MAGE", SCClass, CR_UNTRANSLATED },
|
|
|
|
{ 1,1, 'r', "$MNU_RANDOM", SCClass, CR_UNTRANSLATED } // [RH]
|
2006-06-03 12:30:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static oldmenu_t ClassMenu =
|
|
|
|
{
|
|
|
|
4, ClassItems,
|
|
|
|
DrawClassMenu,
|
|
|
|
66, 58,
|
|
|
|
0
|
|
|
|
};
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
//
|
|
|
|
// [GRB] CLASS SELECT
|
|
|
|
//
|
|
|
|
oldmenuitem_t ClassMenuItems[8] =
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
|
|
|
{1,1,0, NULL, M_ChooseClass, CR_UNTRANSLATED },
|
2006-07-13 10:17:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
oldmenu_t ClassMenuDef =
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
ClassMenuItems,
|
|
|
|
M_DrawClassMenu,
|
|
|
|
48,63,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// EPISODE SELECT
|
|
|
|
//
|
|
|
|
oldmenuitem_t EpisodeMenu[MAX_EPISODES] =
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
|
|
|
{1,0,0, NULL, M_Episode, CR_UNTRANSLATED},
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
char EpisodeMaps[MAX_EPISODES][8];
|
2006-05-13 12:41:15 +00:00
|
|
|
bool EpisodeNoSkill[MAX_EPISODES];
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
oldmenu_t EpiDef =
|
|
|
|
{
|
|
|
|
0,
|
|
|
|
EpisodeMenu, // oldmenuitem_t ->
|
|
|
|
M_DrawEpisode, // drawing routine ->
|
|
|
|
48,63, // x,y
|
|
|
|
0 // lastOn
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// GAME FILES
|
|
|
|
//
|
|
|
|
static oldmenuitem_t FilesItems[] =
|
|
|
|
{
|
2008-02-18 22:40:39 +00:00
|
|
|
{1,1,'l',"$MNU_LOADGAME",M_LoadGame, CR_UNTRANSLATED},
|
|
|
|
{1,1,'s',"$MNU_SAVEGAME",M_SaveGame, CR_UNTRANSLATED}
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static oldmenu_t FilesMenu =
|
|
|
|
{
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
countof(FilesItems),
|
2006-02-24 04:48:15 +00:00
|
|
|
FilesItems,
|
|
|
|
M_DrawFiles,
|
|
|
|
110,60,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// DOOM SKILL SELECT
|
|
|
|
//
|
2007-11-02 22:03:03 +00:00
|
|
|
static oldmenuitem_t SkillSelectMenu[]={
|
2007-11-03 11:41:42 +00:00
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
|
|
|
{ 1, 0, 0, "", M_ChooseSkill, CR_UNTRANSLATED},
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
2007-11-02 22:03:03 +00:00
|
|
|
static oldmenu_t SkillDef =
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-11-02 22:03:03 +00:00
|
|
|
0,
|
2009-07-23 04:33:07 +00:00
|
|
|
SkillSelectMenu, // oldmenuitem_t ->
|
2006-02-24 04:48:15 +00:00
|
|
|
M_DrawNewGame, // drawing routine ->
|
|
|
|
48,63, // x,y
|
2009-07-23 04:33:07 +00:00
|
|
|
-1 // lastOn
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
2006-06-03 12:30:11 +00:00
|
|
|
static oldmenu_t HexenSkillMenu =
|
|
|
|
{
|
2007-11-02 22:03:03 +00:00
|
|
|
0,
|
2009-07-23 04:33:07 +00:00
|
|
|
SkillSelectMenu,
|
2006-06-03 12:30:11 +00:00
|
|
|
DrawHexenSkillMenu,
|
|
|
|
120, 44,
|
2009-07-23 04:33:07 +00:00
|
|
|
-1
|
2006-06-03 12:30:11 +00:00
|
|
|
};
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2007-11-02 22:03:03 +00:00
|
|
|
void M_StartupSkillMenu(const char *playerclass)
|
|
|
|
{
|
|
|
|
if (gameinfo.gametype & GAME_Raven)
|
|
|
|
{
|
|
|
|
SkillDef.x = 38;
|
|
|
|
SkillDef.y = 30;
|
2007-11-03 11:41:42 +00:00
|
|
|
|
|
|
|
if (gameinfo.gametype == GAME_Hexen)
|
|
|
|
{
|
|
|
|
HexenSkillMenu.x = 38;
|
|
|
|
if (playerclass != NULL)
|
|
|
|
{
|
|
|
|
if (!stricmp(playerclass, "fighter")) HexenSkillMenu.x = 120;
|
|
|
|
else if (!stricmp(playerclass, "cleric")) HexenSkillMenu.x = 116;
|
|
|
|
else if (!stricmp(playerclass, "mage")) HexenSkillMenu.x = 112;
|
|
|
|
}
|
|
|
|
}
|
2007-11-02 22:03:03 +00:00
|
|
|
}
|
|
|
|
SkillDef.numitems = HexenSkillMenu.numitems = 0;
|
2009-07-23 04:33:07 +00:00
|
|
|
for(unsigned int i = 0; i < AllSkills.Size() && i < 8; i++)
|
2007-11-02 22:03:03 +00:00
|
|
|
{
|
|
|
|
FSkillInfo &skill = AllSkills[i];
|
|
|
|
|
2010-04-20 11:03:31 +00:00
|
|
|
if (skill.PicName.Len() != 0)
|
|
|
|
{
|
|
|
|
SkillSelectMenu[i].name = skill.PicName;
|
|
|
|
SkillSelectMenu[i].fulltext = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SkillSelectMenu[i].name = skill.MenuName;
|
|
|
|
SkillSelectMenu[i].fulltext = true;
|
|
|
|
}
|
2007-12-08 22:57:55 +00:00
|
|
|
SkillSelectMenu[i].textcolor = skill.GetTextColor();
|
|
|
|
SkillSelectMenu[i].alphaKey = skill.Shortcut;
|
2007-11-02 22:03:03 +00:00
|
|
|
|
|
|
|
if (playerclass != NULL)
|
|
|
|
{
|
|
|
|
FString * pmnm = skill.MenuNamesForPlayerClass.CheckKey(playerclass);
|
|
|
|
if (pmnm != NULL)
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
SkillSelectMenu[i].name = GStrings(*pmnm);
|
2007-11-02 22:03:03 +00:00
|
|
|
SkillSelectMenu[i].fulltext = true;
|
2007-12-08 22:57:55 +00:00
|
|
|
if (skill.Shortcut == 0)
|
2007-11-03 11:41:42 +00:00
|
|
|
SkillSelectMenu[i].alphaKey = tolower(SkillSelectMenu[i].name[0]);
|
2007-11-02 22:03:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
SkillDef.numitems++;
|
|
|
|
HexenSkillMenu.numitems++;
|
|
|
|
}
|
2009-07-23 04:33:07 +00:00
|
|
|
int defskill = DefaultSkill;
|
|
|
|
if ((unsigned int)defskill >= AllSkills.Size())
|
|
|
|
{
|
|
|
|
defskill = (AllSkills.Size() - 1) / 2;
|
|
|
|
}
|
|
|
|
// The default skill is only set the first time the menu is opened.
|
|
|
|
// After that, it opens on whichever skill you last selected.
|
|
|
|
if (SkillDef.lastOn < 0)
|
|
|
|
{
|
|
|
|
SkillDef.lastOn = defskill;
|
|
|
|
}
|
|
|
|
if (HexenSkillMenu.lastOn < 0)
|
|
|
|
{
|
|
|
|
HexenSkillMenu.lastOn = defskill;
|
|
|
|
}
|
2007-11-02 22:03:03 +00:00
|
|
|
// Hexen needs some manual coordinate adjustments based on player class
|
|
|
|
if (gameinfo.gametype == GAME_Hexen)
|
|
|
|
{
|
|
|
|
M_SetupNextMenu(&HexenSkillMenu);
|
|
|
|
}
|
|
|
|
else
|
2009-07-23 04:33:07 +00:00
|
|
|
{
|
2007-11-02 22:03:03 +00:00
|
|
|
M_SetupNextMenu(&SkillDef);
|
2009-07-23 04:33:07 +00:00
|
|
|
}
|
2007-11-02 22:03:03 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// [RH] Player Setup Menu
|
|
|
|
//
|
|
|
|
static oldmenuitem_t PlayerSetupMenu[] =
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
{ 1,0,'n',NULL,M_EditPlayerName, CR_UNTRANSLATED},
|
|
|
|
{ 2,0,'t',NULL,M_ChangePlayerTeam, CR_UNTRANSLATED},
|
2010-03-06 02:51:23 +00:00
|
|
|
{ 2,0,'c',NULL,M_ChangeColorSet, CR_UNTRANSLATED},
|
2007-11-03 11:41:42 +00:00
|
|
|
{ 2,0,'r',NULL,M_SlidePlayerRed, CR_UNTRANSLATED},
|
|
|
|
{ 2,0,'g',NULL,M_SlidePlayerGreen, CR_UNTRANSLATED},
|
|
|
|
{ 2,0,'b',NULL,M_SlidePlayerBlue, CR_UNTRANSLATED},
|
2010-03-06 02:51:23 +00:00
|
|
|
{ 2,0,'t',NULL,M_ChangeClass, CR_UNTRANSLATED},
|
2007-11-03 11:41:42 +00:00
|
|
|
{ 2,0,'s',NULL,M_ChangeSkin, CR_UNTRANSLATED},
|
|
|
|
{ 2,0,'e',NULL,M_ChangeGender, CR_UNTRANSLATED},
|
|
|
|
{ 2,0,'a',NULL,M_ChangeAutoAim, CR_UNTRANSLATED}
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
2010-03-07 11:05:52 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
// These must be changed if the menu definition is altered
|
|
|
|
PSM_RED = 3,
|
|
|
|
PSM_GREEN = 4,
|
|
|
|
PSM_BLUE = 5,
|
|
|
|
};
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
static oldmenu_t PSetupDef =
|
|
|
|
{
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
countof(PlayerSetupMenu),
|
2006-02-24 04:48:15 +00:00
|
|
|
PlayerSetupMenu,
|
|
|
|
M_PlayerSetupDrawer,
|
|
|
|
48, 47,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read This! MENU 1 & 2
|
|
|
|
//
|
|
|
|
static oldmenuitem_t ReadMenu[] =
|
|
|
|
{
|
|
|
|
{1,0,0,NULL,M_ReadThisMore}
|
|
|
|
};
|
|
|
|
|
|
|
|
static oldmenu_t ReadDef =
|
|
|
|
{
|
|
|
|
1,
|
|
|
|
ReadMenu,
|
|
|
|
M_DrawReadThis,
|
|
|
|
280,185,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// LOAD GAME MENU
|
|
|
|
//
|
|
|
|
static oldmenuitem_t LoadMenu[]=
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
{1,0,'1',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'2',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'3',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'4',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'5',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'6',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'7',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'8',NULL, NULL, CR_UNTRANSLATED},
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static oldmenu_t LoadDef =
|
|
|
|
{
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
countof(LoadMenu),
|
2006-02-24 04:48:15 +00:00
|
|
|
LoadMenu,
|
|
|
|
M_DrawLoad,
|
|
|
|
80,54,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
//
|
|
|
|
// SAVE GAME MENU
|
|
|
|
//
|
|
|
|
static oldmenuitem_t SaveMenu[] =
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
{1,0,'1',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'2',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'3',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'4',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'5',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'6',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'7',NULL, NULL, CR_UNTRANSLATED},
|
|
|
|
{1,0,'8',NULL, NULL, CR_UNTRANSLATED},
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static oldmenu_t SaveDef =
|
|
|
|
{
|
- Fixed compilation with mingw again.
- Added multiple-choice sound sequences. These overcome one of the major
deficiences of the Hexen-inherited SNDSEQ system while still being Hexen
compatible: Custom door sounds can now use different opening and closing
sequences, for both normal and blazing speeds.
- Added a serializer for TArray.
- Added a countof macro to doomtype.h. See the1's blog to find out why
it's implemented the way it is.
<http://blogs.msdn.com/the1/articles/210011.aspx>
- Added a new method to FRandom for getting random numbers larger than 255,
which lets me:
- Fixed: SNDSEQ delayrand commands could delay for no more than 255 tics.
- Fixed: If you're going to have sector_t.SoundTarget, then they need to
be included in the pointer cleanup scans.
- Ported back newer name code from 2.1.
- Fixed: Using -warp with only one parameter in Doom and Heretic to
select a map on episode 1 no longer worked.
- New: Loading a multiplayer save now restores the players based on
their names rather than on their connection order. Using connection
order was sensible when -net was the only way to start a network game,
but with -host/-join, it's not so nice. Also, if there aren't enough
players in the save, then the extra players will be spawned normally,
so you can continue a saved game with more players than you started it
with.
- Added some new SNDSEQ commands to make it possible to define Heretic's
ambient sounds in SNDSEQ: volumerel, volumerand, slot, randomsequence,
delayonce, and restart. With these, it is basically possible to obsolete
all of the $ambient SNDINFO commands.
- Fixed: Sound sequences would only execute one command each time they were
ticked.
- Fixed: No bounds checking was done on the volume sound sequences played at.
- Fixed: The tic parameter to playloop was useless and caused it to
act like a redundant playrepeat. I have removed all the logic that
caused playloop to play repeating sounds, and now it acts like an
infinite sequence of play/delay commands until the sequence is
stopped.
- Fixed: Sound sequences were ticked every frame, not every tic, so all
the delay commands were timed incorrectly and varied depending on your
framerate. Since this is useful for restarting looping sounds that got
cut off, I have not changed this. Instead, the delay commands now
record the tic when execution should resume, not the number of tics
left to delay.
SVN r57 (trunk)
2006-04-21 01:22:55 +00:00
|
|
|
countof(LoadMenu),
|
2006-02-24 04:48:15 +00:00
|
|
|
SaveMenu,
|
|
|
|
M_DrawSave,
|
|
|
|
80,54,
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
|
|
|
// CODE --------------------------------------------------------------------
|
|
|
|
|
|
|
|
// [RH] Most menus can now be accessed directly
|
|
|
|
// through console commands.
|
|
|
|
CCMD (menu_main)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartControlPanel (true, true);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_load)
|
|
|
|
{ // F3
|
|
|
|
M_StartControlPanel (true);
|
|
|
|
M_LoadGame (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_save)
|
|
|
|
{ // F2
|
|
|
|
M_StartControlPanel (true);
|
|
|
|
M_SaveGame (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_help)
|
|
|
|
{ // F1
|
|
|
|
M_StartControlPanel (true);
|
|
|
|
M_ReadThis (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (quicksave)
|
|
|
|
{ // F6
|
|
|
|
//M_StartControlPanel (true);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
M_QuickSave();
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (quickload)
|
|
|
|
{ // F9
|
|
|
|
//M_StartControlPanel (true);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
M_QuickLoad();
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_endgame)
|
|
|
|
{ // F7
|
|
|
|
//M_StartControlPanel (true);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
M_EndGame(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_quit)
|
|
|
|
{ // F10
|
|
|
|
//M_StartControlPanel (true);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", 1, ATTN_NONE);
|
2008-01-26 16:42:16 +00:00
|
|
|
M_QuitGame(0);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_game)
|
|
|
|
{
|
|
|
|
M_StartControlPanel (true);
|
|
|
|
M_NewGame(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_options)
|
|
|
|
{
|
|
|
|
M_StartControlPanel (true);
|
|
|
|
M_Options(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (menu_player)
|
|
|
|
{
|
|
|
|
M_StartControlPanel (true);
|
|
|
|
M_PlayerSetup ();
|
|
|
|
}
|
|
|
|
|
|
|
|
CCMD (bumpgamma)
|
|
|
|
{
|
|
|
|
// [RH] Gamma correction tables are now generated
|
|
|
|
// on the fly for *any* gamma level.
|
|
|
|
// Q: What are reasonable limits to use here?
|
|
|
|
|
2008-09-14 23:54:38 +00:00
|
|
|
float newgamma = Gamma + 0.1f;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (newgamma > 3.0)
|
|
|
|
newgamma = 1.0;
|
|
|
|
|
|
|
|
Gamma = newgamma;
|
|
|
|
Printf ("Gamma correction level %g\n", *Gamma);
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_ActivateMenuInput ()
|
|
|
|
{
|
|
|
|
ResetButtonStates ();
|
|
|
|
menuactive = MENU_On;
|
2006-05-21 02:10:16 +00:00
|
|
|
// Pause sound effects before we play the menu switch sound.
|
|
|
|
// That way, it won't be paused.
|
|
|
|
P_CheckTickerPaused ();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void M_DeactivateMenuInput ()
|
|
|
|
{
|
|
|
|
menuactive = MENU_Off;
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_DrawFiles ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_GameFiles (int choice)
|
|
|
|
{
|
|
|
|
M_SetupNextMenu (&FilesMenu);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_ReadSaveStrings
|
|
|
|
//
|
|
|
|
// Find savegames and read their titles
|
|
|
|
//
|
2006-05-12 03:14:40 +00:00
|
|
|
static void M_ReadSaveStrings ()
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
if (SaveGames.IsEmpty ())
|
|
|
|
{
|
|
|
|
void *filefirst;
|
|
|
|
findstate_t c_file;
|
2006-05-03 22:45:01 +00:00
|
|
|
FString filter;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-05-12 03:14:40 +00:00
|
|
|
atterm (M_UnloadSaveStrings);
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
filter = G_BuildSaveName ("*.zds", -1);
|
|
|
|
filefirst = I_FindFirst (filter.GetChars(), &c_file);
|
|
|
|
if (filefirst != ((void *)(-1)))
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
// I_FindName only returns the file's name and not its full path
|
2006-05-03 22:45:01 +00:00
|
|
|
FString filepath = G_BuildSaveName (I_FindName(&c_file), -1);
|
|
|
|
FILE *file = fopen (filepath, "rb");
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (file != NULL)
|
|
|
|
{
|
|
|
|
PNGHandle *png;
|
|
|
|
char sig[16];
|
|
|
|
char title[SAVESTRINGSIZE+1];
|
|
|
|
bool oldVer = true;
|
|
|
|
bool addIt = false;
|
|
|
|
bool missing = false;
|
|
|
|
|
|
|
|
// ZDoom 1.23 betas 21-33 have the savesig first.
|
|
|
|
// Earlier versions have the savesig second.
|
|
|
|
// Later versions have the savegame encapsulated inside a PNG.
|
|
|
|
//
|
|
|
|
// Old savegame versions are always added to the menu so
|
|
|
|
// the user can easily delete them if desired.
|
|
|
|
|
|
|
|
title[SAVESTRINGSIZE] = 0;
|
|
|
|
|
|
|
|
if (NULL != (png = M_VerifyPNG (file)))
|
|
|
|
{
|
|
|
|
char *ver = M_GetPNGText (png, "ZDoom Save Version");
|
2006-04-11 16:27:41 +00:00
|
|
|
char *engine = M_GetPNGText (png, "Engine");
|
2006-02-24 04:48:15 +00:00
|
|
|
if (ver != NULL)
|
|
|
|
{
|
|
|
|
if (!M_GetPNGText (png, "Title", title, SAVESTRINGSIZE))
|
|
|
|
{
|
|
|
|
strncpy (title, I_FindName(&c_file), SAVESTRINGSIZE);
|
|
|
|
}
|
|
|
|
if (strncmp (ver, SAVESIG, 9) == 0 &&
|
2006-04-11 16:27:41 +00:00
|
|
|
atoi (ver+9) >= MINSAVEVER &&
|
|
|
|
engine != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
// Was saved with a compatible ZDoom version,
|
|
|
|
// so check if it's for the current game.
|
|
|
|
// If it is, add it. Otherwise, ignore it.
|
|
|
|
char *iwad = M_GetPNGText (png, "Game WAD");
|
|
|
|
if (iwad != NULL)
|
|
|
|
{
|
|
|
|
if (stricmp (iwad, Wads.GetWadName (FWadCollection::IWAD_FILENUM)) == 0)
|
|
|
|
{
|
|
|
|
addIt = true;
|
|
|
|
oldVer = false;
|
|
|
|
missing = !G_CheckSaveGameWads (png, false);
|
|
|
|
}
|
|
|
|
delete[] iwad;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // An old version
|
|
|
|
addIt = true;
|
|
|
|
}
|
|
|
|
delete[] ver;
|
|
|
|
}
|
2006-05-12 03:14:40 +00:00
|
|
|
if (engine != NULL)
|
|
|
|
{
|
|
|
|
delete[] engine;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
delete png;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fseek (file, 0, SEEK_SET);
|
|
|
|
if (fread (sig, 1, 16, file) == 16)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (strncmp (sig, "ZDOOMSAVE", 9) == 0)
|
|
|
|
{
|
|
|
|
if (fread (title, 1, SAVESTRINGSIZE, file) == SAVESTRINGSIZE)
|
|
|
|
{
|
|
|
|
addIt = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy (title, sig, 16);
|
|
|
|
if (fread (title + 16, 1, SAVESTRINGSIZE-16, file) == SAVESTRINGSIZE-16 &&
|
|
|
|
fread (sig, 1, 16, file) == 16 &&
|
|
|
|
strncmp (sig, "ZDOOMSAVE", 9) == 0)
|
|
|
|
{
|
|
|
|
addIt = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addIt)
|
|
|
|
{
|
|
|
|
FSaveGameNode *node = new FSaveGameNode;
|
|
|
|
node->Filename = filepath;
|
|
|
|
node->bOldVersion = oldVer;
|
|
|
|
node->bMissingWads = missing;
|
|
|
|
memcpy (node->Title, title, SAVESTRINGSIZE);
|
|
|
|
M_InsertSaveNode (node);
|
|
|
|
}
|
|
|
|
fclose (file);
|
|
|
|
}
|
|
|
|
} while (I_FindNext (filefirst, &c_file) == 0);
|
|
|
|
I_FindClose (filefirst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (SelSaveGame == NULL || SelSaveGame->Succ == NULL)
|
|
|
|
{
|
|
|
|
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-12 03:14:40 +00:00
|
|
|
static void M_UnloadSaveStrings()
|
|
|
|
{
|
|
|
|
M_UnloadSaveData();
|
|
|
|
while (!SaveGames.IsEmpty())
|
|
|
|
{
|
|
|
|
M_RemoveSaveSlot (static_cast<FSaveGameNode *>(SaveGames.Head));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static FSaveGameNode *M_RemoveSaveSlot (FSaveGameNode *file)
|
|
|
|
{
|
|
|
|
FSaveGameNode *next = static_cast<FSaveGameNode *>(file->Succ);
|
|
|
|
|
|
|
|
if (file == TopSaveGame)
|
|
|
|
{
|
|
|
|
TopSaveGame = next;
|
|
|
|
}
|
|
|
|
if (quickSaveSlot == file)
|
|
|
|
{
|
|
|
|
quickSaveSlot = NULL;
|
|
|
|
}
|
|
|
|
if (lastSaveSlot == file)
|
|
|
|
{
|
|
|
|
lastSaveSlot = NULL;
|
|
|
|
}
|
|
|
|
file->Remove ();
|
|
|
|
delete file;
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void M_InsertSaveNode (FSaveGameNode *node)
|
|
|
|
{
|
|
|
|
FSaveGameNode *probe;
|
|
|
|
|
|
|
|
if (SaveGames.IsEmpty ())
|
|
|
|
{
|
|
|
|
SaveGames.AddHead (node);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node->bOldVersion)
|
|
|
|
{ // Add node at bottom of list
|
|
|
|
probe = static_cast<FSaveGameNode *>(SaveGames.TailPred);
|
|
|
|
while (probe->Pred != NULL && probe->bOldVersion &&
|
|
|
|
stricmp (node->Title, probe->Title) < 0)
|
|
|
|
{
|
|
|
|
probe = static_cast<FSaveGameNode *>(probe->Pred);
|
|
|
|
}
|
|
|
|
node->Insert (probe);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Add node at top of list
|
|
|
|
probe = static_cast<FSaveGameNode *>(SaveGames.Head);
|
|
|
|
while (probe->Succ != NULL && !probe->bOldVersion &&
|
|
|
|
stricmp (node->Title, probe->Title) > 0)
|
|
|
|
{
|
|
|
|
probe = static_cast<FSaveGameNode *>(probe->Succ);
|
|
|
|
}
|
|
|
|
node->InsertBefore (probe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_NotifyNewSave (const char *file, const char *title, bool okForQuicksave)
|
|
|
|
{
|
|
|
|
FSaveGameNode *node;
|
|
|
|
|
|
|
|
if (file == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
M_ReadSaveStrings ();
|
|
|
|
|
|
|
|
// See if the file is already in our list
|
|
|
|
for (node = static_cast<FSaveGameNode *>(SaveGames.Head);
|
|
|
|
node->Succ != NULL;
|
|
|
|
node = static_cast<FSaveGameNode *>(node->Succ))
|
|
|
|
{
|
|
|
|
#ifdef unix
|
|
|
|
if (node->Filename.Compare (file) == 0)
|
|
|
|
#else
|
|
|
|
if (node->Filename.CompareNoCase (file) == 0)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
strcpy (node->Title, title);
|
|
|
|
node->bOldVersion = false;
|
|
|
|
node->bMissingWads = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node->Succ == NULL)
|
|
|
|
{
|
|
|
|
node = new FSaveGameNode;
|
|
|
|
strcpy (node->Title, title);
|
2006-05-18 04:25:26 +00:00
|
|
|
node->Filename = file;
|
2006-02-24 04:48:15 +00:00
|
|
|
node->bOldVersion = false;
|
|
|
|
node->bMissingWads = false;
|
|
|
|
M_InsertSaveNode (node);
|
|
|
|
SelSaveGame = node;
|
|
|
|
}
|
|
|
|
|
2006-04-20 14:21:27 +00:00
|
|
|
if (okForQuicksave)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-04-20 14:21:27 +00:00
|
|
|
if (quickSaveSlot == NULL) quickSaveSlot = node;
|
|
|
|
lastSaveSlot = node;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_LoadGame & Cie.
|
|
|
|
//
|
|
|
|
void M_DrawLoad (void)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
FTexture *title = TexMan["M_LOADG"];
|
|
|
|
screen->DrawTexture (title,
|
2008-05-20 04:02:49 +00:00
|
|
|
(SCREENWIDTH - title->GetScaledWidth()*CleanXfac)/2, 20*CleanYfac,
|
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-05-01 07:57:08 +00:00
|
|
|
const char *loadgame = GStrings("MNU_LOADGAME");
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (BigFont, CR_UNTRANSLATED,
|
2007-05-01 07:57:08 +00:00
|
|
|
(SCREENWIDTH - BigFont->StringWidth (loadgame)*CleanXfac)/2, 10*CleanYfac,
|
|
|
|
loadgame, DTA_CleanNoMove, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
M_DrawSaveLoadCommon ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Draw border for the savegame description
|
|
|
|
// [RH] Width of the border is variable
|
|
|
|
//
|
|
|
|
void M_DrawSaveLoadBorder (int x, int y, int len)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
screen->DrawTexture (TexMan["M_LSLEFT"], x-8, y+7, DTA_Clean, true, TAG_DONE);
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
screen->DrawTexture (TexMan["M_LSCNTR"], x, y+7, DTA_Clean, true, TAG_DONE);
|
|
|
|
x += 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
screen->DrawTexture (TexMan["M_LSRGHT"], x, y+7, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
screen->DrawTexture (TexMan["M_FSLOT"], x, y+1, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_ExtractSaveData (const FSaveGameNode *node)
|
|
|
|
{
|
|
|
|
FILE *file;
|
|
|
|
PNGHandle *png;
|
|
|
|
|
|
|
|
M_UnloadSaveData ();
|
|
|
|
|
|
|
|
if (node != NULL &&
|
|
|
|
node->Succ != NULL &&
|
|
|
|
!node->Filename.IsEmpty() &&
|
|
|
|
!node->bOldVersion &&
|
|
|
|
(file = fopen (node->Filename.GetChars(), "rb")) != NULL)
|
|
|
|
{
|
|
|
|
if (NULL != (png = M_VerifyPNG (file)))
|
|
|
|
{
|
|
|
|
char *time, *pcomment, *comment;
|
|
|
|
size_t commentlen, totallen, timelen;
|
|
|
|
|
|
|
|
// Extract comment
|
|
|
|
time = M_GetPNGText (png, "Creation Time");
|
|
|
|
pcomment = M_GetPNGText (png, "Comment");
|
|
|
|
if (pcomment != NULL)
|
|
|
|
{
|
|
|
|
commentlen = strlen (pcomment);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
commentlen = 0;
|
|
|
|
}
|
|
|
|
if (time != NULL)
|
|
|
|
{
|
|
|
|
timelen = strlen (time);
|
|
|
|
totallen = timelen + commentlen + 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
timelen = 0;
|
|
|
|
totallen = commentlen + 1;
|
|
|
|
}
|
|
|
|
if (totallen != 0)
|
|
|
|
{
|
|
|
|
comment = new char[totallen];
|
|
|
|
|
|
|
|
if (timelen)
|
|
|
|
{
|
|
|
|
memcpy (comment, time, timelen);
|
|
|
|
comment[timelen] = '\n';
|
|
|
|
comment[timelen+1] = '\n';
|
|
|
|
timelen += 2;
|
|
|
|
}
|
|
|
|
if (commentlen)
|
|
|
|
{
|
|
|
|
memcpy (comment + timelen, pcomment, commentlen);
|
|
|
|
}
|
|
|
|
comment[timelen+commentlen] = 0;
|
2008-11-27 17:43:36 +00:00
|
|
|
SaveComment = V_BreakLines (SmallFont, 216*screen->GetWidth()/640/CleanXfac, comment);
|
2006-02-24 04:48:15 +00:00
|
|
|
delete[] comment;
|
|
|
|
delete[] time;
|
|
|
|
delete[] pcomment;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract pic
|
2008-06-01 20:43:02 +00:00
|
|
|
SavePic = PNGTexture_CreateFromFile(png, node->Filename);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
delete png;
|
|
|
|
}
|
|
|
|
fclose (file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_UnloadSaveData ()
|
|
|
|
{
|
|
|
|
if (SavePic != NULL)
|
|
|
|
{
|
|
|
|
delete SavePic;
|
|
|
|
}
|
|
|
|
if (SaveComment != NULL)
|
|
|
|
{
|
|
|
|
V_FreeBrokenLines (SaveComment);
|
|
|
|
}
|
|
|
|
|
|
|
|
SavePic = NULL;
|
|
|
|
SaveComment = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_DrawSaveLoadCommon ()
|
|
|
|
{
|
|
|
|
const int savepicLeft = 10;
|
|
|
|
const int savepicTop = 54*CleanYfac;
|
|
|
|
const int savepicWidth = 216*screen->GetWidth()/640;
|
|
|
|
const int savepicHeight = 135*screen->GetHeight()/400;
|
|
|
|
|
|
|
|
const int rowHeight = (SmallFont->GetHeight() + 1) * CleanYfac;
|
|
|
|
const int listboxLeft = savepicLeft + savepicWidth + 14;
|
|
|
|
const int listboxTop = savepicTop;
|
|
|
|
const int listboxWidth = screen->GetWidth() - listboxLeft - 10;
|
|
|
|
const int listboxHeight1 = screen->GetHeight() - listboxTop - 10;
|
|
|
|
const int listboxRows = (listboxHeight1 - 1) / rowHeight;
|
|
|
|
const int listboxHeight = listboxRows * rowHeight + 1;
|
|
|
|
const int listboxRight = listboxLeft + listboxWidth;
|
|
|
|
const int listboxBottom = listboxTop + listboxHeight;
|
|
|
|
|
|
|
|
const int commentLeft = savepicLeft;
|
|
|
|
const int commentTop = savepicTop + savepicHeight + 16;
|
|
|
|
const int commentWidth = savepicWidth;
|
|
|
|
const int commentHeight = (51+(screen->GetHeight()>200?10:0))*CleanYfac;
|
|
|
|
const int commentRight = commentLeft + commentWidth;
|
|
|
|
const int commentBottom = commentTop + commentHeight;
|
|
|
|
|
|
|
|
FSaveGameNode *node;
|
|
|
|
int i;
|
|
|
|
bool didSeeSelected = false;
|
|
|
|
|
|
|
|
// Draw picture area
|
|
|
|
if (gameaction == ga_loadgame || gameaction == ga_savegame)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
M_DrawFrame (savepicLeft, savepicTop, savepicWidth, savepicHeight);
|
|
|
|
if (SavePic != NULL)
|
|
|
|
{
|
2007-12-28 01:54:14 +00:00
|
|
|
screen->DrawTexture(SavePic, savepicLeft, savepicTop,
|
|
|
|
DTA_DestWidth, savepicWidth,
|
|
|
|
DTA_DestHeight, savepicHeight,
|
|
|
|
DTA_Masked, false,
|
|
|
|
TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
screen->Clear (savepicLeft, savepicTop,
|
2007-12-22 04:52:51 +00:00
|
|
|
savepicLeft+savepicWidth, savepicTop+savepicHeight, 0, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (!SaveGames.IsEmpty ())
|
|
|
|
{
|
|
|
|
const char *text =
|
|
|
|
(SelSaveGame == NULL || !SelSaveGame->bOldVersion)
|
2007-05-01 07:57:08 +00:00
|
|
|
? GStrings("MNU_NOPICTURE") : GStrings("MNU_DIFFVERSION");
|
2006-02-24 04:48:15 +00:00
|
|
|
const int textlen = SmallFont->StringWidth (text)*CleanXfac;
|
|
|
|
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_GOLD, savepicLeft+(savepicWidth-textlen)/2,
|
2006-02-24 04:48:15 +00:00
|
|
|
savepicTop+(savepicHeight-rowHeight)/2, text,
|
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw comment area
|
|
|
|
M_DrawFrame (commentLeft, commentTop, commentWidth, commentHeight);
|
2007-12-22 04:52:51 +00:00
|
|
|
screen->Clear (commentLeft, commentTop, commentRight, commentBottom, 0, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (SaveComment != NULL)
|
|
|
|
{
|
|
|
|
// I'm not sure why SaveComment would go NULL in this loop, but I got
|
|
|
|
// a crash report where it was NULL when i reached 1, so now I check
|
|
|
|
// for that.
|
2006-08-31 00:16:12 +00:00
|
|
|
for (i = 0; SaveComment != NULL && SaveComment[i].Width >= 0 && i < 6; ++i)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_GOLD, commentLeft, commentTop
|
2006-08-31 00:16:12 +00:00
|
|
|
+ SmallFont->GetHeight()*i*CleanYfac, SaveComment[i].Text,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw file area
|
|
|
|
do
|
|
|
|
{
|
|
|
|
M_DrawFrame (listboxLeft, listboxTop, listboxWidth, listboxHeight);
|
2007-12-22 04:52:51 +00:00
|
|
|
screen->Clear (listboxLeft, listboxTop, listboxRight, listboxBottom, 0, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (SaveGames.IsEmpty ())
|
|
|
|
{
|
2007-05-01 07:57:08 +00:00
|
|
|
const char * text = GStrings("MNU_NOFILES");
|
|
|
|
const int textlen = SmallFont->StringWidth (text)*CleanXfac;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_GOLD, listboxLeft+(listboxWidth-textlen)/2,
|
2007-05-01 07:57:08 +00:00
|
|
|
listboxTop+(listboxHeight-rowHeight)/2, text,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0, node = TopSaveGame;
|
|
|
|
i < listboxRows && node->Succ != NULL;
|
|
|
|
++i, node = static_cast<FSaveGameNode *>(node->Succ))
|
|
|
|
{
|
|
|
|
int color;
|
|
|
|
if (node->bOldVersion)
|
|
|
|
{
|
|
|
|
color = CR_BLUE;
|
|
|
|
}
|
|
|
|
else if (node->bMissingWads)
|
|
|
|
{
|
|
|
|
color = CR_ORANGE;
|
|
|
|
}
|
|
|
|
else if (node == SelSaveGame)
|
|
|
|
{
|
|
|
|
color = CR_WHITE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
color = CR_TAN;
|
|
|
|
}
|
|
|
|
if (node == SelSaveGame)
|
|
|
|
{
|
|
|
|
screen->Clear (listboxLeft, listboxTop+rowHeight*i,
|
2007-12-22 04:52:51 +00:00
|
|
|
listboxRight, listboxTop+rowHeight*(i+1), -1,
|
|
|
|
genStringEnter ? MAKEARGB(255,255,0,0) : MAKEARGB(255,0,0,255));
|
2006-02-24 04:48:15 +00:00
|
|
|
didSeeSelected = true;
|
|
|
|
if (!genStringEnter)
|
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, color,
|
|
|
|
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_WHITE,
|
|
|
|
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, savegamestring,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_WHITE,
|
2006-02-24 04:48:15 +00:00
|
|
|
listboxLeft+1+SmallFont->StringWidth (savegamestring)*CleanXfac,
|
|
|
|
listboxTop+rowHeight*i+CleanYfac, underscore,
|
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, color,
|
|
|
|
listboxLeft+1, listboxTop+rowHeight*i+CleanYfac, node->Title,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is dumb: If the selected node was not visible,
|
|
|
|
// scroll down and redraw. M_SaveLoadResponder()
|
|
|
|
// guarantees that if the node is not visible, it will
|
|
|
|
// always be below the visible list instead of above it.
|
|
|
|
// This should not really be done here, but I don't care.
|
|
|
|
|
|
|
|
if (!didSeeSelected)
|
|
|
|
{
|
|
|
|
for (i = 1; node->Succ != NULL && node != SelSaveGame; ++i)
|
|
|
|
{
|
|
|
|
node = static_cast<FSaveGameNode *>(node->Succ);
|
|
|
|
}
|
|
|
|
if (node->Succ == NULL)
|
|
|
|
{ // SelSaveGame is invalid
|
|
|
|
didSeeSelected = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
TopSaveGame = static_cast<FSaveGameNode *>(TopSaveGame->Succ);
|
|
|
|
} while (--i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (!didSeeSelected);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw a frame around the specified area using the view border
|
|
|
|
// frame graphics. The border is drawn outside the area, not in it.
|
|
|
|
void M_DrawFrame (int left, int top, int width, int height)
|
|
|
|
{
|
2008-01-09 23:04:49 +00:00
|
|
|
FTexture *p;
|
2006-02-24 04:48:15 +00:00
|
|
|
const gameborder_t *border = gameinfo.border;
|
|
|
|
int offset = border->offset;
|
2008-01-09 23:04:49 +00:00
|
|
|
int right = left + width;
|
|
|
|
int bottom = top + height;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Draw top and bottom sides.
|
2008-01-09 23:04:49 +00:00
|
|
|
p = TexMan[border->t];
|
|
|
|
screen->FlatFill(left, top - p->GetHeight(), right, top, p, true);
|
|
|
|
p = TexMan[border->b];
|
|
|
|
screen->FlatFill(left, bottom, right, bottom + p->GetHeight(), p, true);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Draw left and right sides.
|
2008-01-09 23:04:49 +00:00
|
|
|
p = TexMan[border->l];
|
|
|
|
screen->FlatFill(left - p->GetWidth(), top, left, bottom, p, true);
|
|
|
|
p = TexMan[border->r];
|
|
|
|
screen->FlatFill(right, top, right + p->GetWidth(), bottom, p, true);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Draw beveled corners.
|
|
|
|
screen->DrawTexture (TexMan[border->tl], left-offset, top-offset, TAG_DONE);
|
|
|
|
screen->DrawTexture (TexMan[border->tr], left+width, top-offset, TAG_DONE);
|
|
|
|
screen->DrawTexture (TexMan[border->bl], left-offset, top+height, TAG_DONE);
|
|
|
|
screen->DrawTexture (TexMan[border->br], left+width, top+height, TAG_DONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Selected from DOOM menu
|
|
|
|
//
|
|
|
|
void M_LoadGame (int choice)
|
|
|
|
{
|
|
|
|
if (netgame)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("CLOADNET"), NULL);
|
2008-08-30 19:44:19 +00:00
|
|
|
else
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("LOADNET"), NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
M_SetupNextMenu (&LoadDef);
|
|
|
|
drawSkull = false;
|
|
|
|
M_ReadSaveStrings ();
|
|
|
|
TopSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
|
|
|
|
M_ExtractSaveData (SelSaveGame);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_SaveGame & Cie.
|
|
|
|
//
|
|
|
|
void M_DrawSave()
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
FTexture *title = TexMan["M_SAVEG"];
|
|
|
|
screen->DrawTexture (title,
|
2008-05-20 04:02:49 +00:00
|
|
|
(SCREENWIDTH-title->GetScaledWidth()*CleanXfac)/2, 20*CleanYfac,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
const char *text = GStrings("MNU_SAVEGAME");
|
|
|
|
screen->DrawText (BigFont, CR_UNTRANSLATED,
|
2007-05-01 07:57:08 +00:00
|
|
|
(SCREENWIDTH - BigFont->StringWidth (text)*CleanXfac)/2, 10*CleanYfac,
|
|
|
|
text, DTA_CleanNoMove, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
M_DrawSaveLoadCommon ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_Responder calls this when the user is finished
|
|
|
|
//
|
|
|
|
void M_DoSave (FSaveGameNode *node)
|
|
|
|
{
|
|
|
|
if (node != &NewSaveNode)
|
|
|
|
{
|
|
|
|
G_SaveGame (node->Filename.GetChars(), savegamestring);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Find an unused filename and save as that
|
2006-05-03 22:45:01 +00:00
|
|
|
FString filename;
|
2006-02-24 04:48:15 +00:00
|
|
|
int i;
|
|
|
|
FILE *test;
|
|
|
|
|
|
|
|
for (i = 0;; ++i)
|
|
|
|
{
|
|
|
|
filename = G_BuildSaveName ("save", i);
|
2006-05-03 22:45:01 +00:00
|
|
|
test = fopen (filename, "rb");
|
2006-02-24 04:48:15 +00:00
|
|
|
if (test == NULL)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fclose (test);
|
|
|
|
}
|
2006-05-03 22:45:01 +00:00
|
|
|
G_SaveGame (filename, savegamestring);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
M_ClearMenus ();
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Selected from DOOM menu
|
|
|
|
//
|
|
|
|
void M_SaveGame (int choice)
|
|
|
|
{
|
|
|
|
if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer))
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("SAVEDEAD"), NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gamestate != GS_LEVEL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
M_SetupNextMenu(&SaveDef);
|
|
|
|
drawSkull = false;
|
|
|
|
|
|
|
|
M_ReadSaveStrings();
|
|
|
|
SaveGames.AddHead (&NewSaveNode);
|
|
|
|
TopSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
|
2006-04-20 14:21:27 +00:00
|
|
|
if (lastSaveSlot == NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
SelSaveGame = &NewSaveNode;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-20 14:21:27 +00:00
|
|
|
SelSaveGame = lastSaveSlot;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
M_ExtractSaveData (SelSaveGame);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_QuickSave
|
|
|
|
//
|
|
|
|
void M_QuickSaveResponse (int ch)
|
|
|
|
{
|
|
|
|
if (ch == 'y')
|
|
|
|
{
|
|
|
|
M_DoSave (quickSaveSlot);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_QuickSave ()
|
|
|
|
{
|
|
|
|
if (!usergame || (players[consoleplayer].health <= 0 && !multiplayer))
|
|
|
|
{
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/invalid", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gamestate != GS_LEVEL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (quickSaveSlot == NULL)
|
|
|
|
{
|
|
|
|
M_StartControlPanel(false);
|
|
|
|
M_SaveGame (0);
|
|
|
|
return;
|
|
|
|
}
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
|
|
|
mysnprintf (tempstring, countof(tempstring), GStrings("CQSPROMPT"), quickSaveSlot->Title);
|
|
|
|
else
|
|
|
|
mysnprintf (tempstring, countof(tempstring), GStrings("QSPROMPT"), quickSaveSlot->Title);
|
2006-02-24 04:48:15 +00:00
|
|
|
strcpy (savegamestring, quickSaveSlot->Title);
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (tempstring, M_QuickSaveResponse);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_QuickLoad
|
|
|
|
//
|
|
|
|
void M_QuickLoadResponse (int ch)
|
|
|
|
{
|
|
|
|
if (ch == 'y')
|
|
|
|
{
|
|
|
|
M_LoadSelect (quickSaveSlot);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/dismiss", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void M_QuickLoad ()
|
|
|
|
{
|
|
|
|
if (netgame)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("CQLOADNET"), NULL);
|
2008-08-30 19:44:19 +00:00
|
|
|
else
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("QLOADNET"), NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (quickSaveSlot == NULL)
|
|
|
|
{
|
|
|
|
M_StartControlPanel(false);
|
|
|
|
// signal that whatever gets loaded should be the new quicksave
|
|
|
|
quickSaveSlot = (FSaveGameNode *)1;
|
|
|
|
M_LoadGame (0);
|
|
|
|
return;
|
|
|
|
}
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
|
|
|
mysnprintf (tempstring, countof(tempstring), GStrings("CQLPROMPT"), quickSaveSlot->Title);
|
|
|
|
else
|
|
|
|
mysnprintf (tempstring, countof(tempstring), GStrings("QLPROMPT"), quickSaveSlot->Title);
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (tempstring, M_QuickLoadResponse);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Read This Menus
|
|
|
|
//
|
|
|
|
void M_DrawReadThis ()
|
|
|
|
{
|
2008-04-05 12:14:33 +00:00
|
|
|
FTexture *tex = NULL, *prevpic = NULL;
|
2006-02-24 04:48:15 +00:00
|
|
|
fixed_t alpha;
|
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
// Did the mapper choose a custom help page via MAPINFO?
|
|
|
|
if ((level.info != NULL) && level.info->f1[0] != 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-03-22 11:37:56 +00:00
|
|
|
tex = TexMan.FindTexture(level.info->f1);
|
|
|
|
InfoType = 1;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-03-22 11:37:56 +00:00
|
|
|
|
|
|
|
if (tex == NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-03-22 11:37:56 +00:00
|
|
|
tex = TexMan[gameinfo.infoPages[InfoType-1].GetChars()];
|
|
|
|
}
|
2007-05-10 22:22:38 +00:00
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
if (InfoType > 1)
|
|
|
|
{
|
|
|
|
prevpic = TexMan[gameinfo.infoPages[InfoType-2].GetChars()];
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-03-22 11:37:56 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
alpha = MIN<fixed_t> (Scale (gametic - InfoTic, OPAQUE, TICRATE/3), OPAQUE);
|
|
|
|
if (alpha < OPAQUE && prevpic != NULL)
|
|
|
|
{
|
|
|
|
screen->DrawTexture (prevpic, 0, 0,
|
|
|
|
DTA_DestWidth, screen->GetWidth(),
|
|
|
|
DTA_DestHeight, screen->GetHeight(),
|
|
|
|
TAG_DONE);
|
|
|
|
}
|
|
|
|
screen->DrawTexture (tex, 0, 0,
|
|
|
|
DTA_DestWidth, screen->GetWidth(),
|
|
|
|
DTA_DestHeight, screen->GetHeight(),
|
|
|
|
DTA_Alpha, alpha,
|
|
|
|
TAG_DONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_DrawMainMenu
|
|
|
|
//
|
|
|
|
void M_DrawMainMenu (void)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & GAME_DoomChex)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
screen->DrawTexture (TexMan["M_DOOM"], 94, 2, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
screen->DrawTexture (TexMan["M_STRIFE"], 84, 2, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_DrawHereticMainMenu ()
|
|
|
|
{
|
|
|
|
char name[9];
|
|
|
|
|
|
|
|
screen->DrawTexture (TexMan["M_HTIC"], 88, 0, DTA_Clean, true, TAG_DONE);
|
|
|
|
|
|
|
|
if (gameinfo.gametype == GAME_Hexen)
|
|
|
|
{
|
|
|
|
int frame = (MenuTime / 5) % 7;
|
|
|
|
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
mysnprintf (name, countof(name), "FBUL%c0", (frame+2)%7 + 'A');
|
2006-02-24 04:48:15 +00:00
|
|
|
screen->DrawTexture (TexMan[name], 37, 80, DTA_Clean, true, TAG_DONE);
|
|
|
|
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
mysnprintf (name, countof(name), "FBUL%c0", frame + 'A');
|
2006-02-24 04:48:15 +00:00
|
|
|
screen->DrawTexture (TexMan[name], 278, 80, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int frame = (MenuTime / 3) % 18;
|
|
|
|
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
mysnprintf (name, countof(name), "M_SKL%.2d", 17 - frame);
|
2006-02-24 04:48:15 +00:00
|
|
|
screen->DrawTexture (TexMan[name], 40, 10, DTA_Clean, true, TAG_DONE);
|
|
|
|
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
mysnprintf (name, countof(name), "M_SKL%.2d", frame);
|
2006-02-24 04:48:15 +00:00
|
|
|
screen->DrawTexture (TexMan[name], 232, 10, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_NewGame
|
|
|
|
//
|
|
|
|
void M_DrawNewGame(void)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
screen->DrawTexture (TexMan[gameinfo.gametype & GAME_DoomChex ? "M_NEWG" : "M_NGAME"], 96, 14, DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
screen->DrawTexture (TexMan["M_SKILL"], 54, 38, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_NewGame(int choice)
|
|
|
|
{
|
|
|
|
if (netgame && !demoplayback)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("CNEWGAME"), NULL);
|
2008-08-30 19:44:19 +00:00
|
|
|
else
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("NEWGAME"), NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up episode menu positioning
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
EpiDef.x = 48;
|
|
|
|
EpiDef.y = 63;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EpiDef.x = 80;
|
|
|
|
EpiDef.y = 50;
|
|
|
|
}
|
|
|
|
if (EpiDef.numitems > 4)
|
|
|
|
{
|
|
|
|
EpiDef.y -= LINEHEIGHT;
|
|
|
|
}
|
|
|
|
epi = 0;
|
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
if (gameinfo.gametype == GAME_Hexen && ClassMenuDef.numitems == 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // [RH] Make the default entry the last class the player used.
|
|
|
|
ClassMenu.lastOn = players[consoleplayer].userinfo.PlayerClass;
|
|
|
|
if (ClassMenu.lastOn < 0)
|
|
|
|
{
|
|
|
|
ClassMenu.lastOn = 3;
|
|
|
|
}
|
|
|
|
M_SetupNextMenu (&ClassMenu);
|
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
// [GRB] Class select
|
|
|
|
else if (ClassMenuDef.numitems > 1)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
ClassMenuDef.lastOn = ClassMenuDef.numitems - 1;
|
|
|
|
if (players[consoleplayer].userinfo.PlayerClass >= 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
int n = 0;
|
2006-07-16 01:25:29 +00:00
|
|
|
for (int i = 0; i < (int)PlayerClasses.Size () && n < 7; i++)
|
2006-05-13 12:41:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
if (!(PlayerClasses[i].Flags & PCF_NOMENU))
|
|
|
|
{
|
|
|
|
if (i == players[consoleplayer].userinfo.PlayerClass)
|
|
|
|
{
|
|
|
|
ClassMenuDef.lastOn = n;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
n++;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
|
|
|
|
PickPlayerClass ();
|
|
|
|
|
|
|
|
PlayerState = GetDefaultByType (PlayerClass->Type)->SeeState;
|
|
|
|
PlayerTics = PlayerState->GetTics();
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
if (FireTexture == NULL)
|
|
|
|
{
|
|
|
|
FireTexture = new FBackdropTexture;
|
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
M_SetupNextMenu (&ClassMenuDef);
|
|
|
|
}
|
|
|
|
else if (EpiDef.numitems <= 1)
|
|
|
|
{
|
2008-10-26 17:06:47 +00:00
|
|
|
if (AllSkills.Size() == 1)
|
2006-07-13 10:17:56 +00:00
|
|
|
{
|
2008-10-26 17:06:47 +00:00
|
|
|
M_ChooseSkill(0);
|
|
|
|
}
|
|
|
|
else if (EpisodeNoSkill[0])
|
|
|
|
{
|
|
|
|
M_ChooseSkill(AllSkills.Size() == 2? 1:2);
|
2006-07-13 10:17:56 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
else
|
|
|
|
{
|
2007-11-02 22:03:03 +00:00
|
|
|
M_StartupSkillMenu(NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
M_SetupNextMenu (&EpiDef);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-06-03 12:30:11 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// DrawClassMenu
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void DrawClassMenu(void)
|
|
|
|
{
|
|
|
|
char name[9];
|
|
|
|
int classnum;
|
|
|
|
|
|
|
|
static const char boxLumpName[3][7] =
|
|
|
|
{
|
|
|
|
"M_FBOX",
|
|
|
|
"M_CBOX",
|
|
|
|
"M_MBOX"
|
|
|
|
};
|
|
|
|
static const char walkLumpName[3][10] =
|
|
|
|
{
|
|
|
|
"M_FWALK%d",
|
|
|
|
"M_CWALK%d",
|
|
|
|
"M_MWALK%d"
|
|
|
|
};
|
|
|
|
|
2008-11-27 17:43:36 +00:00
|
|
|
const char *text = GStrings("MNU_CHOOSECLASS");
|
|
|
|
screen->DrawText (BigFont, CR_UNTRANSLATED, 34, 24, text, DTA_Clean, true, TAG_DONE);
|
2006-06-03 12:30:11 +00:00
|
|
|
classnum = itemOn;
|
|
|
|
if (classnum > 2)
|
|
|
|
{
|
|
|
|
classnum = (MenuTime>>2) % 3;
|
|
|
|
}
|
|
|
|
screen->DrawTexture (TexMan[boxLumpName[classnum]], 174, 8, DTA_Clean, true, TAG_DONE);
|
|
|
|
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
mysnprintf (name, countof(name), walkLumpName[classnum], ((MenuTime >> 3) & 3) + 1);
|
2006-06-03 12:30:11 +00:00
|
|
|
screen->DrawTexture (TexMan[name], 174+24, 8+12, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
// [GRB] Class select drawer
|
|
|
|
static void M_DrawClassMenu ()
|
|
|
|
{
|
|
|
|
int tit_y = 15;
|
2007-05-01 07:57:08 +00:00
|
|
|
const char * text = GStrings("MNU_CHOOSECLASS");
|
2006-07-13 10:17:56 +00:00
|
|
|
|
|
|
|
if (ClassMenuDef.numitems > 4 && gameinfo.gametype & GAME_Raven)
|
|
|
|
tit_y = 2;
|
|
|
|
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED,
|
2007-05-01 07:57:08 +00:00
|
|
|
160 - BigFont->StringWidth (text)/2,
|
2006-07-13 10:17:56 +00:00
|
|
|
tit_y,
|
2007-05-01 07:57:08 +00:00
|
|
|
text, DTA_Clean, true, TAG_DONE);
|
2006-07-13 10:17:56 +00:00
|
|
|
|
|
|
|
int x = (200-160)*CleanXfac+(SCREENWIDTH>>1);
|
|
|
|
int y = (ClassMenuDef.y-100)*CleanYfac+(SCREENHEIGHT>>1);
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
if (!FireTexture)
|
2006-07-13 10:17:56 +00:00
|
|
|
{
|
2007-12-22 04:52:51 +00:00
|
|
|
screen->Clear (x, y, x + 72 * CleanXfac, y + 80 * CleanYfac-1, 0, 0);
|
2006-07-13 10:17:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-27 04:30:12 +00:00
|
|
|
screen->DrawTexture (FireTexture, x, y - 1,
|
|
|
|
DTA_DestWidth, 72 * CleanXfac,
|
|
|
|
DTA_DestHeight, 80 * CleanYfac,
|
|
|
|
DTA_Translation, &FireRemap,
|
|
|
|
DTA_Masked, true,
|
|
|
|
TAG_DONE);
|
2006-07-13 10:17:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
M_DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1);
|
|
|
|
|
2008-08-10 14:19:47 +00:00
|
|
|
spriteframe_t *sprframe = &SpriteFrames[sprites[PlayerState->sprite].spriteframes + PlayerState->GetFrame()];
|
2006-11-14 16:54:02 +00:00
|
|
|
fixed_t scaleX = GetDefaultByType (PlayerClass->Type)->scaleX;
|
|
|
|
fixed_t scaleY = GetDefaultByType (PlayerClass->Type)->scaleY;
|
2006-07-13 10:17:56 +00:00
|
|
|
|
|
|
|
if (sprframe != NULL)
|
|
|
|
{
|
|
|
|
FTexture *tex = TexMan(sprframe->Texture[0]);
|
|
|
|
if (tex != NULL && tex->UseType != FTexture::TEX_Null)
|
|
|
|
{
|
|
|
|
screen->DrawTexture (tex,
|
|
|
|
x + 36*CleanXfac, y + 71*CleanYfac,
|
2006-11-14 16:54:02 +00:00
|
|
|
DTA_DestWidth, MulScale16 (tex->GetWidth() * CleanXfac, scaleX),
|
|
|
|
DTA_DestHeight, MulScale16 (tex->GetHeight() * CleanYfac, scaleY),
|
2006-07-13 10:17:56 +00:00
|
|
|
TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-03 12:30:11 +00:00
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC DrawSkillMenu
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
static void DrawHexenSkillMenu()
|
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (BigFont, CR_UNTRANSLATED, 74, 16, GStrings("MNU_CHOOSESKILL"), DTA_Clean, true, TAG_DONE);
|
2006-06-03 12:30:11 +00:00
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// M_Episode
|
|
|
|
//
|
|
|
|
void M_DrawEpisode ()
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
screen->DrawTexture (TexMan["M_EPISOD"], 54, 38, DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-10 08:21:25 +00:00
|
|
|
static int confirmskill;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void M_VerifyNightmare (int ch)
|
|
|
|
{
|
|
|
|
if (ch != 'y')
|
|
|
|
return;
|
|
|
|
|
2007-12-10 08:21:25 +00:00
|
|
|
G_DeferedInitNew (EpisodeMaps[epi], confirmskill);
|
2007-10-08 09:54:00 +00:00
|
|
|
if (gamestate == GS_FULLCONSOLE)
|
|
|
|
{
|
|
|
|
gamestate = GS_HIDECONSOLE;
|
|
|
|
gameaction = ga_newgame;
|
2007-12-09 03:40:02 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
M_ClearMenus ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_ChooseSkill (int choice)
|
|
|
|
{
|
2007-12-09 02:27:02 +00:00
|
|
|
if (AllSkills[choice].MustConfirm)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-12-06 08:55:17 +00:00
|
|
|
const char *msg = AllSkills[choice].MustConfirmText;
|
|
|
|
if (*msg==0) msg = GStrings("NIGHTMARE");
|
|
|
|
if (*msg=='$') msg = GStrings(msg+1);
|
2007-12-10 08:21:25 +00:00
|
|
|
confirmskill = choice;
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (msg, M_VerifyNightmare);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-08-09 08:42:15 +00:00
|
|
|
G_DeferedInitNew (EpisodeMaps[epi], choice);
|
2007-02-28 16:49:19 +00:00
|
|
|
if (gamestate == GS_FULLCONSOLE)
|
|
|
|
{
|
|
|
|
gamestate = GS_HIDECONSOLE;
|
|
|
|
gameaction = ga_newgame;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
M_ClearMenus ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_Episode (int choice)
|
|
|
|
{
|
|
|
|
if ((gameinfo.flags & GI_SHAREWARE) && choice)
|
|
|
|
{
|
|
|
|
if (gameinfo.gametype == GAME_Doom)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage(GStrings("SWSTRING"), NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
//M_SetupNextMenu(&ReadDef);
|
|
|
|
}
|
2008-08-30 19:44:19 +00:00
|
|
|
else if (gameinfo.gametype == GAME_Chex)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage(GStrings("CSWSTRING"), NULL);
|
2008-08-30 19:44:19 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
showSharewareMessage = 3*TICRATE;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-07-30 08:31:26 +00:00
|
|
|
epi = choice;
|
|
|
|
|
2008-10-26 17:06:47 +00:00
|
|
|
if (AllSkills.Size() == 1)
|
2006-05-13 12:41:15 +00:00
|
|
|
{
|
2008-12-27 20:18:31 +00:00
|
|
|
saved_playerclass = NULL;
|
2008-10-26 17:06:47 +00:00
|
|
|
M_ChooseSkill(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (EpisodeNoSkill[choice])
|
|
|
|
{
|
2008-12-27 20:18:31 +00:00
|
|
|
saved_playerclass = NULL;
|
2008-10-26 17:06:47 +00:00
|
|
|
M_ChooseSkill(AllSkills.Size() == 2? 1:2);
|
2006-05-13 12:41:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-12-27 20:18:31 +00:00
|
|
|
M_StartupSkillMenu(saved_playerclass);
|
|
|
|
saved_playerclass = NULL;
|
2006-07-13 10:17:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// SCClass
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
static void SCClass (int option)
|
|
|
|
{
|
|
|
|
if (netgame)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("CNEWGAME"), NULL);
|
2008-08-30 19:44:19 +00:00
|
|
|
else
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("NEWGAME"), NULL);
|
2006-07-13 10:17:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (option == 3)
|
|
|
|
playerclass = "Random";
|
|
|
|
else
|
|
|
|
playerclass = PlayerClasses[option].Type->Meta.GetMetaString (APMETA_DisplayName);
|
|
|
|
|
2006-06-03 12:30:11 +00:00
|
|
|
if (EpiDef.numitems > 1)
|
|
|
|
{
|
2008-12-27 20:18:31 +00:00
|
|
|
saved_playerclass = playerclass;
|
2006-06-03 12:30:11 +00:00
|
|
|
M_SetupNextMenu (&EpiDef);
|
|
|
|
}
|
2008-10-26 17:06:47 +00:00
|
|
|
else if (AllSkills.Size() == 1)
|
|
|
|
{
|
|
|
|
M_ChooseSkill(0);
|
|
|
|
}
|
2006-06-03 12:30:11 +00:00
|
|
|
else if (!EpisodeNoSkill[0])
|
|
|
|
{
|
2007-11-02 22:03:03 +00:00
|
|
|
M_StartupSkillMenu(playerclass);
|
2006-06-03 12:30:11 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-10-26 17:06:47 +00:00
|
|
|
M_ChooseSkill(AllSkills.Size() == 2? 1:2);
|
2006-06-03 12:30:11 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
// [GRB]
|
|
|
|
static void M_ChooseClass (int choice)
|
|
|
|
{
|
|
|
|
if (netgame)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("CNEWGAME"), NULL);
|
2008-08-30 19:44:19 +00:00
|
|
|
else
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (GStrings("NEWGAME"), NULL);
|
2006-07-13 10:17:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
playerclass = (choice < ClassMenuDef.numitems-1) ? ClassMenuItems[choice].name : "Random";
|
|
|
|
|
|
|
|
if (EpiDef.numitems > 1)
|
|
|
|
{
|
2008-12-27 20:18:31 +00:00
|
|
|
saved_playerclass = playerclass;
|
2006-07-13 10:17:56 +00:00
|
|
|
M_SetupNextMenu (&EpiDef);
|
|
|
|
}
|
2008-10-26 17:06:47 +00:00
|
|
|
else if (AllSkills.Size() == 1)
|
|
|
|
{
|
|
|
|
M_ChooseSkill(0);
|
|
|
|
}
|
2006-07-16 10:23:14 +00:00
|
|
|
else if (EpisodeNoSkill[0])
|
2006-07-13 10:17:56 +00:00
|
|
|
{
|
2008-10-26 17:06:47 +00:00
|
|
|
M_ChooseSkill(AllSkills.Size() == 2? 1:2);
|
2006-07-13 10:17:56 +00:00
|
|
|
}
|
2007-11-02 22:03:03 +00:00
|
|
|
else
|
2006-07-13 10:17:56 +00:00
|
|
|
{
|
2007-11-02 22:03:03 +00:00
|
|
|
M_StartupSkillMenu(playerclass);
|
2006-07-13 10:17:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
void M_Options (int choice)
|
|
|
|
{
|
|
|
|
OptionsActive = M_StartOptionsMenu ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_EndGame
|
|
|
|
//
|
|
|
|
void M_EndGameResponse(int ch)
|
|
|
|
{
|
|
|
|
if (ch != 'y')
|
|
|
|
return;
|
|
|
|
|
|
|
|
currentMenu->lastOn = itemOn;
|
|
|
|
M_ClearMenus ();
|
|
|
|
D_StartTitle ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_EndGame(int choice)
|
|
|
|
{
|
|
|
|
choice = 0;
|
|
|
|
if (!usergame)
|
|
|
|
{
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/invalid", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (netgame)
|
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage(GStrings("CNETEND"), NULL);
|
2008-08-30 19:44:19 +00:00
|
|
|
else
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage(GStrings("NETEND"), NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-08-30 19:44:19 +00:00
|
|
|
|
|
|
|
if(gameinfo.gametype == GAME_Chex)
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage(GStrings("CENDGAME"), M_EndGameResponse);
|
2008-08-30 19:44:19 +00:00
|
|
|
else
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage(GStrings("ENDGAME"), M_EndGameResponse);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_ReadThis
|
|
|
|
//
|
|
|
|
void M_ReadThis (int choice)
|
|
|
|
{
|
|
|
|
drawSkull = false;
|
|
|
|
InfoType = 1;
|
|
|
|
InfoTic = gametic;
|
|
|
|
M_SetupNextMenu (&ReadDef);
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_ReadThisMore (int choice)
|
|
|
|
{
|
|
|
|
InfoType++;
|
|
|
|
InfoTic = gametic;
|
2009-03-22 11:37:56 +00:00
|
|
|
if ((level.info != NULL && level.info->f1[0] != 0) || InfoType > int(gameinfo.infoPages.Size()))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
M_FinishReadThis (0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_FinishReadThis (int choice)
|
|
|
|
{
|
|
|
|
drawSkull = true;
|
|
|
|
M_PopMenuStack ();
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2008-01-26 16:42:16 +00:00
|
|
|
// M_QuitGame
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
void M_QuitResponse(int ch)
|
|
|
|
{
|
|
|
|
if (ch != 'y')
|
|
|
|
return;
|
|
|
|
if (!netgame)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
if (gameinfo.quitSound.IsNotEmpty())
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, gameinfo.quitSound, 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
I_WaitVBL (105);
|
|
|
|
}
|
|
|
|
}
|
2007-01-06 12:30:34 +00:00
|
|
|
ST_Endoom();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2008-01-26 16:42:16 +00:00
|
|
|
void M_QuitGame (int choice)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-09-01 18:16:53 +00:00
|
|
|
int quitmsg = 0;
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype == GAME_Doom)
|
2008-09-13 19:19:53 +00:00
|
|
|
{
|
|
|
|
quitmsg = gametic % (NUM_QUITDOOMMESSAGES + 1);
|
|
|
|
}
|
2008-08-30 19:44:19 +00:00
|
|
|
else if (gameinfo.gametype == GAME_Strife)
|
2008-09-13 19:19:53 +00:00
|
|
|
{
|
|
|
|
quitmsg = gametic % (NUM_QUITSTRIFEMESSAGES + 1);
|
|
|
|
if (quitmsg != 0) quitmsg += NUM_QUITDOOMMESSAGES;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
quitmsg = gametic % (NUM_QUITCHEXMESSAGES + 1);
|
|
|
|
if (quitmsg != 0) quitmsg += NUM_QUITDOOMMESSAGES + NUM_QUITSTRIFEMESSAGES;
|
|
|
|
}
|
2008-08-30 19:44:19 +00:00
|
|
|
|
2008-09-13 19:19:53 +00:00
|
|
|
if (quitmsg != 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-09-13 19:19:53 +00:00
|
|
|
EndString.Format("QUITMSG%d", quitmsg);
|
2007-05-01 07:57:08 +00:00
|
|
|
EndString.Format("%s\n\n%s", GStrings(EndString), GStrings("DOSY"));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-05-01 07:57:08 +00:00
|
|
|
EndString.Format("%s\n\n%s", GStrings("QUITMSG"), GStrings("DOSY"));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-05-01 07:57:08 +00:00
|
|
|
EndString = GStrings("RAVENQUITMSG");
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (EndString, M_QuitResponse);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// [RH] Player Setup Menu code
|
|
|
|
//
|
|
|
|
void M_PlayerSetup (void)
|
|
|
|
{
|
|
|
|
OptionsActive = false;
|
|
|
|
drawSkull = true;
|
|
|
|
strcpy (savegamestring, name);
|
|
|
|
M_DemoNoPlay = true;
|
|
|
|
if (demoplayback)
|
|
|
|
G_CheckDemoStatus ();
|
|
|
|
M_SetupNextMenu (&PSetupDef);
|
|
|
|
if (players[consoleplayer].mo != NULL)
|
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
PlayerClass = &PlayerClasses[players[consoleplayer].CurrentPlayerClass];
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
PlayerSkin = players[consoleplayer].userinfo.skin;
|
2010-03-06 02:51:23 +00:00
|
|
|
R_GetPlayerTranslation (players[consoleplayer].userinfo.color,
|
|
|
|
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
|
|
|
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
2006-07-13 10:17:56 +00:00
|
|
|
PlayerState = GetDefaultByType (PlayerClass->Type)->SeeState;
|
2006-02-24 04:48:15 +00:00
|
|
|
PlayerTics = PlayerState->GetTics();
|
2007-12-27 04:30:12 +00:00
|
|
|
if (FireTexture == NULL)
|
|
|
|
{
|
|
|
|
FireTexture = new FBackdropTexture;
|
|
|
|
}
|
2010-03-06 02:51:23 +00:00
|
|
|
P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void M_PlayerSetupTicker (void)
|
|
|
|
{
|
|
|
|
// Based on code in f_finale.c
|
2006-07-13 10:17:56 +00:00
|
|
|
FPlayerClass *oldclass = PlayerClass;
|
|
|
|
|
|
|
|
if (currentMenu == &ClassMenuDef)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
int item;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
if (itemOn < ClassMenuDef.numitems-1)
|
|
|
|
item = itemOn;
|
|
|
|
else
|
|
|
|
item = (MenuTime>>2) % (ClassMenuDef.numitems-1);
|
|
|
|
|
|
|
|
PlayerClass = &PlayerClasses[D_PlayerClassToInt (ClassMenuItems[item].name)];
|
2010-03-06 02:51:23 +00:00
|
|
|
P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets);
|
2006-07-13 10:17:56 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-02-24 04:48:15 +00:00
|
|
|
PickPlayerClass ();
|
|
|
|
}
|
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
if (PlayerClass != oldclass)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
PlayerState = GetDefaultByType (PlayerClass->Type)->SeeState;
|
|
|
|
PlayerTics = PlayerState->GetTics();
|
|
|
|
|
2008-09-14 23:54:38 +00:00
|
|
|
PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(PlayerClass - &PlayerClasses[0]));
|
2006-07-13 10:17:56 +00:00
|
|
|
R_GetPlayerTranslation (players[consoleplayer].userinfo.color,
|
2010-03-06 02:51:23 +00:00
|
|
|
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
- Discovered that Shader Model 1.4 clamps my constants, so I can't use
palettes smaller than 256 entries with the shader I wrote for it. Is there
a list of gotchas like this listed some where? I'd really like to see it.
Well, when compiled with SM2.0, the PalTex shader seems to be every-so-
slightly faster on my GF7950GT than the SM1.4 version, so I guess it's a
minor win for cards that support it.
- Fixed: ST_Endoom() failed to free the bitmap it used.
- Added the DTA_ColorOverlay attribute to blend a color with the texture
being drawn. For software, this (currently) only works with black. For
hardware, it works with any color. The motiviation for this was so I could
rewrite the status bar calls that passed DIM_MAP to DTA_Translation to
draw darker icons into something that didn't require making a whole new
remap table.
- After having an "OMG! How could I have been so stupid?" moment, I have
removed the off-by-one check from D3DFB. I had thought the off-by-one error
was caused by rounding errors by the shader hardware. Not so. Rather, I
wasn't sampling what I thought I was sampling. A texture that uses palette
index 255 passes the value 1.0 to the shader. The shader needs to adjust the
range of its palette indexes, or it will end up trying to read color 256
from the palette texture when it should be reading color 255. Doh!
- The TranslationToTable() function has been added to map from translation
numbers used by actors to the tables those numbers represent. This function
performs validation for the input and returns NULL if the input value
is invalid.
- Major changes to the way translation tables work: No longer are they each a
256-byte array. Instead, the FRemapTable structure is used to represent each
one. It includes a remap array for the software renderer, a palette array
for a hardware renderer, and a native texture pointer for D3DFB. The
translationtables array itself is now an array of TArrays that point to the
real tables. The DTA_Translation attribute must also be passed a pointer
to a FRemapTable, not a byte array as previously.
- Modified DFrameBuffer::DrawRateStuff() so that it can do its thing properly
for D3DFB's 2D mode. Before, any fullscreen graphics (like help images)
covered it up.
SVN r640 (trunk)
2007-12-26 04:42:15 +00:00
|
|
|
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
|
|
|
|
if (PlayerState->GetTics () != -1 && PlayerState->GetNextState () != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
if (--PlayerTics > 0)
|
|
|
|
return;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
PlayerState = PlayerState->GetNextState();
|
2006-07-13 10:17:56 +00:00
|
|
|
PlayerTics = PlayerState->GetTics();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-12-25 05:55:51 +00:00
|
|
|
|
|
|
|
static void M_DrawPlayerSlider (int x, int y, int cur)
|
|
|
|
{
|
|
|
|
const int range = 255;
|
|
|
|
|
|
|
|
x = (x - 160) * CleanXfac + screen->GetWidth() / 2;
|
|
|
|
y = (y - 100) * CleanYfac + screen->GetHeight() / 2;
|
|
|
|
|
|
|
|
screen->DrawText (ConFont, CR_WHITE, x, y,
|
|
|
|
"\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12",
|
|
|
|
DTA_CellX, 8 * CleanXfac,
|
|
|
|
DTA_CellY, 8 * CleanYfac,
|
|
|
|
TAG_DONE);
|
|
|
|
screen->DrawText (ConFont, CR_ORANGE, x + (5 + (int)((cur * 78) / range)) * CleanXfac, y,
|
|
|
|
"\x13",
|
|
|
|
DTA_CellX, 8 * CleanXfac,
|
|
|
|
DTA_CellY, 8 * CleanYfac,
|
|
|
|
TAG_DONE);
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_PlayerSetupDrawer ()
|
|
|
|
{
|
2010-01-05 02:56:27 +00:00
|
|
|
const int LINEHEIGHT = PLAYERSETUP_LINEHEIGHT;
|
2006-02-24 04:48:15 +00:00
|
|
|
int x, xo, yo;
|
|
|
|
EColorRange label, value;
|
|
|
|
DWORD color;
|
|
|
|
|
2008-08-30 19:44:19 +00:00
|
|
|
if (!(gameinfo.gametype & (GAME_DoomStrifeChex)))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
xo = 5;
|
|
|
|
yo = 5;
|
|
|
|
label = CR_GREEN;
|
|
|
|
value = CR_UNTRANSLATED;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xo = yo = 0;
|
|
|
|
label = CR_UNTRANSLATED;
|
|
|
|
value = CR_GREY;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw title
|
2008-11-27 17:43:36 +00:00
|
|
|
const char *text = GStrings("MNU_PLAYERSETUP");
|
|
|
|
screen->DrawText (BigFont, gameinfo.gametype & GAME_DoomChex ? CR_RED : CR_UNTRANSLATED,
|
2007-05-01 07:57:08 +00:00
|
|
|
160 - BigFont->StringWidth (text)/2,
|
2006-02-24 04:48:15 +00:00
|
|
|
15,
|
2007-05-01 07:57:08 +00:00
|
|
|
text, DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Draw player name box
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y+yo, "Name", DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
M_DrawSaveLoadBorder (PSetupDef.x + 56, PSetupDef.y, MAXPLAYERNAME+1);
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_UNTRANSLATED, PSetupDef.x + 56 + xo, PSetupDef.y+yo, savegamestring,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
|
|
|
|
// Draw cursor for player name box
|
|
|
|
if (genStringEnter)
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_UNTRANSLATED,
|
2006-02-24 04:48:15 +00:00
|
|
|
PSetupDef.x + SmallFont->StringWidth(savegamestring) + 56+xo,
|
|
|
|
PSetupDef.y + yo, underscore, DTA_Clean, true, TAG_DONE);
|
|
|
|
|
|
|
|
// Draw player team setting
|
|
|
|
x = SmallFont->StringWidth ("Team") + 8 + PSetupDef.x;
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT+yo, "Team",
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_Clean, true, TAG_DONE);
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT+yo,
|
2009-02-04 23:14:28 +00:00
|
|
|
!TeamLibrary.IsValidTeam (players[consoleplayer].userinfo.team) ? "None" :
|
|
|
|
Teams[players[consoleplayer].userinfo.team].GetName (),
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
|
|
|
|
// Draw player character
|
|
|
|
{
|
|
|
|
int x = 320 - 88 - 32 + xo, y = PSetupDef.y + LINEHEIGHT*3 - 18 + yo;
|
|
|
|
|
|
|
|
x = (x-160)*CleanXfac+(SCREENWIDTH>>1);
|
|
|
|
y = (y-100)*CleanYfac+(SCREENHEIGHT>>1);
|
2007-12-27 04:30:12 +00:00
|
|
|
if (!FireTexture)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-12-22 04:52:51 +00:00
|
|
|
screen->Clear (x, y, x + 72 * CleanXfac, y + 80 * CleanYfac-1, 0, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-12-27 04:30:12 +00:00
|
|
|
screen->DrawTexture (FireTexture, x, y - 1,
|
|
|
|
DTA_DestWidth, 72 * CleanXfac,
|
|
|
|
DTA_DestHeight, 80 * CleanYfac,
|
|
|
|
DTA_Translation, &FireRemap,
|
2008-01-27 04:53:55 +00:00
|
|
|
DTA_Masked, false,
|
2007-12-27 04:30:12 +00:00
|
|
|
TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
M_DrawFrame (x, y, 72*CleanXfac, 80*CleanYfac-1);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
spriteframe_t *sprframe;
|
2008-04-27 22:33:19 +00:00
|
|
|
fixed_t ScaleX, ScaleY;
|
2006-07-13 10:17:56 +00:00
|
|
|
|
|
|
|
if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
|
|
|
|
players[consoleplayer].userinfo.PlayerClass == -1 ||
|
2008-08-10 14:19:47 +00:00
|
|
|
PlayerState->sprite != GetDefaultByType (PlayerClass->Type)->SpawnState->sprite)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-10 14:19:47 +00:00
|
|
|
sprframe = &SpriteFrames[sprites[PlayerState->sprite].spriteframes + PlayerState->GetFrame()];
|
2008-04-27 22:33:19 +00:00
|
|
|
ScaleX = GetDefaultByType(PlayerClass->Type)->scaleX;
|
|
|
|
ScaleY = GetDefaultByType(PlayerClass->Type)->scaleY;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
sprframe = &SpriteFrames[sprites[skins[PlayerSkin].sprite].spriteframes + PlayerState->GetFrame()];
|
2008-04-27 22:33:19 +00:00
|
|
|
ScaleX = skins[PlayerSkin].ScaleX;
|
|
|
|
ScaleY = skins[PlayerSkin].ScaleY;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sprframe != NULL)
|
|
|
|
{
|
|
|
|
FTexture *tex = TexMan(sprframe->Texture[0]);
|
|
|
|
if (tex != NULL && tex->UseType != FTexture::TEX_Null)
|
|
|
|
{
|
|
|
|
if (tex->Rotations != 0xFFFF)
|
|
|
|
{
|
|
|
|
tex = TexMan(SpriteFrames[tex->Rotations].Texture[PlayerRotation]);
|
|
|
|
}
|
|
|
|
screen->DrawTexture (tex,
|
|
|
|
(320 - 52 - 32 + xo - 160)*CleanXfac + (SCREENWIDTH)/2,
|
|
|
|
(PSetupDef.y + LINEHEIGHT*3 + 57 - 104)*CleanYfac + (SCREENHEIGHT/2),
|
2008-04-27 22:33:19 +00:00
|
|
|
DTA_DestWidth, MulScale16 (tex->GetWidth() * CleanXfac, ScaleX),
|
|
|
|
DTA_DestHeight, MulScale16 (tex->GetHeight() * CleanYfac, ScaleY),
|
2008-01-08 01:48:33 +00:00
|
|
|
DTA_Translation, translationtables[TRANSLATION_Players](MAXPLAYERS),
|
2006-02-24 04:48:15 +00:00
|
|
|
TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *str = "PRESS " TEXTCOLOR_WHITE "SPACE";
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_GOLD, 320 - 52 - 32 -
|
2006-02-24 04:48:15 +00:00
|
|
|
SmallFont->StringWidth (str)/2,
|
|
|
|
PSetupDef.y + LINEHEIGHT*3 + 76, str,
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
str = PlayerRotation ? "TO SEE FRONT" : "TO SEE BACK";
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_GOLD, 320 - 52 - 32 -
|
2006-02-24 04:48:15 +00:00
|
|
|
SmallFont->StringWidth (str)/2,
|
|
|
|
PSetupDef.y + LINEHEIGHT*3 + 76 + SmallFont->GetHeight (), str,
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
// Draw player color selection and sliders
|
|
|
|
FPlayerColorSet *colorset = P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset);
|
|
|
|
x = SmallFont->StringWidth("Color") + 8 + PSetupDef.x;
|
|
|
|
screen->DrawText(SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*2+yo, "Color", DTA_Clean, true, TAG_DONE);
|
|
|
|
screen->DrawText(SmallFont, value, x, PSetupDef.y + LINEHEIGHT*2+yo,
|
|
|
|
colorset != NULL ? colorset->Name.GetChars() : "Custom", DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
// Only show the sliders for a custom color set.
|
|
|
|
if (colorset == NULL)
|
|
|
|
{
|
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*2.875)+yo, "Red", DTA_Clean, true, TAG_DONE);
|
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*3.5)+yo, "Green", DTA_Clean, true, TAG_DONE);
|
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*4.125)+yo, "Blue", DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x;
|
|
|
|
color = players[consoleplayer].userinfo.color;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*2.875)+yo, RPART(color));
|
|
|
|
M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*3.5)+yo, GPART(color));
|
|
|
|
M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*4.125)+yo, BPART(color));
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
// [GRB] Draw class setting
|
|
|
|
int pclass = players[consoleplayer].userinfo.PlayerClass;
|
|
|
|
x = SmallFont->StringWidth ("Class") + 8 + PSetupDef.x;
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*5+yo, "Class", DTA_Clean, true, TAG_DONE);
|
|
|
|
screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT*5+yo,
|
2006-07-13 10:17:56 +00:00
|
|
|
pclass == -1 ? "Random" : PlayerClasses[pclass].Type->Meta.GetMetaString (APMETA_DisplayName),
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Draw skin setting
|
2006-07-13 10:17:56 +00:00
|
|
|
x = SmallFont->StringWidth ("Skin") + 8 + PSetupDef.x;
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*6+yo, "Skin", DTA_Clean, true, TAG_DONE);
|
2006-07-13 10:17:56 +00:00
|
|
|
if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
|
|
|
|
players[consoleplayer].userinfo.PlayerClass == -1)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT*6+yo, "Base", DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT*6+yo,
|
2006-07-13 10:17:56 +00:00
|
|
|
skins[PlayerSkin].name, DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
// Draw gender setting
|
|
|
|
x = SmallFont->StringWidth ("Gender") + 8 + PSetupDef.x;
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*7+yo, "Gender", DTA_Clean, true, TAG_DONE);
|
|
|
|
screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT*7+yo,
|
2006-07-13 10:17:56 +00:00
|
|
|
genders[players[consoleplayer].userinfo.gender], DTA_Clean, true, TAG_DONE);
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// Draw autoaim setting
|
|
|
|
x = SmallFont->StringWidth ("Autoaim") + 8 + PSetupDef.x;
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*8+yo, "Autoaim", DTA_Clean, true, TAG_DONE);
|
|
|
|
screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT*8+yo,
|
2006-02-24 04:48:15 +00:00
|
|
|
autoaim == 0 ? "Never" :
|
|
|
|
autoaim <= 0.25 ? "Very Low" :
|
|
|
|
autoaim <= 0.5 ? "Low" :
|
|
|
|
autoaim <= 1 ? "Medium" :
|
|
|
|
autoaim <= 2 ? "High" :
|
|
|
|
autoaim <= 3 ? "Very High" : "Always",
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
// A 32x32 cloud rendered with Photoshop, plus some other filters
|
|
|
|
static BYTE pattern1[1024] =
|
|
|
|
{
|
|
|
|
5, 9, 7,10, 9,15, 9, 7, 8,10, 5, 3, 5, 7, 9, 8,14, 8, 4, 7, 8, 9, 5, 7,14, 7, 0, 7,13,13, 9, 6,
|
|
|
|
2, 7, 9, 7, 7,10, 8, 8,11,10, 6, 7,10, 7, 5, 6, 6, 4, 7,13,15,16,11,15,11, 8, 0, 4,13,22,17,11,
|
|
|
|
5, 9, 9, 7, 9,10, 4, 3, 6, 7, 8, 6, 5, 4, 2, 2, 1, 4, 6,11,15,15,14,13,17, 9, 5, 9,11,12,17,20,
|
|
|
|
9,16, 9, 8,12,13, 7, 3, 7, 9, 5, 4, 2, 5, 5, 5, 7,11, 6, 7, 6,13,17,10,10, 9,12,17,14,12,16,15,
|
|
|
|
15,13, 5, 3, 9,10, 4,10,12,12, 7, 9, 8, 8, 8,10, 7, 6, 5, 5, 5, 6,11, 9, 3,13,16,18,21,16,23,18,
|
|
|
|
23,13, 0, 0, 0, 0, 0,12,18,14,15,16,13, 7, 7, 5, 9, 6, 6, 8, 4, 0, 0, 0, 0,14,19,17,14,20,21,25,
|
|
|
|
19,20,14,13, 7, 5,13,19,14,13,17,15,14, 7, 3, 5, 6,11, 7, 7, 8, 8,10, 9, 9,18,17,15,14,15,18,16,
|
|
|
|
16,29,24,23,18, 9,17,20,11, 5,12,15,15,12, 6, 3, 4, 6, 7,10,13,18,18,19,16,12,17,19,23,16,14,14,
|
|
|
|
9,18,20,26,19, 5,18,18,10, 5,12,15,14,17,11, 6,11, 9,10,13,10,20,24,20,21,20,14,18,15,22,20,19,
|
|
|
|
0, 6,16,18, 8, 7,15,18,10,13,17,17,13,11,15,11,19,12,13,10, 4,15,19,21,21,24,14, 9,17,20,24,17,
|
|
|
|
18,17, 7, 7,16,21,22,15, 5,14,20,14,13,21,13, 8,12,14, 7, 8,11,15,13,11,16,17, 7, 5,12,17,19,14,
|
|
|
|
25,23,17,16,23,18,15, 7, 0, 6,11, 6,11,15,11, 7,12, 7, 4,10,16,13, 7, 7,15,13, 9,15,21,14, 5, 0,
|
|
|
|
18,22,21,21,21,22,12, 6,14,20,15, 6,10,19,13, 8, 7, 3, 7,12,14,16, 9,12,22,15,12,18,24,19,17, 9,
|
|
|
|
0,15,18,21,17,25,14,13,19,21,21,11, 6,13,16,16,12,10,12,11,13,20,14,13,18,13, 9,15,16,25,31,20,
|
|
|
|
5,20,24,16, 7,14,14,11,18,19,19, 6, 0, 5,11,14,17,16,19,14,15,21,19,15,14,14, 8, 0, 7,24,18,16,
|
|
|
|
9,17,15, 7, 6,14,12, 7,14,16,11, 4, 7, 6,13,16,15,13,12,20,21,20,21,17,18,26,14, 0,13,23,21,11,
|
|
|
|
9,12,18,11,15,21,13, 8,13,13,10, 7,13, 8, 8,19,13, 7, 4,15,19,18,14,12,14,15, 8, 6,16,22,22,15,
|
|
|
|
9,17,14,19,15,14,15, 9,11, 9, 6, 8,14,13,13,12, 5, 0, 0, 6,12,13, 7, 7, 9, 7, 0,12,21,16,15,18,
|
|
|
|
15,16,18,11, 6, 8,15, 9, 2, 0, 5,10,10,16, 9, 0, 4,12,15, 9,12, 9, 7, 7,12, 7, 0, 6,12, 6, 9,13,
|
|
|
|
12,19,15,14,11, 7, 8, 9,12,10, 5, 5, 7,12,12,10,14,16,16,11, 8,12,10,12,10, 8,10,10,14,12,16,16,
|
|
|
|
16,17,20,22,12,15,12,14,19,11, 6, 5,10,13,17,17,21,19,15, 9, 6, 9,15,18,10,10,18,14,20,15,16,17,
|
|
|
|
11,19,19,18,19,14,17,13,12,12, 7,11,18,17,16,15,19,19,10, 2, 0, 8,15,12, 8,11,12,10,19,20,19,19,
|
|
|
|
6,14,18,13,13,16,16,12, 5, 8,10,12,10,13,18,12, 9,10, 7, 6, 5,11, 8, 6, 7,13,16,13,10,15,20,14,
|
|
|
|
0, 5,12,12, 4, 0, 9,16, 9,10,12, 8, 0, 9,13, 9, 0, 2, 4, 7,10, 6, 7, 3, 4,11,16,18,10,11,21,21,
|
|
|
|
16,13,11,15, 8, 0, 5, 9, 8, 7, 6, 3, 0, 9,17, 9, 0, 0, 0, 3, 5, 4, 3, 5, 7,15,16,16,17,14,22,22,
|
|
|
|
24,14,15,12, 9, 0, 5,10, 8, 4, 7,12,10,11,12, 7, 6, 8, 6, 5, 7, 8, 8,11,13,10,15,14,12,18,20,16,
|
|
|
|
16,17,17,18,12, 9,12,16,10, 5, 6,20,13,15, 8, 4, 8, 9, 8, 7, 9,11,12,17,16,16,11,10, 9,10, 5, 0,
|
|
|
|
0,14,18,18,15,16,14, 9,10, 9, 9,15,14,10, 4, 6,10, 8, 8, 7,10, 9,10,16,18,10, 0, 0, 7,12,10, 8,
|
|
|
|
0,14,19,14, 9,11,11, 8, 8,10,15, 9,10, 7, 4,10,13, 9, 7, 5, 5, 7, 7, 7,13,13, 5, 5,14,22,18,16,
|
|
|
|
0,10,14,10, 3, 6, 5, 6, 8, 9, 8, 9, 5, 9, 8, 9, 6, 8, 8, 8, 1, 0, 0, 0, 9,17,12,12,17,19,20,13,
|
|
|
|
6,11,17,11, 5, 5, 8,10, 6, 5, 6, 6, 3, 7, 9, 7, 6, 8,12,10, 4, 8, 6, 6,11,16,16,15,16,17,17,16,
|
|
|
|
11, 9,10,10, 5, 6,12,10, 5, 1, 6,10, 5, 3, 3, 5, 4, 7,15,10, 7,13, 7, 8,15,11,15,15,15, 8,11,15,
|
2006-02-24 04:48:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Just a 32x32 cloud rendered with the standard Photoshop filter
|
2007-12-27 04:30:12 +00:00
|
|
|
static BYTE pattern2[1024] =
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
9, 9, 8, 8, 8, 8, 6, 6,13,13,11,21,19,21,23,18,23,24,19,19,24,17,18,12, 9,14, 8,12,12, 5, 8, 6,
|
|
|
|
11,10, 6, 7, 8, 8, 9,13,10,11,17,15,23,22,23,22,20,26,27,26,17,21,20,14,12, 8,11, 8,11, 7, 8, 7,
|
|
|
|
6, 9,13,13,10, 9,13, 7,12,13,16,19,16,20,22,25,22,25,27,22,21,23,15,10,14,14,15,13,12, 8,12, 6,
|
|
|
|
6, 7,12,12,12,16, 9,12,12,15,16,11,21,24,19,24,23,26,28,27,26,21,14,15, 7, 7,10,15,12,11,10, 9,
|
|
|
|
7,14,11,16,12,18,16,14,16,14,11,14,15,21,23,17,20,18,26,24,27,18,20,11,11,14,10,17,17,10, 6,10,
|
|
|
|
13, 9,14,10,13,11,14,15,18,15,15,12,19,19,20,18,22,20,19,22,19,19,19,20,17,15,15,11,16,14,10, 8,
|
|
|
|
13,16,12,16,17,19,17,18,15,19,14,18,15,14,15,17,21,19,23,18,23,22,18,18,17,15,15,16,12,12,15,10,
|
|
|
|
10,12,14,10,16,11,18,15,21,20,20,17,18,19,16,19,14,20,19,14,19,25,22,21,22,24,18,12, 9, 9, 8, 6,
|
|
|
|
10,10,13, 9,15,13,20,19,22,18,18,17,17,21,21,13,13,12,19,18,16,17,27,26,22,23,20,17,12,11, 8, 9,
|
|
|
|
7,13,14,15,11,13,18,22,19,23,23,20,22,24,21,14,12,16,17,19,18,18,22,18,24,23,19,17,16,14, 8, 7,
|
|
|
|
12,12, 8, 8,16,20,26,25,28,28,22,29,23,22,21,18,13,16,15,15,20,17,25,24,19,17,17,17,15,10, 8, 9,
|
|
|
|
7,12,15,11,17,20,25,25,25,29,30,31,28,26,18,16,17,18,20,21,22,20,23,19,18,19,10,16,16,11,11, 8,
|
|
|
|
5, 6, 8,14,14,17,17,21,27,23,27,31,27,22,23,21,19,19,21,19,20,19,17,22,13,17,12,15,10,10,12, 6,
|
|
|
|
8, 9, 8,14,15,16,15,18,27,26,23,25,23,22,18,21,20,17,19,20,20,16,20,14,15,13,12, 8, 8, 7,11,13,
|
|
|
|
7, 6,11,11,11,13,15,22,25,24,26,22,24,26,23,18,24,24,20,18,20,16,17,12,12,12,10, 8,11, 9, 6, 8,
|
|
|
|
9,10, 9, 6, 5,14,16,19,17,21,26,20,23,19,19,17,20,21,26,25,23,21,17,13,12, 5,13,11, 7,12,10,12,
|
|
|
|
6, 5, 4,10,11, 9,10,13,17,20,20,18,23,26,27,20,21,24,20,19,24,20,18,10,11, 3, 6,13, 9, 6, 8, 8,
|
|
|
|
1, 2, 2,11,13,13,11,16,16,16,19,21,20,23,22,28,21,20,19,18,23,16,18, 7, 5, 9, 7, 6, 5,10, 8, 8,
|
|
|
|
0, 0, 6, 9,11,15,12,12,19,18,19,26,22,24,26,30,23,22,22,16,20,19,12,12, 3, 4, 6, 5, 4, 7, 2, 4,
|
|
|
|
2, 0, 0, 7,11, 8,14,13,15,21,26,28,25,24,27,26,23,24,22,22,15,17,12, 8,10, 7, 7, 4, 0, 5, 0, 1,
|
|
|
|
1, 2, 0, 1, 9,14,13,10,19,24,22,29,30,28,30,30,31,23,24,19,17,14,13, 8, 8, 8, 1, 4, 0, 0, 0, 3,
|
|
|
|
5, 2, 4, 2, 9, 8, 8, 8,18,23,20,27,30,27,31,25,28,30,28,24,24,15,11,14,10, 3, 4, 3, 0, 0, 1, 3,
|
|
|
|
9, 3, 4, 3, 5, 6, 8,13,14,23,21,27,28,27,28,27,27,29,30,24,22,23,13,15, 8, 6, 2, 0, 4, 3, 4, 1,
|
|
|
|
6, 5, 5, 3, 9, 3, 6,14,13,16,23,26,28,23,30,31,28,29,26,27,21,20,15,15,13, 9, 1, 0, 2, 0, 5, 8,
|
|
|
|
8, 4, 3, 7, 2, 0,10, 7,10,14,21,21,29,28,25,27,30,28,25,24,27,22,19,13,10, 5, 0, 0, 0, 0, 0, 7,
|
|
|
|
7, 6, 7, 0, 2, 2, 5, 6,15,11,19,24,22,29,27,31,30,30,31,28,23,18,14,14, 7, 5, 0, 0, 1, 0, 1, 0,
|
|
|
|
5, 5, 5, 0, 0, 4, 5,11, 7,10,13,20,21,21,28,31,28,30,26,28,25,21, 9,12, 3, 3, 0, 2, 2, 2, 0, 1,
|
|
|
|
3, 3, 0, 2, 0, 3, 5, 3,11,11,16,19,19,27,26,26,30,27,28,26,23,22,16, 6, 2, 2, 3, 2, 0, 2, 4, 0,
|
|
|
|
0, 0, 0, 3, 3, 1, 0, 4, 5, 9,11,16,24,20,28,26,28,24,28,25,22,21,16, 5, 7, 5, 7, 3, 2, 3, 3, 6,
|
|
|
|
0, 0, 2, 0, 2, 0, 4, 3, 8,12, 9,17,16,23,23,27,27,22,26,22,21,21,13,14, 5, 3, 7, 3, 2, 4, 6, 1,
|
|
|
|
2, 5, 6, 4, 0, 1, 5, 8, 7, 6,15,17,22,20,24,28,23,25,20,21,18,16,13,15,13,10, 8, 5, 5, 9, 3, 7,
|
|
|
|
7, 7, 0, 5, 1, 6, 7, 9,12, 9,12,21,22,25,24,22,23,25,24,18,24,22,17,13,10, 9,10, 9, 6,11, 6, 5,
|
|
|
|
};
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
const FTexture::Span FBackdropTexture::DummySpan[2] = { { 0, 160 }, { 0, 0 } };
|
|
|
|
|
|
|
|
FBackdropTexture::FBackdropTexture()
|
|
|
|
{
|
|
|
|
Width = 144;
|
|
|
|
Height = 160;
|
|
|
|
WidthBits = 8;
|
|
|
|
HeightBits = 8;
|
|
|
|
WidthMask = 255;
|
|
|
|
LastRenderTic = 0;
|
|
|
|
|
|
|
|
time1 = ANGLE_1*180;
|
|
|
|
time2 = ANGLE_1*56;
|
|
|
|
time3 = ANGLE_1*99;
|
|
|
|
time4 = ANGLE_1*1;
|
|
|
|
t1ang = ANGLE_90;
|
|
|
|
t2ang = 0;
|
|
|
|
z1ang = 0;
|
|
|
|
z2ang = ANGLE_90/2;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FBackdropTexture::CheckModified()
|
|
|
|
{
|
|
|
|
return LastRenderTic != gametic;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FBackdropTexture::Unload()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const BYTE *FBackdropTexture::GetColumn(unsigned int column, const Span **spans_out)
|
|
|
|
{
|
|
|
|
if (LastRenderTic != gametic)
|
|
|
|
{
|
|
|
|
Render();
|
|
|
|
}
|
|
|
|
column = clamp(column, 0u, 143u);
|
|
|
|
if (spans_out != NULL)
|
|
|
|
{
|
|
|
|
*spans_out = DummySpan;
|
|
|
|
}
|
|
|
|
return Pixels + column*160;
|
|
|
|
}
|
|
|
|
|
|
|
|
const BYTE *FBackdropTexture::GetPixels()
|
|
|
|
{
|
|
|
|
if (LastRenderTic != gametic)
|
|
|
|
{
|
|
|
|
Render();
|
|
|
|
}
|
|
|
|
return Pixels;
|
|
|
|
}
|
|
|
|
|
2007-12-15 03:27:40 +00:00
|
|
|
// This is one plasma and two rotozoomers. I think it turned out quite awesome.
|
2007-12-27 04:30:12 +00:00
|
|
|
void FBackdropTexture::Render()
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-09-14 00:02:31 +00:00
|
|
|
BYTE *from;
|
2006-02-24 04:48:15 +00:00
|
|
|
int width, height, pitch;
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
width = 160;
|
|
|
|
height = 144;
|
|
|
|
pitch = width;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
int x, y;
|
|
|
|
|
|
|
|
const angle_t a1add = ANGLE_1/2;
|
|
|
|
const angle_t a2add = ANGLE_MAX-ANGLE_1;
|
|
|
|
const angle_t a3add = ANGLE_1*5/7;
|
|
|
|
const angle_t a4add = ANGLE_MAX-ANGLE_1*4/3;
|
|
|
|
|
|
|
|
const angle_t t1add = ANGLE_MAX-ANGLE_1*2;
|
|
|
|
const angle_t t2add = ANGLE_MAX-ANGLE_1*3+ANGLE_1/6;
|
|
|
|
const angle_t t3add = ANGLE_1*16/7;
|
|
|
|
const angle_t t4add = ANGLE_MAX-ANGLE_1*2/3;
|
|
|
|
const angle_t x1add = 5<<ANGLETOFINESHIFT;
|
|
|
|
const angle_t x2add = ANGLE_MAX-(13<<ANGLETOFINESHIFT);
|
|
|
|
const angle_t z1add = 3<<ANGLETOFINESHIFT;
|
|
|
|
const angle_t z2add = 4<<ANGLETOFINESHIFT;
|
|
|
|
|
|
|
|
angle_t a1, a2, a3, a4;
|
|
|
|
fixed_t c1, c2, c3, c4;
|
|
|
|
DWORD tx, ty, tc, ts;
|
|
|
|
DWORD ux, uy, uc, us;
|
|
|
|
DWORD ltx, lty, lux, luy;
|
|
|
|
|
2007-12-27 04:30:12 +00:00
|
|
|
from = Pixels;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
a3 = time3;
|
|
|
|
a4 = time4;
|
|
|
|
|
|
|
|
fixed_t z1 = (finecosine[z2ang>>ANGLETOFINESHIFT]>>2)+FRACUNIT/2;
|
|
|
|
fixed_t z2 = (finecosine[z1ang>>ANGLETOFINESHIFT]>>2)+FRACUNIT*3/4;
|
|
|
|
|
|
|
|
tc = MulScale5 (finecosine[t1ang>>ANGLETOFINESHIFT], z1);
|
|
|
|
ts = MulScale5 (finesine[t1ang>>ANGLETOFINESHIFT], z1);
|
|
|
|
uc = MulScale5 (finecosine[t2ang>>ANGLETOFINESHIFT], z2);
|
|
|
|
us = MulScale5 (finesine[t2ang>>ANGLETOFINESHIFT], z2);
|
|
|
|
|
|
|
|
ltx = -width/2*tc;
|
|
|
|
lty = -width/2*ts;
|
|
|
|
lux = -width/2*uc;
|
|
|
|
luy = -width/2*us;
|
|
|
|
|
|
|
|
for (y = 0; y < height; ++y)
|
|
|
|
{
|
|
|
|
a1 = time1;
|
|
|
|
a2 = time2;
|
|
|
|
c3 = finecosine[a3>>ANGLETOFINESHIFT];
|
|
|
|
c4 = finecosine[a4>>ANGLETOFINESHIFT];
|
|
|
|
tx = ltx - (y-height/2)*ts;
|
|
|
|
ty = lty + (y-height/2)*tc;
|
|
|
|
ux = lux - (y-height/2)*us;
|
|
|
|
uy = luy + (y-height/2)*uc;
|
|
|
|
for (x = 0; x < width; ++x)
|
|
|
|
{
|
|
|
|
c1 = finecosine[a1>>ANGLETOFINESHIFT];
|
|
|
|
c2 = finecosine[a2>>ANGLETOFINESHIFT];
|
|
|
|
from[x] = ((c1 + c2 + c3 + c4) >> (FRACBITS+3-7)) + 128 // plasma
|
2007-12-27 04:30:12 +00:00
|
|
|
+ pattern1[(tx>>27)+((ty>>22)&992)] // rotozoomer 1
|
|
|
|
+ pattern2[(ux>>27)+((uy>>22)&992)]; // rotozoomer 2
|
2006-02-24 04:48:15 +00:00
|
|
|
tx += tc;
|
|
|
|
ty += ts;
|
|
|
|
ux += uc;
|
|
|
|
uy += us;
|
|
|
|
a1 += a1add;
|
|
|
|
a2 += a2add;
|
|
|
|
}
|
|
|
|
a3 += a3add;
|
|
|
|
a4 += a4add;
|
|
|
|
from += pitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
time1 += t1add;
|
|
|
|
time2 += t2add;
|
|
|
|
time3 += t3add;
|
|
|
|
time4 += t4add;
|
|
|
|
t1ang += x1add;
|
|
|
|
t2ang += x2add;
|
|
|
|
z1ang += z1add;
|
|
|
|
z2ang += z2add;
|
2007-12-27 04:30:12 +00:00
|
|
|
|
|
|
|
LastRenderTic = gametic;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
static void M_ChangeClass (int choice)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
if (PlayerClasses.Size () == 1)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int type = players[consoleplayer].userinfo.PlayerClass;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (!choice)
|
2006-07-13 10:17:56 +00:00
|
|
|
type = (type < 0) ? (int)PlayerClasses.Size () - 1 : type - 1;
|
2006-02-24 04:48:15 +00:00
|
|
|
else
|
2006-07-13 10:17:56 +00:00
|
|
|
type = (type < (int)PlayerClasses.Size () - 1) ? type + 1 : -1;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
cvar_set ("playerclass", type < 0 ? "Random" :
|
|
|
|
PlayerClasses[type].Type->Meta.GetMetaString (APMETA_DisplayName));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void M_ChangeSkin (int choice)
|
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN ||
|
|
|
|
players[consoleplayer].userinfo.PlayerClass == -1)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
return;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
do
|
|
|
|
{
|
2006-02-24 04:48:15 +00:00
|
|
|
if (!choice)
|
2006-07-13 10:17:56 +00:00
|
|
|
PlayerSkin = (PlayerSkin == 0) ? (int)numskins - 1 : PlayerSkin - 1;
|
2006-02-24 04:48:15 +00:00
|
|
|
else
|
2006-07-13 10:17:56 +00:00
|
|
|
PlayerSkin = (PlayerSkin < (int)numskins - 1) ? PlayerSkin + 1 : 0;
|
|
|
|
} while (!PlayerClass->CheckSkin (PlayerSkin));
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
R_GetPlayerTranslation (players[consoleplayer].userinfo.color,
|
|
|
|
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
|
|
|
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
cvar_set ("skin", skins[PlayerSkin].name);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
static void M_ChangeGender (int choice)
|
|
|
|
{
|
|
|
|
int gender = players[consoleplayer].userinfo.gender;
|
|
|
|
|
|
|
|
if (!choice)
|
|
|
|
gender = (gender == 0) ? 2 : gender - 1;
|
|
|
|
else
|
|
|
|
gender = (gender == 2) ? 0 : gender + 1;
|
|
|
|
|
|
|
|
cvar_set ("gender", genders[gender]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void M_ChangeAutoAim (int choice)
|
|
|
|
{
|
|
|
|
static const float ranges[] = { 0, 0.25, 0.5, 1, 2, 3, 5000 };
|
|
|
|
float aim = autoaim;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!choice) {
|
|
|
|
// Select a lower autoaim
|
|
|
|
|
|
|
|
for (i = 6; i >= 1; i--)
|
|
|
|
{
|
|
|
|
if (aim >= ranges[i])
|
|
|
|
{
|
|
|
|
aim = ranges[i - 1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Select a higher autoaim
|
|
|
|
|
|
|
|
for (i = 5; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if (aim >= ranges[i])
|
|
|
|
{
|
|
|
|
aim = ranges[i + 1];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
autoaim = aim;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_EditPlayerName (int choice)
|
|
|
|
{
|
|
|
|
// we are going to be intercepting all chars
|
2006-04-11 16:27:41 +00:00
|
|
|
genStringEnter = 2;
|
2006-02-24 04:48:15 +00:00
|
|
|
genStringEnd = M_PlayerNameChanged;
|
2007-02-28 16:49:19 +00:00
|
|
|
genStringCancel = M_PlayerNameNotChanged;
|
2006-02-24 04:48:15 +00:00
|
|
|
genStringLen = MAXPLAYERNAME;
|
|
|
|
|
|
|
|
saveSlot = 0;
|
|
|
|
saveCharIndex = strlen (savegamestring);
|
|
|
|
}
|
|
|
|
|
2007-02-28 16:49:19 +00:00
|
|
|
static void M_PlayerNameNotChanged ()
|
|
|
|
{
|
|
|
|
strcpy (savegamestring, name);
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_PlayerNameChanged (FSaveGameNode *dummy)
|
|
|
|
{
|
2007-12-15 03:27:40 +00:00
|
|
|
const char *p;
|
|
|
|
FString command("name \"");
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2007-12-15 03:27:40 +00:00
|
|
|
// Escape any backslashes or quotation marks before sending the name to the console.
|
|
|
|
for (p = savegamestring; *p != '\0'; ++p)
|
|
|
|
{
|
|
|
|
if (*p == '"' || *p == '\\')
|
|
|
|
{
|
|
|
|
command << '\\';
|
|
|
|
}
|
|
|
|
command << *p;
|
|
|
|
}
|
|
|
|
command << '"';
|
2006-02-24 04:48:15 +00:00
|
|
|
C_DoCommand (command);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_ChangePlayerTeam (int choice)
|
|
|
|
{
|
|
|
|
if (!choice)
|
|
|
|
{
|
|
|
|
if (team == 0)
|
|
|
|
{
|
2009-02-04 23:14:28 +00:00
|
|
|
team = TEAM_NONE;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-02-04 23:14:28 +00:00
|
|
|
else if (team == TEAM_NONE)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-02-04 23:14:28 +00:00
|
|
|
team = Teams.Size () - 1;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
team = team - 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-04 23:14:28 +00:00
|
|
|
if (team == int(Teams.Size () - 1))
|
2008-01-06 10:05:24 +00:00
|
|
|
{
|
2009-02-04 23:14:28 +00:00
|
|
|
team = TEAM_NONE;
|
2008-01-06 10:05:24 +00:00
|
|
|
}
|
2009-02-04 23:14:28 +00:00
|
|
|
else if (team == TEAM_NONE)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
team = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
team = team + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
static void M_ChangeColorSet (int choice)
|
|
|
|
{
|
|
|
|
int curpos = (int)PlayerColorSets.Size();
|
|
|
|
int mycolorset = players[consoleplayer].userinfo.colorset;
|
|
|
|
while (--curpos >= 0)
|
|
|
|
{
|
|
|
|
if (PlayerColorSets[curpos] == mycolorset)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (choice == 0)
|
|
|
|
{
|
|
|
|
curpos--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
curpos++;
|
|
|
|
}
|
|
|
|
if (curpos < -1)
|
|
|
|
{
|
|
|
|
curpos = (int)PlayerColorSets.Size() - 1;
|
|
|
|
}
|
|
|
|
else if (curpos >= (int)PlayerColorSets.Size())
|
|
|
|
{
|
|
|
|
curpos = -1;
|
|
|
|
}
|
|
|
|
mycolorset = (curpos >= 0) ? PlayerColorSets[curpos] : -1;
|
|
|
|
|
2010-03-07 11:05:52 +00:00
|
|
|
// disable the sliders if a valid colorset is selected
|
|
|
|
PlayerSetupMenu[PSM_RED].status =
|
|
|
|
PlayerSetupMenu[PSM_GREEN].status =
|
|
|
|
PlayerSetupMenu[PSM_BLUE].status = (mycolorset == -1? 2:-1);
|
|
|
|
|
2010-03-06 02:51:23 +00:00
|
|
|
char command[24];
|
|
|
|
mysnprintf(command, countof(command), "colorset %d", mycolorset);
|
|
|
|
C_DoCommand(command);
|
|
|
|
R_GetPlayerTranslation(players[consoleplayer].userinfo.color,
|
|
|
|
P_GetPlayerColorSet(PlayerClass->Type->TypeName, mycolorset),
|
|
|
|
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
static void SendNewColor (int red, int green, int blue)
|
|
|
|
{
|
|
|
|
char command[24];
|
|
|
|
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
mysnprintf (command, countof(command), "color \"%02x %02x %02x\"", red, green, blue);
|
2006-02-24 04:48:15 +00:00
|
|
|
C_DoCommand (command);
|
2010-03-06 02:51:23 +00:00
|
|
|
R_GetPlayerTranslation(MAKERGB (red, green, blue),
|
|
|
|
P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset),
|
|
|
|
&skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void M_SlidePlayerRed (int choice)
|
|
|
|
{
|
|
|
|
int color = players[consoleplayer].userinfo.color;
|
|
|
|
int red = RPART(color);
|
|
|
|
|
|
|
|
if (choice == 0) {
|
|
|
|
red -= 16;
|
|
|
|
if (red < 0)
|
|
|
|
red = 0;
|
|
|
|
} else {
|
|
|
|
red += 16;
|
|
|
|
if (red > 255)
|
|
|
|
red = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendNewColor (red, GPART(color), BPART(color));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_SlidePlayerGreen (int choice)
|
|
|
|
{
|
|
|
|
int color = players[consoleplayer].userinfo.color;
|
|
|
|
int green = GPART(color);
|
|
|
|
|
|
|
|
if (choice == 0) {
|
|
|
|
green -= 16;
|
|
|
|
if (green < 0)
|
|
|
|
green = 0;
|
|
|
|
} else {
|
|
|
|
green += 16;
|
|
|
|
if (green > 255)
|
|
|
|
green = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendNewColor (RPART(color), green, BPART(color));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_SlidePlayerBlue (int choice)
|
|
|
|
{
|
|
|
|
int color = players[consoleplayer].userinfo.color;
|
|
|
|
int blue = BPART(color);
|
|
|
|
|
|
|
|
if (choice == 0) {
|
|
|
|
blue -= 16;
|
|
|
|
if (blue < 0)
|
|
|
|
blue = 0;
|
|
|
|
} else {
|
|
|
|
blue += 16;
|
|
|
|
if (blue > 255)
|
|
|
|
blue = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendNewColor (RPART(color), GPART(color), blue);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Menu Functions
|
|
|
|
//
|
2009-08-07 03:30:51 +00:00
|
|
|
void M_StartMessage (const char *string, void (*routine)(int))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
C_HideConsole ();
|
|
|
|
messageLastMenuActive = menuactive;
|
|
|
|
messageToPrint = 1;
|
|
|
|
messageString = string;
|
|
|
|
messageRoutine = routine;
|
2009-08-07 03:30:51 +00:00
|
|
|
messageSelection = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
if (menuactive == MENU_Off)
|
|
|
|
{
|
|
|
|
M_ActivateMenuInput ();
|
|
|
|
}
|
2009-08-07 03:30:51 +00:00
|
|
|
if (messageRoutine != NULL)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-07-01 04:06:56 +00:00
|
|
|
S_StopSound (CHAN_VOICE);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/prompt", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-07 03:30:51 +00:00
|
|
|
void M_EndMessage(int key)
|
|
|
|
{
|
|
|
|
menuactive = messageLastMenuActive;
|
|
|
|
messageToPrint = 0;
|
|
|
|
if (messageRoutine != NULL)
|
|
|
|
{
|
|
|
|
messageRoutine(key);
|
|
|
|
}
|
|
|
|
if (menuactive != MENU_Off)
|
|
|
|
{
|
|
|
|
M_DeactivateMenuInput();
|
|
|
|
}
|
|
|
|
SB_state = screen->GetPageCount(); // refresh the status bar
|
|
|
|
BorderNeedRefresh = screen->GetPageCount();
|
|
|
|
S_Sound(CHAN_VOICE | CHAN_UI, "menu/dismiss", 1, ATTN_NONE);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// Find string height from hu_font chars
|
|
|
|
//
|
2008-11-27 17:43:36 +00:00
|
|
|
int M_StringHeight (FFont *font, const char *string)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int h;
|
2008-11-27 17:43:36 +00:00
|
|
|
int height = font->GetHeight ();
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
h = height;
|
|
|
|
while (*string)
|
|
|
|
{
|
|
|
|
if ((*string++) == '\n')
|
|
|
|
h += height;
|
|
|
|
}
|
|
|
|
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// CONTROL PANEL
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_Responder
|
|
|
|
//
|
2006-09-14 00:02:31 +00:00
|
|
|
bool M_Responder (event_t *ev)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
int ch;
|
|
|
|
int i;
|
2009-07-26 03:25:18 +00:00
|
|
|
EMenuKey mkey = NUM_MKEYS;
|
|
|
|
bool keyup = true;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
ch = -1;
|
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
if (chatmodeon)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
if (menuactive == MENU_Off && ev->type == EV_KeyDown)
|
|
|
|
{
|
|
|
|
// Pop-up menu?
|
|
|
|
if (ev->data1 == KEY_ESCAPE)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartControlPanel(true, true);
|
2006-02-24 04:48:15 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// If devparm is set, pressing F1 always takes a screenshot no matter
|
|
|
|
// what it's bound to. (for those who don't bother to read the docs)
|
|
|
|
if (devparm && ev->data1 == KEY_F1)
|
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
G_ScreenShot(NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return true;
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (menuactive == MENU_WaitKey && OptionsActive)
|
|
|
|
{
|
|
|
|
M_OptResponder(ev);
|
|
|
|
return true;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
if (menuactive != MENU_On && menuactive != MENU_OnNoPause &&
|
|
|
|
!genStringEnter && !messageToPrint)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// There are a few input sources we are interested in:
|
|
|
|
//
|
|
|
|
// EV_KeyDown / EV_KeyUp : joysticks/gamepads/controllers
|
|
|
|
// EV_GUI_KeyDown / EV_GUI_KeyUp : the keyboard
|
|
|
|
// EV_GUI_Char : printable characters, which we want in string input mode
|
|
|
|
//
|
|
|
|
// This code previously listened for EV_GUI_KeyRepeat to handle repeating
|
|
|
|
// in the menus, but that doesn't work with gamepads, so now we combine
|
|
|
|
// the multiple inputs into buttons and handle the repetition manually.
|
|
|
|
if (ev->type == EV_GUI_Event)
|
|
|
|
{
|
|
|
|
// Save game and player name string input
|
|
|
|
if (genStringEnter)
|
|
|
|
{
|
|
|
|
if (ev->subtype == EV_GUI_Char)
|
|
|
|
{
|
2010-01-23 19:07:18 +00:00
|
|
|
InputGridOkay = false;
|
2009-07-26 03:25:18 +00:00
|
|
|
if (saveCharIndex < genStringLen &&
|
2010-01-23 19:07:18 +00:00
|
|
|
(genStringEnter == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(savegamestring) < (genStringLen-1)*8))
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
|
|
|
savegamestring[saveCharIndex] = (char)ev->data1;
|
|
|
|
savegamestring[++saveCharIndex] = 0;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2009-08-29 02:19:46 +00:00
|
|
|
ch = ev->data1;
|
2010-01-23 19:07:18 +00:00
|
|
|
if ((ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat) && ch == '\b')
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
2009-08-29 02:19:46 +00:00
|
|
|
if (saveCharIndex > 0)
|
|
|
|
{
|
|
|
|
saveCharIndex--;
|
|
|
|
savegamestring[saveCharIndex] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ev->subtype == EV_GUI_KeyDown)
|
|
|
|
{
|
|
|
|
if (ch == GK_ESCAPE)
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
2009-08-29 02:19:46 +00:00
|
|
|
genStringEnter = 0;
|
|
|
|
genStringCancel(); // [RH] Function to call when escape is pressed
|
|
|
|
}
|
|
|
|
else if (ch == '\r')
|
|
|
|
{
|
|
|
|
if (savegamestring[0])
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
|
|
|
genStringEnter = 0;
|
2009-08-29 02:19:46 +00:00
|
|
|
if (messageToPrint)
|
|
|
|
M_ClearMenus ();
|
|
|
|
genStringEnd (SelSaveGame); // [RH] Function to call when enter is pressed
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-08-29 02:19:46 +00:00
|
|
|
if (ev->subtype == EV_GUI_KeyDown || ev->subtype == EV_GUI_KeyRepeat)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
|
|
|
if (ev->subtype != EV_GUI_KeyDown && ev->subtype != EV_GUI_KeyUp)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
return false;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-08-29 02:19:46 +00:00
|
|
|
if (ev->subtype == EV_GUI_KeyRepeat)
|
|
|
|
{
|
|
|
|
// We do our own key repeat handling but still want to eat the
|
|
|
|
// OS's repeated keys.
|
|
|
|
return true;
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
ch = ev->data1;
|
|
|
|
keyup = ev->subtype == EV_GUI_KeyUp;
|
2009-08-07 03:30:51 +00:00
|
|
|
if (messageToPrint && messageRoutine == NULL)
|
|
|
|
{
|
|
|
|
if (!keyup && !OptionsActive)
|
|
|
|
{
|
|
|
|
D_RemoveNextCharEvent();
|
|
|
|
M_EndMessage(ch);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
switch (ch)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
case GK_ESCAPE: mkey = MKEY_Back; break;
|
|
|
|
case GK_RETURN: mkey = MKEY_Enter; break;
|
|
|
|
case GK_UP: mkey = MKEY_Up; break;
|
|
|
|
case GK_DOWN: mkey = MKEY_Down; break;
|
|
|
|
case GK_LEFT: mkey = MKEY_Left; break;
|
|
|
|
case GK_RIGHT: mkey = MKEY_Right; break;
|
|
|
|
case GK_BACKSPACE: mkey = MKEY_Clear; break;
|
|
|
|
case GK_PGUP: mkey = MKEY_PageUp; break;
|
|
|
|
case GK_PGDN: mkey = MKEY_PageDown; break;
|
|
|
|
default:
|
|
|
|
if (ch == ' ' && currentMenu == &PSetupDef)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
mkey = MKEY_Clear;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2010-01-08 02:10:05 +00:00
|
|
|
else if (!keyup)
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
2010-01-08 02:10:05 +00:00
|
|
|
if (OptionsActive)
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
2010-01-08 02:10:05 +00:00
|
|
|
M_OptResponder(ev);
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-01-08 02:10:05 +00:00
|
|
|
ch = tolower (ch);
|
|
|
|
if (messageToPrint)
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
2010-01-08 02:10:05 +00:00
|
|
|
// Take care of any messages that need input
|
|
|
|
ch = tolower (ch);
|
|
|
|
assert(messageRoutine != NULL);
|
|
|
|
if (ch != ' ' && ch != 'n' && ch != 'y')
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
2010-01-08 02:10:05 +00:00
|
|
|
return false;
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
2010-01-08 02:10:05 +00:00
|
|
|
D_RemoveNextCharEvent();
|
|
|
|
M_EndMessage(ch);
|
|
|
|
return true;
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
2010-01-08 02:10:05 +00:00
|
|
|
else
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
2010-01-08 02:10:05 +00:00
|
|
|
// Search for a menu item associated with the pressed key.
|
|
|
|
for (i = (itemOn + 1) % currentMenu->numitems;
|
|
|
|
i != itemOn;
|
|
|
|
i = (i + 1) % currentMenu->numitems)
|
|
|
|
{
|
|
|
|
if (currentMenu->menuitems[i].alphaKey == ch)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (currentMenu->menuitems[i].alphaKey == ch)
|
|
|
|
{
|
|
|
|
itemOn = i;
|
|
|
|
S_Sound(CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
|
|
|
|
return true;
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-12-09 03:40:02 +00:00
|
|
|
}
|
2010-01-23 19:07:18 +00:00
|
|
|
if (!keyup)
|
|
|
|
{
|
|
|
|
InputGridOkay = false;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
else if (ev->type == EV_KeyDown || ev->type == EV_KeyUp)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
keyup = ev->type == EV_KeyUp;
|
2010-01-23 19:07:18 +00:00
|
|
|
// If this is a button down, it's okay to show the input grid if the
|
|
|
|
// next action causes us to enter genStringEnter mode. If we are
|
|
|
|
// already in that mode, then we let M_ButtonHandler() turn it on so
|
|
|
|
// that it will know if a button press happened while the input grid
|
|
|
|
// was turned off.
|
|
|
|
if (!keyup && !genStringEnter)
|
|
|
|
{
|
|
|
|
InputGridOkay = true;
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
ch = ev->data1;
|
2006-02-24 04:48:15 +00:00
|
|
|
switch (ch)
|
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
case KEY_JOY1:
|
|
|
|
case KEY_PAD_A:
|
|
|
|
mkey = MKEY_Enter;
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
case KEY_JOY2:
|
|
|
|
case KEY_PAD_B:
|
|
|
|
mkey = MKEY_Back;
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
2009-07-26 03:25:18 +00:00
|
|
|
|
|
|
|
case KEY_JOY3:
|
|
|
|
case KEY_PAD_X:
|
|
|
|
mkey = MKEY_Clear;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KEY_JOY5:
|
|
|
|
case KEY_PAD_LSHOULDER:
|
|
|
|
mkey = MKEY_PageUp;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KEY_JOY6:
|
|
|
|
case KEY_PAD_RSHOULDER:
|
|
|
|
mkey = MKEY_PageDown;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KEY_PAD_DPAD_UP:
|
|
|
|
case KEY_PAD_LTHUMB_UP:
|
|
|
|
case KEY_JOYAXIS1MINUS:
|
|
|
|
case KEY_JOYPOV1_UP:
|
|
|
|
mkey = MKEY_Up;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KEY_PAD_DPAD_DOWN:
|
|
|
|
case KEY_PAD_LTHUMB_DOWN:
|
|
|
|
case KEY_JOYAXIS1PLUS:
|
|
|
|
case KEY_JOYPOV1_DOWN:
|
|
|
|
mkey = MKEY_Down;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KEY_PAD_DPAD_LEFT:
|
|
|
|
case KEY_PAD_LTHUMB_LEFT:
|
|
|
|
case KEY_JOYAXIS2MINUS:
|
|
|
|
case KEY_JOYPOV1_LEFT:
|
|
|
|
mkey = MKEY_Left;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KEY_PAD_DPAD_RIGHT:
|
|
|
|
case KEY_PAD_LTHUMB_RIGHT:
|
|
|
|
case KEY_JOYAXIS2PLUS:
|
|
|
|
case KEY_JOYPOV1_RIGHT:
|
|
|
|
mkey = MKEY_Right;
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2009-08-07 03:30:51 +00:00
|
|
|
// Any button press will work for messages without callbacks
|
|
|
|
if (!keyup && messageToPrint && messageRoutine == NULL)
|
|
|
|
{
|
|
|
|
M_EndMessage(ch);
|
|
|
|
return true;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
if (mkey != NUM_MKEYS)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
if (keyup)
|
|
|
|
{
|
|
|
|
MenuButtons[mkey].ReleaseKey(ch);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
MenuButtons[mkey].PressKey(ch);
|
|
|
|
if (mkey <= MKEY_PageDown)
|
2007-12-09 03:40:02 +00:00
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
MenuButtonTickers[mkey] = KEY_REPEAT_DELAY;
|
2007-12-09 03:40:02 +00:00
|
|
|
}
|
2009-08-07 03:30:51 +00:00
|
|
|
M_ButtonHandler(mkey, false);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
if (ev->type == EV_GUI_Event && (currentMenu == &SaveDef || currentMenu == &LoadDef))
|
|
|
|
{
|
|
|
|
return M_SaveLoadResponder (ev);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
// Eat key downs, but let the rest through.
|
|
|
|
return !keyup;
|
|
|
|
}
|
|
|
|
|
|
|
|
void M_ButtonHandler(EMenuKey key, bool repeat)
|
|
|
|
{
|
|
|
|
if (OptionsActive)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
M_OptButtonHandler(key, repeat);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (key == MKEY_Back)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
if (genStringEnter)
|
|
|
|
{
|
|
|
|
// Cancel string entry.
|
|
|
|
genStringEnter = 0;
|
|
|
|
genStringCancel();
|
|
|
|
}
|
|
|
|
else if (messageToPrint)
|
|
|
|
{
|
|
|
|
M_EndMessage(GK_ESCAPE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Save the cursor position on the current menu, and pop it off the stack
|
|
|
|
// to go back to the previous menu.
|
|
|
|
currentMenu->lastOn = itemOn;
|
|
|
|
M_PopMenuStack();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (messageToPrint)
|
|
|
|
{
|
|
|
|
if (key == MKEY_Down || key == MKEY_Up)
|
|
|
|
{
|
|
|
|
messageSelection ^= 1;
|
|
|
|
}
|
|
|
|
else if (key == MKEY_Enter)
|
|
|
|
{
|
|
|
|
M_EndMessage(messageSelection == 0 ? 'y' : 'n');
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
return;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2010-01-23 19:07:18 +00:00
|
|
|
if (genStringEnter)
|
|
|
|
{
|
|
|
|
int ch;
|
|
|
|
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
case MKEY_Down:
|
|
|
|
InputGridY = (InputGridY + 1) % INPUTGRID_HEIGHT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MKEY_Up:
|
|
|
|
InputGridY = (InputGridY + INPUTGRID_HEIGHT - 1) % INPUTGRID_HEIGHT;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MKEY_Right:
|
|
|
|
InputGridX = (InputGridX + 1) % INPUTGRID_WIDTH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MKEY_Left:
|
|
|
|
InputGridX = (InputGridX + INPUTGRID_WIDTH - 1) % INPUTGRID_WIDTH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MKEY_Clear:
|
|
|
|
if (saveCharIndex > 0)
|
|
|
|
{
|
|
|
|
savegamestring[--saveCharIndex] = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MKEY_Enter:
|
|
|
|
assert(unsigned(InputGridX) < INPUTGRID_WIDTH && unsigned(InputGridY) < INPUTGRID_HEIGHT);
|
|
|
|
if (InputGridOkay)
|
|
|
|
{
|
|
|
|
ch = InputGridChars[InputGridX + InputGridY * INPUTGRID_WIDTH];
|
|
|
|
if (ch == 0) // end
|
|
|
|
{
|
|
|
|
if (savegamestring[0] != '\0')
|
|
|
|
{
|
|
|
|
genStringEnter = 0;
|
|
|
|
if (messageToPrint)
|
|
|
|
{
|
|
|
|
M_ClearMenus();
|
|
|
|
}
|
|
|
|
genStringEnd(SelSaveGame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (ch == '\b') // bs
|
|
|
|
{
|
|
|
|
if (saveCharIndex > 0)
|
|
|
|
{
|
|
|
|
savegamestring[--saveCharIndex] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (saveCharIndex < genStringLen &&
|
|
|
|
(genStringEnter == 2/*entering player name*/ || (size_t)SmallFont->StringWidth(savegamestring) < (genStringLen-1)*8))
|
|
|
|
{
|
|
|
|
savegamestring[saveCharIndex] = ch;
|
|
|
|
savegamestring[++saveCharIndex] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break; // Keep GCC quiet
|
|
|
|
}
|
|
|
|
InputGridOkay = true;
|
|
|
|
return;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
if (currentMenu == &SaveDef || currentMenu == &LoadDef)
|
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
M_SaveLoadButtonHandler(key);
|
|
|
|
return;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
switch (key)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
case MKEY_Down:
|
2006-02-24 04:48:15 +00:00
|
|
|
do
|
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
if (itemOn + 1 >= currentMenu->numitems)
|
2006-02-24 04:48:15 +00:00
|
|
|
itemOn = 0;
|
|
|
|
else itemOn++;
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
|
2009-07-26 03:25:18 +00:00
|
|
|
} while (currentMenu->menuitems[itemOn].status == -1);
|
|
|
|
break;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
case MKEY_Up:
|
2006-02-24 04:48:15 +00:00
|
|
|
do
|
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
if (itemOn == 0)
|
|
|
|
itemOn = currentMenu->numitems - 1;
|
2006-02-24 04:48:15 +00:00
|
|
|
else itemOn--;
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/cursor", 1, ATTN_NONE);
|
2009-07-26 03:25:18 +00:00
|
|
|
} while (currentMenu->menuitems[itemOn].status == -1);
|
|
|
|
break;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
case MKEY_Left:
|
2006-02-24 04:48:15 +00:00
|
|
|
if (currentMenu->menuitems[itemOn].routine &&
|
|
|
|
currentMenu->menuitems[itemOn].status == 2)
|
|
|
|
{
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
currentMenu->menuitems[itemOn].routine(0);
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
break;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
case MKEY_Right:
|
2006-02-24 04:48:15 +00:00
|
|
|
if (currentMenu->menuitems[itemOn].routine &&
|
|
|
|
currentMenu->menuitems[itemOn].status == 2)
|
|
|
|
{
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
currentMenu->menuitems[itemOn].routine(1);
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
break;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
case MKEY_Enter:
|
2006-02-24 04:48:15 +00:00
|
|
|
if (currentMenu->menuitems[itemOn].routine &&
|
|
|
|
currentMenu->menuitems[itemOn].status)
|
|
|
|
{
|
|
|
|
currentMenu->lastOn = itemOn;
|
|
|
|
if (currentMenu->menuitems[itemOn].status == 2)
|
|
|
|
{
|
|
|
|
currentMenu->menuitems[itemOn].routine(1); // right arrow
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/change", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
currentMenu->menuitems[itemOn].routine(itemOn);
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/choose", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
break;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
case MKEY_Clear:
|
2006-02-24 04:48:15 +00:00
|
|
|
if (currentMenu == &PSetupDef)
|
|
|
|
{
|
|
|
|
PlayerRotation ^= 8;
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
break;
|
2009-08-02 03:38:57 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break; // Keep GCC quiet
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
static void M_SaveLoadButtonHandler(EMenuKey key)
|
|
|
|
{
|
|
|
|
if (SelSaveGame == NULL || SelSaveGame->Succ == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (key)
|
|
|
|
{
|
|
|
|
case MKEY_Up:
|
|
|
|
if (SelSaveGame != SaveGames.Head)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
if (SelSaveGame == TopSaveGame)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
TopSaveGame = static_cast<FSaveGameNode *>(TopSaveGame->Pred);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Pred);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.TailPred);
|
|
|
|
}
|
|
|
|
M_UnloadSaveData ();
|
|
|
|
M_ExtractSaveData (SelSaveGame);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MKEY_Down:
|
|
|
|
if (SelSaveGame != SaveGames.TailPred)
|
|
|
|
{
|
|
|
|
SelSaveGame = static_cast<FSaveGameNode *>(SelSaveGame->Succ);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SelSaveGame = TopSaveGame =
|
|
|
|
static_cast<FSaveGameNode *>(SaveGames.Head);
|
|
|
|
}
|
|
|
|
M_UnloadSaveData ();
|
|
|
|
M_ExtractSaveData (SelSaveGame);
|
2006-02-24 04:48:15 +00:00
|
|
|
break;
|
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
case MKEY_Enter:
|
|
|
|
if (currentMenu == &LoadDef)
|
|
|
|
{
|
|
|
|
M_LoadSelect (SelSaveGame);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
M_SaveSelect (SelSaveGame);
|
|
|
|
}
|
|
|
|
break;
|
2009-08-02 03:38:57 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break; // Keep GCC quiet
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2009-07-26 03:25:18 +00:00
|
|
|
static bool M_SaveLoadResponder (event_t *ev)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
if (ev->subtype != EV_GUI_KeyDown)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
if (SelSaveGame != NULL && SelSaveGame->Succ != NULL)
|
|
|
|
{
|
|
|
|
switch (ev->data1)
|
|
|
|
{
|
|
|
|
case GK_F1:
|
|
|
|
if (!SelSaveGame->Filename.IsEmpty())
|
|
|
|
{
|
2009-07-26 03:25:18 +00:00
|
|
|
char workbuf[512];
|
|
|
|
|
About a week's worth of changes here. As a heads-up, I wouldn't be
surprised if this doesn't build in Linux right now. The CMakeLists.txt
were checked with MinGW and NMake, but how they fair under Linux is an
unknown to me at this time.
- Converted most sprintf (and all wsprintf) calls to either mysnprintf or
FStrings, depending on the situation.
- Changed the strings in the wbstartstruct to be FStrings.
- Changed myvsnprintf() to output nothing if count is greater than INT_MAX.
This is so that I can use a series of mysnprintf() calls and advance the
pointer for each one. Once the pointer goes beyond the end of the buffer,
the count will go negative, but since it's an unsigned type it will be
seen as excessively huge instead. This should not be a problem, as there's
no reason for ZDoom to be using text buffers larger than 2 GB anywhere.
- Ripped out the disabled bit from FGameConfigFile::MigrateOldConfig().
- Changed CalcMapName() to return an FString instead of a pointer to a static
buffer.
- Changed startmap in d_main.cpp into an FString.
- Changed CheckWarpTransMap() to take an FString& as the first argument.
- Changed d_mapname in g_level.cpp into an FString.
- Changed DoSubstitution() in ct_chat.cpp to place the substitutions in an
FString.
- Fixed: The MAPINFO parser wrote into the string buffer to construct a map
name when given a Hexen map number. This was fine with the old scanner
code, but only a happy coincidence prevents it from crashing with the new
code
- Added the 'B' conversion specifier to StringFormat::VWorker() for printing
binary numbers.
- Added CMake support for building with MinGW, MSYS, and NMake. Linux support
is probably broken until I get around to booting into Linux again. Niceties
provided over the existing Makefiles they're replacing:
* All command-line builds can use the same build system, rather than having
a separate one for MinGW and another for Linux.
* Microsoft's NMake tool is supported as a target.
* Progress meters.
* Parallel makes work from a fresh checkout without needing to be primed
first with a single-threaded make.
* Porting to other architectures should be simplified, whenever that day
comes.
- Replaced the makewad tool with zipdir. This handles the dependency tracking
itself instead of generating an external makefile to do it, since I couldn't
figure out how to generate a makefile with an external tool and include it
with a CMake-generated makefile. Where makewad used a master list of files
to generate the package file, zipdir just zips the entire contents of one or
more directories.
- Added the gdtoa package from netlib's fp library so that ZDoom's printf-style
formatting can be entirely independant of the CRT.
SVN r1082 (trunk)
2008-07-23 04:57:26 +00:00
|
|
|
mysnprintf (workbuf, countof(workbuf), "File on disk:\n%s", SelSaveGame->Filename.GetChars());
|
2006-02-24 04:48:15 +00:00
|
|
|
if (SaveComment != NULL)
|
|
|
|
{
|
|
|
|
V_FreeBrokenLines (SaveComment);
|
|
|
|
}
|
2008-11-27 17:43:36 +00:00
|
|
|
SaveComment = V_BreakLines (SmallFont, 216*screen->GetWidth()/640/CleanXfac, workbuf);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GK_DEL:
|
|
|
|
case '\b':
|
|
|
|
if (SelSaveGame != &NewSaveNode)
|
|
|
|
{
|
2007-05-01 10:09:04 +00:00
|
|
|
EndString.Format("%s" TEXTCOLOR_WHITE "%s" TEXTCOLOR_NORMAL "?\n\n%s",
|
|
|
|
GStrings("MNU_DELETESG"), SelSaveGame->Title, GStrings("PRESSYN"));
|
2007-05-01 07:57:08 +00:00
|
|
|
|
2009-08-07 03:30:51 +00:00
|
|
|
M_StartMessage (EndString, M_DeleteSaveResponse);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'N':
|
|
|
|
if (currentMenu == &SaveDef)
|
|
|
|
{
|
|
|
|
SelSaveGame = TopSaveGame = &NewSaveNode;
|
|
|
|
M_UnloadSaveData ();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-07-26 03:25:18 +00:00
|
|
|
return true;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void M_LoadSelect (const FSaveGameNode *file)
|
|
|
|
{
|
|
|
|
G_LoadGame (file->Filename.GetChars());
|
|
|
|
if (gamestate == GS_FULLCONSOLE)
|
|
|
|
{
|
|
|
|
gamestate = GS_HIDECONSOLE;
|
|
|
|
}
|
|
|
|
if (quickSaveSlot == (FSaveGameNode *)1)
|
|
|
|
{
|
|
|
|
quickSaveSlot = SelSaveGame;
|
|
|
|
}
|
|
|
|
M_ClearMenus ();
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
}
|
|
|
|
|
2007-02-28 16:49:19 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// User wants to save. Start string input for M_Responder
|
|
|
|
//
|
2009-08-07 03:30:51 +00:00
|
|
|
static void M_CancelSaveName ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
static void M_SaveSelect (const FSaveGameNode *file)
|
|
|
|
{
|
|
|
|
// we are going to be intercepting all chars
|
|
|
|
genStringEnter = 1;
|
|
|
|
genStringEnd = M_DoSave;
|
2009-08-07 03:30:51 +00:00
|
|
|
genStringCancel = M_CancelSaveName;
|
2006-02-24 04:48:15 +00:00
|
|
|
genStringLen = SAVESTRINGSIZE-1;
|
|
|
|
|
|
|
|
if (file != &NewSaveNode)
|
|
|
|
{
|
|
|
|
strcpy (savegamestring, file->Title);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-01-23 19:07:18 +00:00
|
|
|
// If we are naming a new save, don't start the cursor on "end".
|
|
|
|
if (InputGridX == INPUTGRID_WIDTH - 1 && InputGridY == INPUTGRID_HEIGHT - 1)
|
|
|
|
{
|
|
|
|
InputGridX = 0;
|
|
|
|
InputGridY = 0;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
savegamestring[0] = 0;
|
|
|
|
}
|
|
|
|
saveCharIndex = strlen (savegamestring);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void M_DeleteSaveResponse (int choice)
|
|
|
|
{
|
|
|
|
M_ClearSaveStuff ();
|
|
|
|
if (choice == 'y')
|
|
|
|
{
|
|
|
|
FSaveGameNode *next = static_cast<FSaveGameNode *>(SelSaveGame->Succ);
|
|
|
|
if (next->Succ == NULL)
|
|
|
|
{
|
|
|
|
next = static_cast<FSaveGameNode *>(SelSaveGame->Pred);
|
|
|
|
if (next->Pred == NULL)
|
|
|
|
{
|
|
|
|
next = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
remove (SelSaveGame->Filename.GetChars());
|
|
|
|
M_UnloadSaveData ();
|
2006-05-12 03:14:40 +00:00
|
|
|
SelSaveGame = M_RemoveSaveSlot (SelSaveGame);
|
2006-02-24 04:48:15 +00:00
|
|
|
M_ExtractSaveData (SelSaveGame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_StartControlPanel
|
|
|
|
//
|
2009-08-07 03:30:51 +00:00
|
|
|
void M_StartControlPanel (bool makeSound, bool wantTop)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
// intro might call this repeatedly
|
|
|
|
if (menuactive == MENU_On)
|
|
|
|
return;
|
2009-07-26 03:25:18 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < NUM_MKEYS; ++i)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
MenuButtons[i].ReleaseKey(0);
|
2009-07-26 03:25:18 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
drawSkull = true;
|
|
|
|
MenuStackDepth = 0;
|
2009-08-07 03:30:51 +00:00
|
|
|
if (wantTop)
|
|
|
|
{
|
|
|
|
M_SetupNextMenu(TopLevelMenu);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Just a default. The caller ought to call M_SetupNextMenu() next.
|
|
|
|
currentMenu = TopLevelMenu;
|
|
|
|
itemOn = currentMenu->lastOn;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
C_HideConsole (); // [RH] Make sure console goes bye bye.
|
|
|
|
OptionsActive = false; // [RH] Make sure none of the options menus appear.
|
|
|
|
M_ActivateMenuInput ();
|
|
|
|
|
|
|
|
if (makeSound)
|
|
|
|
{
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/activate", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_Drawer
|
|
|
|
// Called after the view has been rendered,
|
|
|
|
// but before it has been blitted.
|
|
|
|
//
|
|
|
|
void M_Drawer ()
|
|
|
|
{
|
|
|
|
int i, x, y, max;
|
2006-05-09 00:28:01 +00:00
|
|
|
PalEntry fade = 0;
|
|
|
|
|
2008-06-16 07:40:28 +00:00
|
|
|
player_t *player = &players[consoleplayer];
|
|
|
|
AActor *camera = player->camera;
|
|
|
|
|
|
|
|
if (!screen->Accel2D && camera != NULL && (gamestate == GS_LEVEL || gamestate == GS_TITLELEVEL))
|
2006-05-09 00:28:01 +00:00
|
|
|
{
|
2008-06-16 07:40:28 +00:00
|
|
|
if (camera->player != NULL)
|
2006-05-09 00:28:01 +00:00
|
|
|
{
|
2008-06-16 07:40:28 +00:00
|
|
|
player = camera->player;
|
2006-05-09 00:28:01 +00:00
|
|
|
}
|
|
|
|
fade = PalEntry (BYTE(player->BlendA*255), BYTE(player->BlendR*255), BYTE(player->BlendG*255), BYTE(player->BlendB*255));
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Horiz. & Vertically center string and print it.
|
|
|
|
if (messageToPrint)
|
|
|
|
{
|
2009-08-07 03:30:51 +00:00
|
|
|
int fontheight = SmallFont->GetHeight();
|
2006-05-09 00:28:01 +00:00
|
|
|
screen->Dim (fade);
|
2006-02-24 04:48:15 +00:00
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
SB_state = screen->GetPageCount ();
|
|
|
|
|
2008-11-27 17:43:36 +00:00
|
|
|
FBrokenLines *lines = V_BreakLines (SmallFont, 320, messageString);
|
2006-02-24 04:48:15 +00:00
|
|
|
y = 100;
|
|
|
|
|
2006-08-31 00:16:12 +00:00
|
|
|
for (i = 0; lines[i].Width >= 0; i++)
|
2008-11-27 17:43:36 +00:00
|
|
|
y -= SmallFont->GetHeight () / 2;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-08-31 00:16:12 +00:00
|
|
|
for (i = 0; lines[i].Width >= 0; i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (SmallFont, CR_UNTRANSLATED, 160 - lines[i].Width/2, y, lines[i].Text,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_Clean, true, TAG_DONE);
|
2009-08-07 03:30:51 +00:00
|
|
|
y += fontheight;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
V_FreeBrokenLines (lines);
|
2009-08-07 03:30:51 +00:00
|
|
|
if (messageRoutine != NULL)
|
|
|
|
{
|
|
|
|
y += fontheight;
|
|
|
|
screen->DrawText(SmallFont, CR_UNTRANSLATED, 160, y, GStrings["TXT_YES"], DTA_Clean, true, TAG_DONE);
|
|
|
|
screen->DrawText(SmallFont, CR_UNTRANSLATED, 160, y + fontheight + 1, GStrings["TXT_NO"], DTA_Clean, true, TAG_DONE);
|
|
|
|
if (skullAnimCounter < 6)
|
|
|
|
{
|
2009-12-25 05:55:51 +00:00
|
|
|
screen->DrawText(ConFont, CR_RED,
|
|
|
|
(150 - 160) * CleanXfac + screen->GetWidth() / 2,
|
|
|
|
(y + (fontheight + 1) * messageSelection - 100) * CleanYfac + screen->GetHeight() / 2,
|
|
|
|
"\xd",
|
|
|
|
DTA_CellX, 8 * CleanXfac,
|
|
|
|
DTA_CellY, 8 * CleanYfac,
|
|
|
|
TAG_DONE);
|
2009-08-07 03:30:51 +00:00
|
|
|
}
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else if (menuactive != MENU_Off)
|
|
|
|
{
|
|
|
|
if (InfoType == 0 && !OptionsActive)
|
|
|
|
{
|
2006-05-09 00:28:01 +00:00
|
|
|
screen->Dim (fade);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
// For Heretic shareware message:
|
|
|
|
if (showSharewareMessage)
|
|
|
|
{
|
2008-11-27 17:43:36 +00:00
|
|
|
const char *text = GStrings("MNU_ONLYREGISTERED");
|
|
|
|
screen->DrawText (SmallFont, CR_WHITE, 160 - SmallFont->StringWidth(text)/2,
|
2007-05-01 07:57:08 +00:00
|
|
|
8, text, DTA_Clean, true, TAG_DONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
SB_state = screen->GetPageCount ();
|
|
|
|
|
|
|
|
if (OptionsActive)
|
|
|
|
{
|
|
|
|
M_OptDrawer ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (currentMenu->routine)
|
|
|
|
currentMenu->routine(); // call Draw routine
|
|
|
|
|
|
|
|
// DRAW MENU
|
|
|
|
x = currentMenu->x;
|
|
|
|
y = currentMenu->y;
|
|
|
|
max = currentMenu->numitems;
|
|
|
|
|
|
|
|
for (i = 0; i < max; i++)
|
|
|
|
{
|
|
|
|
if (currentMenu->menuitems[i].name)
|
|
|
|
{
|
|
|
|
if (currentMenu->menuitems[i].fulltext)
|
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
int color = currentMenu->menuitems[i].textcolor;
|
|
|
|
if (color == CR_UNTRANSLATED)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-11-03 11:41:42 +00:00
|
|
|
// The default DBIGFONT is white but Doom's default should be red.
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & GAME_DoomChex)
|
2007-11-03 11:41:42 +00:00
|
|
|
{
|
|
|
|
color = CR_RED;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2008-02-18 22:40:39 +00:00
|
|
|
const char *text = currentMenu->menuitems[i].name;
|
|
|
|
if (*text == '$') text = GStrings(text+1);
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (BigFont, color, x, y, text,
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
screen->DrawTexture (TexMan[currentMenu->menuitems[i].name], x, y,
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
y += LINEHEIGHT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// DRAW CURSOR
|
|
|
|
if (drawSkull)
|
|
|
|
{
|
|
|
|
if (currentMenu == &PSetupDef)
|
|
|
|
{
|
|
|
|
// [RH] Use options menu cursor for the player setup menu.
|
|
|
|
if (skullAnimCounter < 6)
|
|
|
|
{
|
2010-03-06 02:51:23 +00:00
|
|
|
double item;
|
|
|
|
// The green slider is halfway between lines, and the red and
|
|
|
|
// blue ones are offset slightly to make room for it.
|
|
|
|
if (itemOn < 3)
|
|
|
|
{
|
|
|
|
item = itemOn;
|
|
|
|
}
|
|
|
|
else if (itemOn > 5)
|
|
|
|
{
|
|
|
|
item = itemOn - 1;
|
|
|
|
}
|
|
|
|
else if (itemOn == 3)
|
|
|
|
{
|
|
|
|
item = 2.875;
|
|
|
|
}
|
|
|
|
else if (itemOn == 4)
|
|
|
|
{
|
|
|
|
item = 3.5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item = 4.125;
|
|
|
|
}
|
2008-11-27 17:43:36 +00:00
|
|
|
screen->DrawText (ConFont, CR_RED, x - 16,
|
2010-03-06 02:51:23 +00:00
|
|
|
currentMenu->y + int(item*PLAYERSETUP_LINEHEIGHT) +
|
2008-08-30 19:44:19 +00:00
|
|
|
(!(gameinfo.gametype & (GAME_DoomStrifeChex)) ? 6 : -1), "\xd",
|
2006-02-24 04:48:15 +00:00
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
2008-08-30 19:44:19 +00:00
|
|
|
else if (gameinfo.gametype & GAME_DoomChex)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-03-27 03:30:02 +00:00
|
|
|
screen->DrawTexture (TexMan("M_SKULL1"),
|
2006-02-24 04:48:15 +00:00
|
|
|
x + SKULLXOFF, currentMenu->y - 5 + itemOn*LINEHEIGHT,
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else if (gameinfo.gametype == GAME_Strife)
|
|
|
|
{
|
2010-03-27 03:30:02 +00:00
|
|
|
screen->DrawTexture (TexMan("M_CURS1"),
|
2006-02-24 04:48:15 +00:00
|
|
|
x - 28, currentMenu->y - 5 + itemOn*LINEHEIGHT,
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-03-27 03:30:02 +00:00
|
|
|
screen->DrawTexture (TexMan("M_SLCTR1"),
|
2006-02-24 04:48:15 +00:00
|
|
|
x + SELECTOR_XOFFSET,
|
|
|
|
currentMenu->y + itemOn*LINEHEIGHT + SELECTOR_YOFFSET,
|
|
|
|
DTA_Clean, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-23 19:07:18 +00:00
|
|
|
if (genStringEnter && InputGridOkay)
|
|
|
|
{
|
|
|
|
M_DrawInputGrid();
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void M_ClearSaveStuff ()
|
|
|
|
{
|
|
|
|
M_UnloadSaveData ();
|
|
|
|
if (SaveGames.Head == &NewSaveNode)
|
|
|
|
{
|
|
|
|
SaveGames.RemHead ();
|
|
|
|
if (SelSaveGame == &NewSaveNode)
|
|
|
|
{
|
|
|
|
SelSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
|
|
|
|
}
|
|
|
|
if (TopSaveGame == &NewSaveNode)
|
|
|
|
{
|
|
|
|
TopSaveGame = static_cast<FSaveGameNode *>(SaveGames.Head);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (quickSaveSlot == (FSaveGameNode *)1)
|
|
|
|
{
|
|
|
|
quickSaveSlot = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-23 19:07:18 +00:00
|
|
|
static void M_DrawInputGrid()
|
|
|
|
{
|
|
|
|
const int cell_width = 18 * CleanXfac;
|
|
|
|
const int cell_height = 12 * CleanYfac;
|
|
|
|
const int top_padding = cell_height / 2 - SmallFont->GetHeight() * CleanYfac / 2;
|
|
|
|
|
|
|
|
// Darken the background behind the character grid.
|
|
|
|
// Unless we frame it with a border, I think it looks better to extend the
|
|
|
|
// background across the full width of the screen.
|
|
|
|
screen->Dim(0, 0.8f,
|
|
|
|
0 /*screen->GetWidth()/2 - 13 * cell_width / 2*/,
|
|
|
|
screen->GetHeight() - 5 * cell_height,
|
|
|
|
screen->GetWidth() /*13 * cell_width*/,
|
|
|
|
5 * cell_height);
|
|
|
|
|
|
|
|
// Highlight the background behind the selected character.
|
|
|
|
screen->Dim(MAKERGB(255,248,220), 0.6f,
|
|
|
|
InputGridX * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2,
|
|
|
|
InputGridY * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight(),
|
|
|
|
cell_width, cell_height);
|
|
|
|
|
|
|
|
for (int y = 0; y < INPUTGRID_HEIGHT; ++y)
|
|
|
|
{
|
|
|
|
const int yy = y * cell_height - INPUTGRID_HEIGHT * cell_height + screen->GetHeight();
|
|
|
|
for (int x = 0; x < INPUTGRID_WIDTH; ++x)
|
|
|
|
{
|
|
|
|
int width;
|
|
|
|
const int xx = x * cell_width - INPUTGRID_WIDTH * cell_width / 2 + screen->GetWidth() / 2;
|
|
|
|
const int ch = InputGridChars[y * INPUTGRID_WIDTH + x];
|
|
|
|
FTexture *pic = SmallFont->GetChar(ch, &width);
|
|
|
|
EColorRange color;
|
|
|
|
FRemapTable *remap;
|
|
|
|
|
|
|
|
// The highlighted character is yellow; the rest are dark gray.
|
|
|
|
color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY;
|
|
|
|
remap = SmallFont->GetColorTranslation(color);
|
|
|
|
|
|
|
|
if (pic != NULL)
|
|
|
|
{
|
|
|
|
// Draw a normal character.
|
|
|
|
screen->DrawTexture(pic, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding,
|
|
|
|
DTA_Translation, remap,
|
|
|
|
DTA_CleanNoMove, true,
|
|
|
|
TAG_DONE);
|
|
|
|
}
|
|
|
|
else if (ch == ' ')
|
|
|
|
{
|
|
|
|
// Draw the space as a box outline. We also draw it 50% wider than it really is.
|
|
|
|
const int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4;
|
|
|
|
const int x2 = x1 + width * 3 * CleanXfac / 2;
|
|
|
|
const int y1 = yy + top_padding;
|
|
|
|
const int y2 = y1 + SmallFont->GetHeight() * CleanYfac;
|
|
|
|
const int palentry = remap->Remap[remap->NumEntries*2/3];
|
|
|
|
const uint32 palcolor = remap->Palette[remap->NumEntries*2/3];
|
|
|
|
screen->Clear(x1, y1, x2, y1+CleanYfac, palentry, palcolor); // top
|
|
|
|
screen->Clear(x1, y2, x2, y2+CleanYfac, palentry, palcolor); // bottom
|
|
|
|
screen->Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palentry, palcolor); // left
|
|
|
|
screen->Clear(x2-CleanXfac, y1+CleanYfac, x2, y2, palentry, palcolor); // right
|
|
|
|
}
|
|
|
|
else if (ch == '\b' || ch == 0)
|
|
|
|
{
|
|
|
|
// Draw the backspace and end "characters".
|
|
|
|
const char *const str = ch == '\b' ? "BS" : "ED";
|
|
|
|
screen->DrawText(SmallFont, color,
|
|
|
|
xx + cell_width/2 - SmallFont->StringWidth(str)*CleanXfac/2,
|
|
|
|
yy + top_padding, str, DTA_CleanNoMove, true, TAG_DONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
//
|
|
|
|
// M_ClearMenus
|
|
|
|
//
|
|
|
|
void M_ClearMenus ()
|
|
|
|
{
|
2007-12-27 04:30:12 +00:00
|
|
|
if (FireTexture)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2007-12-27 04:30:12 +00:00
|
|
|
delete FireTexture;
|
|
|
|
FireTexture = NULL;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
M_ClearSaveStuff ();
|
|
|
|
M_DeactivateMenuInput ();
|
|
|
|
MenuStackDepth = 0;
|
|
|
|
OptionsActive = false;
|
|
|
|
InfoType = 0;
|
|
|
|
drawSkull = true;
|
|
|
|
M_DemoNoPlay = false;
|
|
|
|
BorderNeedRefresh = screen->GetPageCount ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_SetupNextMenu
|
|
|
|
//
|
|
|
|
void M_SetupNextMenu (oldmenu_t *menudef)
|
|
|
|
{
|
|
|
|
MenuStack[MenuStackDepth].menu.old = menudef;
|
|
|
|
MenuStack[MenuStackDepth].isNewStyle = false;
|
|
|
|
MenuStack[MenuStackDepth].drawSkull = drawSkull;
|
|
|
|
MenuStackDepth++;
|
|
|
|
|
|
|
|
currentMenu = menudef;
|
|
|
|
itemOn = currentMenu->lastOn;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void M_PopMenuStack (void)
|
|
|
|
{
|
|
|
|
M_DemoNoPlay = false;
|
|
|
|
InfoType = 0;
|
|
|
|
M_ClearSaveStuff ();
|
|
|
|
flagsvar = 0;
|
|
|
|
if (MenuStackDepth > 1)
|
|
|
|
{
|
|
|
|
MenuStackDepth -= 2;
|
|
|
|
if (MenuStack[MenuStackDepth].isNewStyle)
|
|
|
|
{
|
|
|
|
OptionsActive = true;
|
|
|
|
CurrentMenu = MenuStack[MenuStackDepth].menu.newmenu;
|
|
|
|
CurrentItem = CurrentMenu->lastOn;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
OptionsActive = false;
|
|
|
|
currentMenu = MenuStack[MenuStackDepth].menu.old;
|
|
|
|
itemOn = currentMenu->lastOn;
|
|
|
|
}
|
|
|
|
drawSkull = MenuStack[MenuStackDepth].drawSkull;
|
|
|
|
++MenuStackDepth;
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/backup", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
M_ClearMenus ();
|
2008-07-05 03:32:44 +00:00
|
|
|
S_Sound (CHAN_VOICE | CHAN_UI, "menu/clear", 1, ATTN_NONE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_Ticker
|
|
|
|
//
|
|
|
|
void M_Ticker (void)
|
|
|
|
{
|
|
|
|
if (showSharewareMessage)
|
|
|
|
{
|
|
|
|
--showSharewareMessage;
|
|
|
|
}
|
|
|
|
if (menuactive == MENU_Off)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
MenuTime++;
|
|
|
|
if (--skullAnimCounter <= 0)
|
|
|
|
{
|
|
|
|
skullAnimCounter = 8;
|
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
if (currentMenu == &PSetupDef || currentMenu == &ClassMenuDef)
|
2009-07-26 03:25:18 +00:00
|
|
|
{
|
|
|
|
M_PlayerSetupTicker();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_MKEYS; ++i)
|
|
|
|
{
|
|
|
|
if (MenuButtons[i].bDown)
|
|
|
|
{
|
|
|
|
if (MenuButtonTickers[i] > 0 && --MenuButtonTickers[i] <= 0)
|
|
|
|
{
|
|
|
|
MenuButtonTickers[i] = KEY_REPEAT_RATE;
|
|
|
|
M_ButtonHandler(EMenuKey(i), true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
// M_Init
|
|
|
|
//
|
|
|
|
EXTERN_CVAR (Int, screenblocks)
|
|
|
|
|
|
|
|
void M_Init (void)
|
|
|
|
{
|
2006-07-16 01:25:29 +00:00
|
|
|
unsigned int i;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-05-12 03:14:40 +00:00
|
|
|
atterm (M_Deinit);
|
|
|
|
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
TopLevelMenu = currentMenu = &MainDef;
|
|
|
|
if (gameinfo.gametype == GAME_Strife)
|
|
|
|
{
|
|
|
|
MainDef.y = 45;
|
2007-11-02 22:03:03 +00:00
|
|
|
//NewDef.lastOn = 1;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TopLevelMenu = currentMenu = &HereticMainDef;
|
|
|
|
PSetupDef.y -= 7;
|
|
|
|
LoadDef.y -= 20;
|
|
|
|
SaveDef.y -= 20;
|
|
|
|
}
|
|
|
|
PickPlayerClass ();
|
|
|
|
OptionsActive = false;
|
|
|
|
menuactive = MENU_Off;
|
|
|
|
InfoType = 0;
|
|
|
|
itemOn = currentMenu->lastOn;
|
|
|
|
skullAnimCounter = 10;
|
|
|
|
drawSkull = true;
|
|
|
|
messageToPrint = 0;
|
|
|
|
messageString = NULL;
|
|
|
|
messageLastMenuActive = menuactive;
|
|
|
|
quickSaveSlot = NULL;
|
2006-04-20 14:21:27 +00:00
|
|
|
lastSaveSlot = NULL;
|
2006-02-24 04:48:15 +00:00
|
|
|
strcpy (NewSaveNode.Title, "<New Save Game>");
|
|
|
|
|
2008-08-30 19:44:19 +00:00
|
|
|
underscore[0] = (gameinfo.gametype & (GAME_DoomStrifeChex)) ? '_' : '[';
|
2006-02-24 04:48:15 +00:00
|
|
|
underscore[1] = '\0';
|
|
|
|
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & GAME_DoomChex)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
LINEHEIGHT = 16;
|
|
|
|
}
|
|
|
|
else if (gameinfo.gametype == GAME_Strife)
|
|
|
|
{
|
|
|
|
LINEHEIGHT = 19;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LINEHEIGHT = 20;
|
|
|
|
}
|
|
|
|
|
2009-03-22 11:37:56 +00:00
|
|
|
if (!gameinfo.drawreadthis)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
MainMenu[MainDef.numitems-2] = MainMenu[MainDef.numitems-1];
|
|
|
|
MainDef.numitems--;
|
|
|
|
MainDef.y += 8;
|
|
|
|
ReadDef.routine = M_DrawReadThis;
|
|
|
|
ReadDef.x = 330;
|
|
|
|
ReadDef.y = 165;
|
2009-03-22 11:37:56 +00:00
|
|
|
//ReadMenu[0].routine = M_FinishReadThis;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
M_OptInit ();
|
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
// [GRB] Set up player class menu
|
|
|
|
if (!(gameinfo.gametype == GAME_Hexen && PlayerClasses.Size () == 3 &&
|
|
|
|
PlayerClasses[0].Type->IsDescendantOf (PClass::FindClass (NAME_FighterPlayer)) &&
|
|
|
|
PlayerClasses[1].Type->IsDescendantOf (PClass::FindClass (NAME_ClericPlayer)) &&
|
|
|
|
PlayerClasses[2].Type->IsDescendantOf (PClass::FindClass (NAME_MagePlayer))))
|
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
for (i = 0; i < PlayerClasses.Size () && n < 7; i++)
|
|
|
|
{
|
|
|
|
if (!(PlayerClasses[i].Flags & PCF_NOMENU))
|
|
|
|
{
|
|
|
|
ClassMenuItems[n].name =
|
|
|
|
PlayerClasses[i].Type->Meta.GetMetaString (APMETA_DisplayName);
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n > 1)
|
|
|
|
{
|
|
|
|
ClassMenuItems[n].name = "Random";
|
|
|
|
ClassMenuDef.numitems = n+1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (n == 0)
|
|
|
|
{
|
|
|
|
ClassMenuItems[0].name =
|
|
|
|
PlayerClasses[0].Type->Meta.GetMetaString (APMETA_DisplayName);
|
|
|
|
}
|
|
|
|
ClassMenuDef.numitems = 1;
|
|
|
|
}
|
|
|
|
|
2008-08-30 19:44:19 +00:00
|
|
|
if (gameinfo.gametype & (GAME_DoomStrifeChex))
|
2006-07-13 10:17:56 +00:00
|
|
|
{
|
|
|
|
ClassMenuDef.x = 48;
|
|
|
|
ClassMenuDef.y = 63;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ClassMenuDef.x = 80;
|
|
|
|
ClassMenuDef.y = 50;
|
|
|
|
}
|
|
|
|
if (ClassMenuDef.numitems > 4)
|
|
|
|
{
|
|
|
|
ClassMenuDef.y -= LINEHEIGHT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// [RH] Build a palette translation table for the player setup effect
|
|
|
|
if (gameinfo.gametype != GAME_Hexen)
|
|
|
|
{
|
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
{
|
2007-12-27 04:30:12 +00:00
|
|
|
FireRemap.Remap[i] = ColorMatcher.Pick (i/2+32, 0, i/4);
|
2008-04-22 18:48:30 +00:00
|
|
|
FireRemap.Palette[i] = PalEntry(255, i/2+32, 0, i/4);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // The reddish color ramp above doesn't look too good with the
|
|
|
|
// Hexen palette, so Hexen gets a greenish one instead.
|
|
|
|
for (i = 0; i < 256; ++i)
|
|
|
|
{
|
2007-12-27 04:30:12 +00:00
|
|
|
FireRemap.Remap[i] = ColorMatcher.Pick (i/4, i*13/40+7, i/4);
|
2008-04-22 18:48:30 +00:00
|
|
|
FireRemap.Palette[i] = PalEntry(255, i/4, i*13/40+7, i/4);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void PickPlayerClass ()
|
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
int pclass = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
// [GRB] Pick a class from player class list
|
|
|
|
if (PlayerClasses.Size () > 1)
|
|
|
|
{
|
|
|
|
pclass = players[consoleplayer].userinfo.PlayerClass;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-13 10:17:56 +00:00
|
|
|
if (pclass < 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-13 10:17:56 +00:00
|
|
|
pclass = (MenuTime>>7) % PlayerClasses.Size ();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
2006-07-13 10:17:56 +00:00
|
|
|
|
|
|
|
PlayerClass = &PlayerClasses[pclass];
|
2010-03-06 02:51:23 +00:00
|
|
|
P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|