11 Dec 2009

This commit is contained in:
g-cont 2009-12-11 00:00:00 +03:00 committed by Alibek Omarov
parent 01f41ca1a5
commit 60302daf99
17 changed files with 947 additions and 613 deletions

View File

@ -227,7 +227,7 @@ edict_t *CL_GetEdictByIndex( int index );
edict_t *CL_GetLocalPlayer( void );
int CL_GetMaxClients( void );
byte CL_GetMouthOpen( int entityIndex );
bool SV_GetComment( char *comment, int savenum );
bool SV_GetComment( const char *savename, char *comment );
void SV_ForceMod( void );
void CL_MouseEvent( int mx, int my );
void CL_AddLoopingSounds( void );

View File

@ -1124,8 +1124,14 @@ void Key_Event( int key, bool down, int time )
return;
case key_console:
if( cls.state == ca_active )
{
cls.key_dest = key_game;
else UI_SetActiveMenu( UI_MAINMENU );
}
else
{
UI_SetActiveMenu( UI_MAINMENU );
return; // don't pass Esc into menu
}
break;
case key_menu:
UI_KeyEvent( key );

View File

@ -3842,4 +3842,7 @@ void SV_LoadProgs( const char *name )
// initialize pm_shared
SV_InitClientMove();
// fire once
MsgDev( D_INFO, "Dll loaded for mod %s\n", svgame.dllFuncs.pfnGetGameDescription() );
}

View File

@ -373,9 +373,6 @@ void SV_InitGame( void )
if( !svgame.hInstance )
SV_LoadProgs( "server" );
// fire once
MsgDev( D_INFO, "Dll loaded for mod %s\n", svgame.dllFuncs.pfnGetGameDescription() );
// make sure the client is down
CL_Drop();
}

View File

@ -323,11 +323,13 @@ static void SV_SaveServerData( wfile_t *f, const char *name, bool bUseLandMark )
SV_WriteSaveFile
=============
*/
void SV_WriteSaveFile( const char *name, bool autosave, bool bUseLandmark )
void SV_WriteSaveFile( const char *inname, bool autosave, bool bUseLandmark )
{
wfile_t *savfile = NULL;
char path[MAX_SYSPATH];
int n, minutes, tens, units;
string path, name;
float total;
if( sv.state != ss_active ) return;
if( svgame.globals->deathmatch || svgame.globals->coop || svgame.globals->teamplay )
{
@ -340,6 +342,10 @@ void SV_WriteSaveFile( const char *name, bool autosave, bool bUseLandmark )
return;
}
if( !com.stricmp( inname, "new" ))
com.strncpy( name, timestamp( TIME_FILENAME ), sizeof( name ));
else com.strncpy( name, inname, sizeof( name ));
com.sprintf( path, "save/%s.bin", name );
savfile = WAD_Open( path, "wb" );
@ -349,11 +355,18 @@ void SV_WriteSaveFile( const char *name, bool autosave, bool bUseLandmark )
return;
}
// calc time
total = svgame.globals->time;
minutes = (int)total / 60;
n = total - minutes * 60;
tens = n / 10;
units = n % 10;
// split comment to sections
com.strncpy( svs.comment, sv.configstrings[CS_NAME], CS_SIZE );
com.strncpy( svs.comment + CS_SIZE, timestamp( TIME_DATE_ONLY ), CS_TIME );
com.strncpy( svs.comment + CS_SIZE + CS_TIME, timestamp( TIME_NO_SECONDS ), CS_TIME );
com.strncpy( svs.comment + CS_SIZE + (CS_TIME * 2), svs.mapname, CS_SIZE );
com.strncpy( svs.comment + CS_SIZE + (CS_TIME * 2), va( "%i:%i%i", minutes, tens, units ), CS_SIZE );
if( !autosave ) MsgDev( D_INFO, "Saving game..." );
// write lumps
@ -364,7 +377,7 @@ void SV_WriteSaveFile( const char *name, bool autosave, bool bUseLandmark )
WAD_Close( savfile );
// write saveshot for preview, but autosave
if( !autosave ) Cbuf_AddText( va( "saveshot %s\n", name ));
if( !autosave ) Cbuf_AddText( va( "saveshot \"%s\"\n", name ));
if( !autosave ) MsgDev( D_INFO, "done.\n" );
}
@ -373,10 +386,13 @@ void SV_ReadComment( wfile_t *l )
SAVERESTOREDATA *pSaveData;
game_header_t ghdr;
// init the game to get acess for read funcs
if( !svgame.hInstance ) SV_LoadProgs( "server" );
// initialize SAVERESTOREDATA
Mem_Set( &svgame.SaveData, 0, sizeof( SAVERESTOREDATA ));
svgame.SaveData.tokenCount = 0xFFF; // assume a maximum of 4K-1 symbol table entries
svgame.SaveData.pTokens = (char **)Mem_Alloc( svgame.temppool, svgame.SaveData.tokenCount * sizeof( char* ));
svgame.SaveData.pTokens = (char **)Mem_Alloc( host.mempool, svgame.SaveData.tokenCount * sizeof( char* ));
pSaveData = svgame.globals->pSaveData = &svgame.SaveData;
SV_ReadBuffer( l, LUMP_GLOBALS );
@ -780,18 +796,18 @@ void SV_ChangeLevel( bool bUseLandmark, const char *mapname, const char *start )
SV_ActivateServer ();
}
bool SV_GetComment( char *comment, int savenum )
bool SV_GetComment( const char *savename, char *comment )
{
wfile_t *savfile;
int result;
if( !comment ) return false;
result = WAD_Check( va( "save/save%i.bin", savenum ));
result = WAD_Check( savename );
switch( result )
{
case 0:
com.strncpy( comment, "<empty>", MAX_STRING );
com.strncpy( comment, "", MAX_STRING );
return false;
case 1: break;
default:
@ -799,7 +815,7 @@ bool SV_GetComment( char *comment, int savenum )
return false;
}
savfile = WAD_Open( va( "save/save%i.bin", savenum ), "rb" );
savfile = WAD_Open( savename, "rb" );
SV_ReadComment( savfile );
Mem_Copy( comment, svs.comment, MAX_STRING );
WAD_Close( savfile );

View File

@ -19,67 +19,52 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "common.h"
#include "com_library.h"
#include "ui_local.h"
#include "client.h"
#define ART_BACKGROUND "gfx/shell/splash"
#define ART_BANNER "gfx/shell/banners/loadgame_t"
#define ART_LISTBACK "gfx/shell/segments/files_box"
#define ART_BANNER "gfx/shell/head_load"
#define ART_LEVELSHOTBLUR "gfx/shell/segments/sp_mapshot"
#define UI_MAXGAMES 14
#define ID_BACKGROUND 0
#define ID_BANNER 1
#define ID_LOAD 2
#define ID_DELETE 3
#define ID_CANCEL 4
#define ID_SAVELIST 5
#define ID_TABLEHINT 6
#define ID_LEVELSHOT 7
#define ID_BACK 2
#define ID_LOAD 3
#define LEVELSHOT_X 72
#define LEVELSHOT_Y 400
#define LEVELSHOT_W 192
#define LEVELSHOT_H 160
#define ID_LISTBACK 4
#define ID_GAMETITLE 5
#define ID_LISTGAMES 6
#define ID_LEVELSHOT 20
#define ID_NEWGAME 21
#define ID_SAVEGAME 22
#define ID_DELETEGAME 23
#define TIME_LENGTH 20
#define NAME_LENGTH 32+TIME_LENGTH
#define GAMETIME_LENGTH 15+NAME_LENGTH
typedef struct
{
char map[CS_SIZE];
char time[CS_TIME];
char date[CS_TIME];
char name[CS_SIZE];
bool valid;
} uiLoadGameGame_t;
static rgba_t uiLoadGameColor = { 0, 76, 127, 255 };
typedef struct
{
uiLoadGameGame_t games[UI_MAXGAMES];
int currentGame;
int currentLevelShot;
long fadeTime;
char saveName[UI_MAXGAMES][CS_SIZE];
char delName[UI_MAXGAMES][CS_SIZE];
string saveDescription[UI_MAXGAMES];
char *saveDescriptionPtr[UI_MAXGAMES];
menuFramework_s menu;
menuBitmap_s background;
menuBitmap_s banner;
menuAction_s load;
menuAction_s delete;
menuAction_s cancel;
menuBitmap_s back;
menuBitmap_s load;
menuScrollList_s savesList;
menuBitmap_s listBack;
menuAction_s gameTitle;
menuAction_s listGames[UI_MAXGAMES];
menuBitmap_s levelShot;
menuBitmap_s newGame;
menuBitmap_s saveGame;
menuBitmap_s deleteGame;
menuAction_s hintMessage;
char hintText[MAX_SYSPATH];
} uiLoadGame_t;
static uiLoadGame_t uiLoadGame;
@ -92,43 +77,60 @@ UI_LoadGame_GetGameList
*/
static void UI_LoadGame_GetGameList( void )
{
string name;
string comment;
search_t *t;
int i;
for( i = 0; i < UI_MAXGAMES; i++ )
t = FS_Search( "save/*.bin", true );
for( i = 0; t && i < t->numfilenames; i++ )
{
if( !SV_GetComment( name, i ))
if( i >= UI_MAXGAMES ) break;
if( !SV_GetComment( t->filenames[i], comment ))
{
// get name string even if not found - SV_GetComment can be mark saves
// as <CORRUPTED> <OLD VERSION> <EMPTY> etc
com.strncpy(uiLoadGame.games[i].name, name, sizeof( uiLoadGame.games[i].name ));
com.strncpy(uiLoadGame.games[i].map, "", sizeof( uiLoadGame.games[i].map ));
com.strncpy(uiLoadGame.games[i].time, "", sizeof( uiLoadGame.games[i].time ));
com.strncpy(uiLoadGame.games[i].date, "", sizeof( uiLoadGame.games[i].date ));
uiLoadGame.games[i].valid = false;
if( com.strlen( comment ))
{
// get name string even if not found - SV_GetComment can be mark saves
// as <CORRUPTED> <OLD VERSION> etc
com.strncat( uiLoadGame.saveDescription[i], uiEmptyString, TIME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], comment, NAME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], uiEmptyString, NAME_LENGTH );
uiLoadGame.saveDescriptionPtr[i] = uiLoadGame.saveDescription[i];
FS_FileBase( t->filenames[i], uiLoadGame.delName[i] );
}
else uiLoadGame.saveDescriptionPtr[i] = NULL;
continue;
}
com.strncpy( uiLoadGame.games[i].map, name + CS_SIZE + (CS_TIME * 2), CS_SIZE );
com.strncpy( uiLoadGame.games[i].time, name + CS_SIZE + CS_TIME, CS_TIME );
com.strncpy( uiLoadGame.games[i].date, name + CS_SIZE, CS_TIME );
com.strncpy( uiLoadGame.games[i].name, name, CS_SIZE );
uiLoadGame.games[i].valid = true;
// strip path, leave only filename (empty slots doesn't have savename)
FS_FileBase( t->filenames[i], uiLoadGame.saveName[i] );
FS_FileBase( t->filenames[i], uiLoadGame.delName[i] );
// fill save desc
com.strncat( uiLoadGame.saveDescription[i], comment + CS_SIZE, TIME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], " ", TIME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], comment + CS_SIZE + CS_TIME, TIME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], uiEmptyString, TIME_LENGTH ); // fill remaining entries
com.strncat( uiLoadGame.saveDescription[i], comment, NAME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], uiEmptyString, NAME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], comment + CS_SIZE + (CS_TIME * 2), GAMETIME_LENGTH );
com.strncat( uiLoadGame.saveDescription[i], uiEmptyString, GAMETIME_LENGTH );
uiLoadGame.saveDescriptionPtr[i] = uiLoadGame.saveDescription[i];
}
// select first valid slot
for( i = 0; i < UI_MAXGAMES; i++ )
{
if( uiLoadGame.games[i].valid )
{
uiLoadGame.listGames[i].generic.color = uiColorOrange;
uiLoadGame.currentGame = i;
break;
}
}
for( ; i < UI_MAXGAMES; i++ ) uiLoadGame.saveDescriptionPtr[i] = NULL;
uiLoadGame.savesList.itemNames = uiLoadGame.saveDescriptionPtr;
// couldn't find a valid slot, so gray load button
if( i == UI_MAXGAMES ) uiLoadGame.load.generic.flags |= QMF_GRAYED;
if( com.strlen( uiLoadGame.saveName[0] ) == 0 )
uiLoadGame.load.generic.flags |= QMF_GRAYED;
else uiLoadGame.load.generic.flags &= ~QMF_GRAYED;
if( com.strlen( uiLoadGame.delName[0] ) == 0 )
uiLoadGame.delete.generic.flags |= QMF_GRAYED;
else uiLoadGame.delete.generic.flags &= ~QMF_GRAYED;
if( t ) Mem_Free( t );
}
/*
@ -140,40 +142,36 @@ static void UI_LoadGame_Callback( void *self, int event )
{
menuCommon_s *item = (menuCommon_s *)self;
if( event != QM_ACTIVATED )
return;
if( item->type == QMTYPE_ACTION )
if( event == QM_CHANGED )
{
// reset color, get current game, set color
uiLoadGame.listGames[uiLoadGame.currentGame].generic.color = uiColorOrange;
uiLoadGame.currentGame = item->id - ID_LISTGAMES;
uiLoadGame.listGames[uiLoadGame.currentGame].generic.color = uiColorYellow;
if( com.strlen( uiLoadGame.saveName[uiLoadGame.savesList.curItem] ) == 0 )
uiLoadGame.load.generic.flags |= QMF_GRAYED;
else uiLoadGame.load.generic.flags &= ~QMF_GRAYED;
// restart levelshot animation
uiLoadGame.currentLevelShot = 0;
uiLoadGame.fadeTime = uiStatic.realTime;
if( com.strlen( uiLoadGame.delName[uiLoadGame.savesList.curItem] ) == 0 )
uiLoadGame.delete.generic.flags |= QMF_GRAYED;
else uiLoadGame.delete.generic.flags &= ~QMF_GRAYED;
return;
}
if( event != QM_ACTIVATED )
return;
switch( item->id )
{
case ID_BACK:
case ID_CANCEL:
UI_PopMenu();
break;
case ID_LOAD:
if( uiLoadGame.games[uiLoadGame.currentGame].valid )
Cbuf_ExecuteText( EXEC_APPEND, va( "load save%i\n", uiLoadGame.currentGame ));
if( com.strlen( uiLoadGame.saveName[uiLoadGame.savesList.curItem] ))
Cbuf_ExecuteText( EXEC_APPEND, va( "load \"%s\"\n", uiLoadGame.saveName[uiLoadGame.savesList.curItem] ));
break;
case ID_NEWGAME:
UI_NewGame_Menu();
break;
case ID_SAVEGAME:
UI_SaveGame_Menu();
break;
case ID_DELETEGAME:
Cbuf_ExecuteText( EXEC_NOW, va( "delete save%i\n", uiLoadGame.currentGame ));
UI_LoadGame_GetGameList();
case ID_DELETE:
if( com.strlen( uiLoadGame.delName[uiLoadGame.savesList.curItem] ))
{
Cbuf_ExecuteText( EXEC_NOW, va( "delete \"%s\"\n", uiLoadGame.delName[uiLoadGame.savesList.curItem] ));
UI_LoadGame_GetGameList();
}
break;
}
}
@ -187,106 +185,32 @@ static void UI_LoadGame_Ownerdraw( void *self )
{
menuCommon_s *item = (menuCommon_s *)self;
if( item->type == QMTYPE_ACTION )
if( item->type != QMTYPE_ACTION && item->id == ID_LEVELSHOT )
{
rgba_t color;
char *time, *date, *name;
bool centered;
int x, y, w, h;
if( item->id == ID_GAMETITLE )
{
time = "Time";
date = "Date";
name = "Map Name";
centered = false;
}
else
{
time = uiLoadGame.games[item->id - ID_LISTGAMES].time;
date = uiLoadGame.games[item->id - ID_LISTGAMES].date;
name = uiLoadGame.games[item->id - ID_LISTGAMES].name;
centered = !uiLoadGame.games[item->id - ID_LISTGAMES].valid;
if( com.strstr( uiLoadGame.games[item->id - ID_LISTGAMES].name, "<empty>" ))
centered = true;
if( com.strstr( uiLoadGame.games[item->id - ID_LISTGAMES].name, "<corrupted>" ))
centered = true;
}
if( !centered )
{
UI_DrawString( item->x, item->y, 82*uiStatic.scaleX, item->height, time, item->color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX, item->y, 82*uiStatic.scaleX, item->height, date, item->color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX + 83*uiStatic.scaleX, item->y, 296*uiStatic.scaleX, item->height, name, item->color, true, item->charWidth, item->charHeight, 1, true );
}
else UI_DrawString( item->x, item->y, item->width, item->height, name, item->color, true, item->charWidth, item->charHeight, 1, true );
if( self != UI_ItemAtCursor( item->parent ))
return;
*(uint *)color = *(uint *)item->color;
if( !centered )
{
UI_DrawString(item->x, item->y, 82*uiStatic.scaleX, item->height, time, color, true, item->charWidth, item->charHeight, 1, true);
UI_DrawString(item->x + 83*uiStatic.scaleX, item->y, 82*uiStatic.scaleX, item->height, date, color, true, item->charWidth, item->charHeight, 1, true);
UI_DrawString(item->x + 83*uiStatic.scaleX + 83*uiStatic.scaleX, item->y, 296*uiStatic.scaleX, item->height, name, color, true, item->charWidth, item->charHeight, 1, true);
}
else UI_DrawString(item->x, item->y, item->width, item->height, name, color, true, item->charWidth, item->charHeight, 1, true);
}
else
{
if( item->id == ID_LEVELSHOT )
{
int x, y, w, h;
int prev;
rgba_t color = { 255, 255, 255, 255 };
// draw the levelshot
x = 570;
y = 210;
w = 410;
h = 202;
// draw the levelshot
x = LEVELSHOT_X;
y = LEVELSHOT_Y;
w = LEVELSHOT_W;
h = LEVELSHOT_H;
UI_ScaleCoords( &x, &y, &w, &h );
UI_ScaleCoords( &x, &y, &w, &h );
if( uiLoadGame.games[uiLoadGame.currentGame].map[0] )
{
string pathJPG;
if( uiStatic.realTime - uiLoadGame.fadeTime >= 3000 )
{
uiLoadGame.fadeTime = uiStatic.realTime;
uiLoadGame.currentLevelShot++;
if( uiLoadGame.currentLevelShot == 3 )
uiLoadGame.currentLevelShot = 0;
}
prev = uiLoadGame.currentLevelShot - 1;
if( prev < 0 ) prev = 2;
color[3] = bound( 0.0f, (float)(uiStatic.realTime - uiLoadGame.fadeTime) * 0.001f, 1.0f ) * 255;
com.snprintf( pathJPG, sizeof( pathJPG ), "save/save%i.jpg", uiLoadGame.currentGame );
if( !FS_FileExists( pathJPG ))
UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
else UI_DrawPic( x, y, w, h, uiColorWhite, pathJPG );
}
else UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
// draw the blurred frame
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
}
else
if( com.strlen( uiLoadGame.saveName[uiLoadGame.savesList.curItem] ))
{
if( uiLoadGame.menu.items[uiLoadGame.menu.cursor] == self )
UI_DrawPic(item->x, item->y, item->width, item->height, uiColorWhite, UI_MOVEBOXFOCUS );
else UI_DrawPic(item->x, item->y, item->width, item->height, uiColorWhite, UI_MOVEBOX );
string pathJPG;
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
com.snprintf( pathJPG, sizeof( pathJPG ), "save/%s.jpg", uiLoadGame.saveName[uiLoadGame.savesList.curItem] );
if( !FS_FileExists( pathJPG ))
UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
else UI_DrawPic( x, y, w, h, uiColorWhite, pathJPG );
}
else UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
// draw the blurred frame
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
}
}
@ -297,11 +221,14 @@ UI_LoadGame_Init
*/
static void UI_LoadGame_Init( void )
{
int i, y;
Mem_Set( &uiLoadGame, 0, sizeof( uiLoadGame_t ));
uiLoadGame.fadeTime = uiStatic.realTime;
com.strncat( uiLoadGame.hintText, "Time", TIME_LENGTH );
com.strncat( uiLoadGame.hintText, uiEmptyString, TIME_LENGTH );
com.strncat( uiLoadGame.hintText, "Game", NAME_LENGTH );
com.strncat( uiLoadGame.hintText, uiEmptyString, NAME_LENGTH );
com.strncat( uiLoadGame.hintText, "Elapsed time", GAMETIME_LENGTH );
com.strncat( uiLoadGame.hintText, uiEmptyString, GAMETIME_LENGTH );
uiLoadGame.background.generic.id = ID_BACKGROUND;
uiLoadGame.background.generic.type = QMTYPE_BITMAP;
@ -315,119 +242,76 @@ static void UI_LoadGame_Init( void )
uiLoadGame.banner.generic.id = ID_BANNER;
uiLoadGame.banner.generic.type = QMTYPE_BITMAP;
uiLoadGame.banner.generic.flags = QMF_INACTIVE;
uiLoadGame.banner.generic.x = 0;
uiLoadGame.banner.generic.y = 66;
uiLoadGame.banner.generic.width = 1024;
uiLoadGame.banner.generic.height = 46;
uiLoadGame.banner.generic.x = 65;
uiLoadGame.banner.generic.y = 92;
uiLoadGame.banner.generic.width = 690;
uiLoadGame.banner.generic.height = 120;
uiLoadGame.banner.pic = ART_BANNER;
uiLoadGame.back.generic.id = ID_BACK;
uiLoadGame.back.generic.type = QMTYPE_BITMAP;
uiLoadGame.back.generic.x = 310;
uiLoadGame.back.generic.y = 656;
uiLoadGame.back.generic.width = 198;
uiLoadGame.back.generic.height = 38;
uiLoadGame.back.generic.callback = UI_LoadGame_Callback;
uiLoadGame.back.generic.ownerdraw = UI_LoadGame_Ownerdraw;
uiLoadGame.back.pic = UI_BACKBUTTON;
uiLoadGame.load.generic.id = ID_LOAD;
uiLoadGame.load.generic.type = QMTYPE_BITMAP;
uiLoadGame.load.generic.x = 516;
uiLoadGame.load.generic.y = 656;
uiLoadGame.load.generic.width = 198;
uiLoadGame.load.generic.height = 38;
uiLoadGame.load.generic.type = QMTYPE_ACTION;
uiLoadGame.load.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiLoadGame.load.generic.x = 72;
uiLoadGame.load.generic.y = 230;
uiLoadGame.load.generic.name = "Load";
uiLoadGame.load.generic.statusText = "Load saved game";
uiLoadGame.load.generic.callback = UI_LoadGame_Callback;
uiLoadGame.load.generic.ownerdraw = UI_LoadGame_Ownerdraw;
uiLoadGame.load.pic = UI_LOADBUTTON;
uiLoadGame.listBack.generic.id = ID_LISTBACK;
uiLoadGame.listBack.generic.type = QMTYPE_BITMAP;
uiLoadGame.listBack.generic.flags = QMF_INACTIVE;
uiLoadGame.listBack.generic.x = 42;
uiLoadGame.listBack.generic.y = 146;
uiLoadGame.listBack.generic.width = 462;
uiLoadGame.listBack.generic.height = 476;
uiLoadGame.listBack.pic = ART_LISTBACK;
uiLoadGame.delete.generic.id = ID_DELETE;
uiLoadGame.delete.generic.type = QMTYPE_ACTION;
uiLoadGame.delete.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiLoadGame.delete.generic.x = 72;
uiLoadGame.delete.generic.y = 280;
uiLoadGame.delete.generic.name = "Delete";
uiLoadGame.delete.generic.statusText = "Delete saved game";
uiLoadGame.delete.generic.callback = UI_LoadGame_Callback;
uiLoadGame.gameTitle.generic.id = ID_GAMETITLE;
uiLoadGame.gameTitle.generic.type = QMTYPE_ACTION;
uiLoadGame.gameTitle.generic.flags = QMF_INACTIVE|QMF_SMALLFONT;
uiLoadGame.gameTitle.generic.x = 42;
uiLoadGame.gameTitle.generic.y = 146;
uiLoadGame.gameTitle.generic.width = 462;
uiLoadGame.gameTitle.generic.height = 24;
uiLoadGame.gameTitle.generic.ownerdraw = UI_LoadGame_Ownerdraw;
uiLoadGame.cancel.generic.id = ID_CANCEL;
uiLoadGame.cancel.generic.type = QMTYPE_ACTION;
uiLoadGame.cancel.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiLoadGame.cancel.generic.x = 72;
uiLoadGame.cancel.generic.y = 330;
uiLoadGame.cancel.generic.name = "Cancel";
uiLoadGame.cancel.generic.statusText = "Return back to main menu";
uiLoadGame.cancel.generic.callback = UI_LoadGame_Callback;
for( i = 0, y = 182; i < UI_MAXGAMES; i++, y += 32 )
{
uiLoadGame.listGames[i].generic.id = ID_LISTGAMES+i;
uiLoadGame.listGames[i].generic.type = QMTYPE_ACTION;
uiLoadGame.listGames[i].generic.flags = QMF_SILENT|QMF_SMALLFONT;
uiLoadGame.listGames[i].generic.x = 42;
uiLoadGame.listGames[i].generic.y = y;
uiLoadGame.listGames[i].generic.width = 462;
uiLoadGame.listGames[i].generic.height = 24;
uiLoadGame.listGames[i].generic.callback = UI_LoadGame_Callback;
uiLoadGame.listGames[i].generic.ownerdraw = UI_LoadGame_Ownerdraw;
}
uiLoadGame.hintMessage.generic.id = ID_TABLEHINT;
uiLoadGame.hintMessage.generic.type = QMTYPE_ACTION;
uiLoadGame.hintMessage.generic.flags = QMF_INACTIVE|QMF_SMALLFONT;
uiLoadGame.hintMessage.generic.color = uiColorLtGrey;
uiLoadGame.hintMessage.generic.name = uiLoadGame.hintText;
uiLoadGame.hintMessage.generic.x = 360;
uiLoadGame.hintMessage.generic.y = 225;
uiLoadGame.levelShot.generic.id = ID_LEVELSHOT;
uiLoadGame.levelShot.generic.type = QMTYPE_BITMAP;
uiLoadGame.levelShot.generic.flags = QMF_INACTIVE;
uiLoadGame.levelShot.generic.x = 568;
uiLoadGame.levelShot.generic.y = 208;
uiLoadGame.levelShot.generic.width = 414;
uiLoadGame.levelShot.generic.height = 206;
uiLoadGame.levelShot.generic.x = LEVELSHOT_X;
uiLoadGame.levelShot.generic.y = LEVELSHOT_Y;
uiLoadGame.levelShot.generic.width = LEVELSHOT_W;
uiLoadGame.levelShot.generic.height = LEVELSHOT_H;
uiLoadGame.levelShot.generic.ownerdraw = UI_LoadGame_Ownerdraw;
uiLoadGame.levelShot.pic = ART_LEVELSHOTBLUR;
uiLoadGame.newGame.generic.id = ID_NEWGAME;
uiLoadGame.newGame.generic.type = QMTYPE_BITMAP;
uiLoadGame.newGame.generic.x = 676;
uiLoadGame.newGame.generic.y = 468;
uiLoadGame.newGame.generic.width = 198;
uiLoadGame.newGame.generic.height = 38;
uiLoadGame.newGame.generic.callback = UI_LoadGame_Callback;
uiLoadGame.newGame.generic.ownerdraw = UI_LoadGame_Ownerdraw;
uiLoadGame.newGame.pic = UI_NEWGAMEBUTTON;
uiLoadGame.saveGame.generic.id = ID_SAVEGAME;
uiLoadGame.saveGame.generic.type = QMTYPE_BITMAP;
uiLoadGame.saveGame.generic.x = 676;
uiLoadGame.saveGame.generic.y = 516;
uiLoadGame.saveGame.generic.width = 198;
uiLoadGame.saveGame.generic.height = 38;
uiLoadGame.saveGame.generic.callback = UI_LoadGame_Callback;
uiLoadGame.saveGame.generic.ownerdraw = UI_LoadGame_Ownerdraw;
uiLoadGame.saveGame.pic = UI_SAVEBUTTON;
uiLoadGame.deleteGame.generic.id = ID_DELETEGAME;
uiLoadGame.deleteGame.generic.type = QMTYPE_BITMAP;
uiLoadGame.deleteGame.generic.x = 676;
uiLoadGame.deleteGame.generic.y = 564;
uiLoadGame.deleteGame.generic.width = 198;
uiLoadGame.deleteGame.generic.height = 38;
uiLoadGame.deleteGame.generic.callback = UI_LoadGame_Callback;
uiLoadGame.deleteGame.generic.ownerdraw = UI_LoadGame_Ownerdraw;
uiLoadGame.deleteGame.pic = UI_DELETEBUTTON;
uiLoadGame.savesList.generic.id = ID_SAVELIST;
uiLoadGame.savesList.generic.type = QMTYPE_SCROLLLIST;
uiLoadGame.savesList.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_SMALLFONT;
uiLoadGame.savesList.generic.x = 360;
uiLoadGame.savesList.generic.y = 255;
uiLoadGame.savesList.generic.width = 640;
uiLoadGame.savesList.generic.height = 440;
uiLoadGame.savesList.generic.callback = UI_LoadGame_Callback;
UI_LoadGame_GetGameList();
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.background );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.banner );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.back );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.load );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.listBack );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.gameTitle );
for( i = 0; i < UI_MAXGAMES; i++ )
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.listGames[i] );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.delete );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.cancel );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.hintMessage );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.levelShot );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.newGame );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.saveGame );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.deleteGame );
UI_AddItem( &uiLoadGame.menu, (void *)&uiLoadGame.savesList );
}
/*
@ -441,7 +325,6 @@ void UI_LoadGame_Precache( void )
re->RegisterShader( ART_BACKGROUND, SHADER_NOMIP );
re->RegisterShader( ART_BANNER, SHADER_NOMIP );
re->RegisterShader( ART_LISTBACK, SHADER_NOMIP );
re->RegisterShader( ART_LEVELSHOTBLUR, SHADER_NOMIP );
}
@ -452,6 +335,11 @@ UI_LoadGame_Menu
*/
void UI_LoadGame_Menu( void )
{
string libpath;
Com_BuildPath( "server", libpath );
if( !FS_FileExists( libpath )) return;
UI_LoadGame_Precache();
UI_LoadGame_Init();

View File

@ -72,7 +72,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define UI_MAX_FIELD_LINE 256
#define UI_OUTLINE_WIDTH 4 // outline thickness
#define UI_MAXGAMES 14
#define UI_MAXGAMES 128
#define UI_MAX_SERVERS 10
// Generic types
@ -263,6 +263,7 @@ typedef struct
extern uiStatic_t uiStatic;
extern string uiEmptyString;
extern const char *uiSoundIn;
extern const char *uiSoundMove;
extern const char *uiSoundOut;

View File

@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "common.h"
#include "com_library.h"
#include "ui_local.h"
#include "input.h"
#include "client.h"
@ -72,28 +73,6 @@ typedef struct
static uiMain_t uiMain;
/*
=================
UI_Main_KeyFunc
=================
*/
static const char *UI_Main_KeyFunc( int key )
{
switch( key )
{
case K_ESCAPE:
case K_MOUSE2:
if( cls.state == ca_active )
{
// this shouldn't be happening, but for some reason it is in some mods
UI_CloseMenu();
return uiSoundNull;
}
return uiSoundNull;
}
return UI_DefaultKey( &uiMain.menu, key );
}
/*
=================
UI_MsgBox_Ownerdraw
@ -129,6 +108,24 @@ static void UI_QuitDialog( void )
}
/*
=================
UI_Main_KeyFunc
=================
*/
static const char *UI_Main_KeyFunc( int key )
{
switch( key )
{
case K_ESCAPE:
if( cls.state == ca_active )
UI_CloseMenu();
else UI_QuitDialog ();
return uiSoundNull;
}
return UI_DefaultKey( &uiMain.menu, key );
}
/*
=================
UI_Main_Callback
@ -192,6 +189,8 @@ UI_Main_Init
*/
static void UI_Main_Init( void )
{
string libpath;
Mem_Set( &uiMain, 0, sizeof( uiMain_t ));
uiMain.menu.keyFunc = UI_Main_KeyFunc;
@ -235,6 +234,11 @@ static void UI_Main_Init( void )
uiMain.saveRestore.generic.type = QMTYPE_ACTION;
uiMain.saveRestore.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
// server.dll needs for reading savefiles
Com_BuildPath( "server", libpath );
if( !FS_FileExists( libpath ))
uiMain.saveRestore.generic.flags |= QMF_GRAYED;
if( cls.state == ca_active )
{
uiMain.saveRestore.generic.name = "Save\\Load Game";

View File

@ -31,6 +31,7 @@ cvar_t *ui_sensitivity;
uiStatic_t uiStatic;
string uiEmptyString;
const char *uiSoundIn = "misc/menu1.wav";
const char *uiSoundMove = "misc/menu2.wav";
const char *uiSoundOut = "misc/menu3.wav";
@ -1037,6 +1038,7 @@ void UI_Init( void )
Cmd_AddCommand( "menu_demos", UI_Demos_Menu, "open the demos viewer menu" );
Cmd_AddCommand( "menu_customgame", UI_CustomGame_Menu, "open the change game menu" );
Mem_Set( uiEmptyString, ' ', sizeof( uiEmptyString ));
uiStatic.scaleX = scr_width->integer / 1024.0f;
uiStatic.scaleY = scr_height->integer / 768.0f;

View File

@ -33,6 +33,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ID_MODLIST 5
#define ID_TABLEHINT 6
#define TYPE_LENGTH 10
#define NAME_LENGTH 32+TYPE_LENGTH
#define VER_LENGTH 10+NAME_LENGTH
#define SIZE_LENGTH 10+VER_LENGTH
typedef struct
{
string modsDir[MAX_MODS];
@ -64,23 +69,24 @@ static void UI_CustomGame_GetModList( void )
{
int i;
Com_Assert( SIZE_LENGTH >= MAX_STRING );
for( i = 0; i < SI->numgames; i++ )
{
com.strncpy( uiCustomGame.modsDir[i], SI->games[i]->gamefolder, sizeof( uiCustomGame.modsDir[i] ));
com.strncpy( uiCustomGame.modsWebSites[i], SI->games[i]->game_url, sizeof( uiCustomGame.modsWebSites[i] ));
if( com.strlen( SI->games[i]->type ))
{
com.strncat( uiCustomGame.modsDescription[i], SI->games[i]->type, 10 );
com.strncat( uiCustomGame.modsDescription[i], " ", 10 ); // ugly method to fill remaining space
}
else com.strncat( uiCustomGame.modsDescription[i], " ", 10 );
com.strncat( uiCustomGame.modsDescription[i], SI->games[i]->title, 43 );
com.strncat( uiCustomGame.modsDescription[i], " ", 43 );
com.strncat( uiCustomGame.modsDescription[i], va( "%g", SI->games[i]->version ), 48 );
com.strncat( uiCustomGame.modsDescription[i], " ", 48 );
com.strncat( uiCustomGame.modsDescription[i], SI->games[i]->type, TYPE_LENGTH );
com.strncat( uiCustomGame.modsDescription[i], uiEmptyString, TYPE_LENGTH );
com.strncat( uiCustomGame.modsDescription[i], SI->games[i]->title, NAME_LENGTH );
com.strncat( uiCustomGame.modsDescription[i], uiEmptyString, NAME_LENGTH );
com.strncat( uiCustomGame.modsDescription[i], va( "%g", SI->games[i]->version ), VER_LENGTH );
com.strncat( uiCustomGame.modsDescription[i], uiEmptyString, VER_LENGTH );
if( SI->games[i]->size > 0 )
com.strncat( uiCustomGame.modsDescription[i], memprint( SI->games[i]->size ), MAX_STRING );
com.strncat( uiCustomGame.modsDescription[i], com.pretifymem( SI->games[i]->size, 0 ), SIZE_LENGTH );
else com.strncat( uiCustomGame.modsDescription[i], "0.0 Mb", SIZE_LENGTH );
com.strncat( uiCustomGame.modsDescription[i], uiEmptyString, SIZE_LENGTH );
uiCustomGame.modsDescriptionPtr[i] = uiCustomGame.modsDescription[i];
}
for( ; i < MAX_MODS; i++ ) uiCustomGame.modsDescriptionPtr[i] = NULL;
@ -147,7 +153,14 @@ static void UI_CustomGame_Init( void )
{
Mem_Set( &uiCustomGame, 0, sizeof( uiCustomGame_t ));
com.strncat( uiCustomGame.hintText, "Type Name Version Size", MAX_SYSPATH );
com.strncat( uiCustomGame.hintText, "Type", TYPE_LENGTH );
com.strncat( uiCustomGame.hintText, uiEmptyString, TYPE_LENGTH );
com.strncat( uiCustomGame.hintText, "Name", NAME_LENGTH );
com.strncat( uiCustomGame.hintText, uiEmptyString, NAME_LENGTH );
com.strncat( uiCustomGame.hintText, "Version", VER_LENGTH );
com.strncat( uiCustomGame.hintText, uiEmptyString, VER_LENGTH );
com.strncat( uiCustomGame.hintText, "Size", SIZE_LENGTH );
com.strncat( uiCustomGame.hintText, uiEmptyString, SIZE_LENGTH );
uiCustomGame.background.generic.id = ID_BACKGROUND;
uiCustomGame.background.generic.type = QMTYPE_BITMAP;
@ -200,7 +213,7 @@ static void UI_CustomGame_Init( void )
uiCustomGame.hintMessage.generic.color = uiColorLtGrey;
uiCustomGame.hintMessage.generic.name = uiCustomGame.hintText;
uiCustomGame.hintMessage.generic.x = 360;
uiCustomGame.hintMessage.generic.y = 220;
uiCustomGame.hintMessage.generic.y = 225;
uiCustomGame.modList.generic.id = ID_MODLIST;
uiCustomGame.modList.generic.type = QMTYPE_SCROLLLIST;

View File

@ -19,62 +19,52 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "common.h"
#include "com_library.h"
#include "ui_local.h"
#include "client.h"
#define ART_BACKGROUND "gfx/shell/splash"
#define ART_BANNER "gfx/shell/banners/savegame_t"
#define ART_LISTBACK "gfx/shell/segments/files_box"
#define ART_BACKGROUND "gfx/shell/splash"
#define ART_BANNER "gfx/shell/head_save"
#define ART_LEVELSHOTBLUR "gfx/shell/segments/sp_mapshot"
#define ID_BACKGROUND 0
#define ID_BANNER 1
#define ID_SAVE 2
#define ID_DELETE 3
#define ID_CANCEL 4
#define ID_SAVELIST 5
#define ID_TABLEHINT 6
#define ID_LEVELSHOT 7
#define ID_BACK 2
#define ID_SAVE 3
#define LEVELSHOT_X 72
#define LEVELSHOT_Y 400
#define LEVELSHOT_W 192
#define LEVELSHOT_H 160
#define ID_LISTBACK 4
#define ID_GAMETITLE 5
#define ID_LISTGAMES 6
#define ID_LEVELSHOT 20
#define ID_NEWGAME 21
#define ID_LOADGAME 22
#define ID_DELETEGAME 23
#define TIME_LENGTH 20
#define NAME_LENGTH 32+TIME_LENGTH
#define GAMETIME_LENGTH 15+NAME_LENGTH
typedef struct
{
char map[80];
char time[16];
char date[16];
char name[32];
bool valid;
} uiSaveGameGame_t;
static rgba_t uiSaveGameColor = { 0, 76, 127, 255 };
typedef struct
{
uiSaveGameGame_t games[UI_MAXGAMES];
int currentGame;
int currentLevelShot;
long fadeTime;
char saveName[UI_MAXGAMES][CS_SIZE];
char delName[UI_MAXGAMES][CS_SIZE];
string saveDescription[UI_MAXGAMES];
char *saveDescriptionPtr[UI_MAXGAMES];
menuFramework_s menu;
menuBitmap_s background;
menuBitmap_s banner;
menuBitmap_s back;
menuBitmap_s save;
menuBitmap_s listBack;
menuAction_s gameTitle;
menuAction_s listGames[UI_MAXGAMES];
menuAction_s save;
menuAction_s delete;
menuAction_s cancel;
menuScrollList_s savesList;
menuBitmap_s levelShot;
menuBitmap_s newGame;
menuBitmap_s loadGame;
menuBitmap_s deleteGame;
menuAction_s hintMessage;
char hintText[MAX_SYSPATH];
} uiSaveGame_t;
static uiSaveGame_t uiSaveGame;
@ -87,47 +77,74 @@ UI_SaveGame_GetGameList
*/
static void UI_SaveGame_GetGameList( void )
{
string name;
int i;
string comment;
search_t *t;
int i = 0, j;
for( i = 0; i < UI_MAXGAMES; i++ )
t = FS_Search( "save/*.bin", true );
if( cls.state == ca_active )
{
if( !SV_GetComment( name, i ))
// create new entry for current save game
com.strncpy( uiSaveGame.saveName[i], "new", CS_SIZE );
com.strncat( uiSaveGame.saveDescription[i], "Current", TIME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, TIME_LENGTH ); // fill remaining entries
com.strncat( uiSaveGame.saveDescription[i], "New Saved Game", NAME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, NAME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], "New", GAMETIME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, GAMETIME_LENGTH );
uiSaveGame.saveDescriptionPtr[i] = uiSaveGame.saveDescription[i];
i++;
}
for( j = 0; t && j < t->numfilenames; i++, j++ )
{
if( i >= UI_MAXGAMES ) break;
if( !SV_GetComment( t->filenames[j], comment ))
{
// get name string even if not found - SV_GetComment can be mark saves
// as <CORRUPTED> <OLD VERSION> <EMPTY> etc
com.strncpy(uiSaveGame.games[i].name, name, sizeof( uiSaveGame.games[i].name ));
com.strncpy(uiSaveGame.games[i].map, "", sizeof( uiSaveGame.games[i].map ));
com.strncpy(uiSaveGame.games[i].time, "", sizeof( uiSaveGame.games[i].time ));
com.strncpy(uiSaveGame.games[i].date, "", sizeof( uiSaveGame.games[i].date ));
uiSaveGame.games[i].valid = false;
if( com.strlen( comment ))
{
// get name string even if not found - SV_GetComment can be mark saves
// as <CORRUPTED> <OLD VERSION> etc
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, TIME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], comment, NAME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, NAME_LENGTH );
uiSaveGame.saveDescriptionPtr[i] = uiSaveGame.saveDescription[i];
FS_FileBase( t->filenames[j], uiSaveGame.delName[i] );
}
else uiSaveGame.saveDescriptionPtr[i] = NULL;
continue;
}
com.strncpy( uiSaveGame.games[i].map, name + CS_SIZE + (CS_TIME * 2), CS_SIZE );
com.strncpy( uiSaveGame.games[i].time, name + CS_SIZE + CS_TIME, CS_TIME );
com.strncpy( uiSaveGame.games[i].date, name + CS_SIZE, CS_TIME );
com.strncpy( uiSaveGame.games[i].name, name, CS_SIZE );
uiSaveGame.games[i].valid = true;
// strip path, leave only filename (empty slots doesn't have savename)
FS_FileBase( t->filenames[j], uiSaveGame.saveName[i] );
FS_FileBase( t->filenames[j], uiSaveGame.delName[i] );
// fill save desc
com.strncat( uiSaveGame.saveDescription[i], comment + CS_SIZE, TIME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], " ", TIME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], comment + CS_SIZE + CS_TIME, TIME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, TIME_LENGTH ); // fill remaining entries
com.strncat( uiSaveGame.saveDescription[i], comment, NAME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, NAME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], comment + CS_SIZE + (CS_TIME * 2), GAMETIME_LENGTH );
com.strncat( uiSaveGame.saveDescription[i], uiEmptyString, GAMETIME_LENGTH );
uiSaveGame.saveDescriptionPtr[i] = uiSaveGame.saveDescription[i];
}
// select first empty slot
for( i = 0; i < UI_MAXGAMES; i++ )
{
if( !uiSaveGame.games[i].valid )
{
uiSaveGame.listGames[i].generic.color = uiSaveGameColor;
uiSaveGame.currentGame = i;
break;
}
}
for( ; i < UI_MAXGAMES; i++ ) uiSaveGame.saveDescriptionPtr[i] = NULL;
uiSaveGame.savesList.itemNames = uiSaveGame.saveDescriptionPtr;
// couldn't find an empty slot, so select first
if( i == UI_MAXGAMES )
{
uiSaveGame.listGames[i].generic.color = uiSaveGameColor;
uiSaveGame.currentGame = 0;
}
if( com.strlen( uiSaveGame.saveName[0] ) == 0 || cls.state != ca_active )
uiSaveGame.save.generic.flags |= QMF_GRAYED;
else uiSaveGame.save.generic.flags &= ~QMF_GRAYED;
if( com.strlen( uiSaveGame.delName[0] ) == 0 || cls.state != ca_active )
uiSaveGame.delete.generic.flags |= QMF_GRAYED;
else uiSaveGame.delete.generic.flags &= ~QMF_GRAYED;
if( t ) Mem_Free( t );
}
/*
@ -139,43 +156,44 @@ static void UI_SaveGame_Callback( void *self, int event )
{
menuCommon_s *item = (menuCommon_s *)self;
if( event != QM_ACTIVATED )
return;
if( item->type == QMTYPE_ACTION )
if( event == QM_CHANGED )
{
// reset color, get current game, set color
uiSaveGame.listGames[uiSaveGame.currentGame].generic.color = uiColorWhite;
uiSaveGame.currentGame = item->id - ID_LISTGAMES;
uiSaveGame.listGames[uiSaveGame.currentGame].generic.color = uiSaveGameColor;
// never overwrite existing saves, because their names was never get collision
if( com.stricmp( uiSaveGame.saveName[uiSaveGame.savesList.curItem], "new" ))
uiSaveGame.save.generic.flags |= QMF_GRAYED;
else uiSaveGame.save.generic.flags &= ~QMF_GRAYED;
// restart levelshot animation
uiSaveGame.currentLevelShot = 0;
uiSaveGame.fadeTime = uiStatic.realTime;
if( com.strlen( uiSaveGame.delName[uiSaveGame.savesList.curItem] ) == 0 )
uiSaveGame.delete.generic.flags |= QMF_GRAYED;
else uiSaveGame.delete.generic.flags &= ~QMF_GRAYED;
return;
}
if( event != QM_ACTIVATED )
return;
switch( item->id )
{
case ID_BACK:
case ID_CANCEL:
UI_PopMenu();
break;
case ID_SAVE:
if( Host_ServerState())
if( com.strlen( uiSaveGame.saveName[uiSaveGame.savesList.curItem] ))
{
Cbuf_ExecuteText( EXEC_APPEND, va( "save save%i\n", uiSaveGame.currentGame ));
Cbuf_ExecuteText( EXEC_APPEND, va( "save \"%s\"\n", uiSaveGame.saveName[uiSaveGame.savesList.curItem] ));
UI_CloseMenu();
}
break;
case ID_NEWGAME:
UI_NewGame_Menu();
break;
case ID_LOADGAME:
UI_LoadGame_Menu();
break;
case ID_DELETEGAME:
Cbuf_ExecuteText( EXEC_NOW, va( "delete save%i\n", uiSaveGame.currentGame ));
UI_SaveGame_GetGameList();
case ID_DELETE:
if( com.strlen( uiSaveGame.delName[uiSaveGame.savesList.curItem] ))
{
string pathJPG;
com.snprintf( pathJPG, sizeof( pathJPG ), "save/%s.jpg", uiSaveGame.saveName[uiSaveGame.savesList.curItem] );
Cbuf_ExecuteText( EXEC_NOW, va( "delete \"%s\"\n", uiSaveGame.delName[uiSaveGame.savesList.curItem] ));
if( re ) re->FreeShader( pathJPG );
UI_SaveGame_GetGameList();
}
break;
}
}
@ -189,107 +207,32 @@ static void UI_SaveGame_Ownerdraw( void *self )
{
menuCommon_s *item = (menuCommon_s *)self;
if( item->type == QMTYPE_ACTION )
if( item->type != QMTYPE_ACTION && item->id == ID_LEVELSHOT )
{
rgba_t color;
char *time, *date, *name;
bool centered;
int x, y, w, h;
if( item->id == ID_GAMETITLE )
{
time = "Time";
date = "Date";
name = "Map Name";
centered = false;
}
else
{
time = uiSaveGame.games[item->id - ID_LISTGAMES].time;
date = uiSaveGame.games[item->id - ID_LISTGAMES].date;
name = uiSaveGame.games[item->id - ID_LISTGAMES].name;
centered = !uiSaveGame.games[item->id - ID_LISTGAMES].valid;
if( com.strstr( uiSaveGame.games[item->id - ID_LISTGAMES].name, "<empty>" ))
centered = true;
if( com.strstr( uiSaveGame.games[item->id - ID_LISTGAMES].name, "<corrupted>" ))
centered = true;
}
if( !centered )
{
UI_DrawString( item->x, item->y, 82*uiStatic.scaleX, item->height, time, item->color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX, item->y, 82*uiStatic.scaleX, item->height, date, item->color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX + 83*uiStatic.scaleX, item->y, 296*uiStatic.scaleX, item->height, name, item->color, true, item->charWidth, item->charHeight, 1, true );
}
else UI_DrawString( item->x, item->y, item->width, item->height, name, item->color, true, item->charWidth, item->charHeight, 1, true );
if( self != UI_ItemAtCursor( item->parent ))
return;
*(uint *)color = *(uint *)item->color;
color[3] = 255 * (0.5 + 0.5 * com.sin( uiStatic.realTime / UI_PULSE_DIVISOR ));
if( !centered )
{
UI_DrawString( item->x, item->y, 82*uiStatic.scaleX, item->height, time, color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX, item->y, 82*uiStatic.scaleX, item->height, date, color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX + 83*uiStatic.scaleX, item->y, 296*uiStatic.scaleX, item->height, name, color, true, item->charWidth, item->charHeight, 1, true );
}
else UI_DrawString( item->x, item->y, item->width, item->height, name, color, true, item->charWidth, item->charHeight, 1, true );
}
else
{
if( item->id == ID_LEVELSHOT )
{
int x, y, w, h;
int prev;
rgba_t color = { 255, 255, 255, 255 };
// draw the levelshot
x = 570;
y = 210;
w = 410;
h = 202;
// draw the levelshot
x = LEVELSHOT_X;
y = LEVELSHOT_Y;
w = LEVELSHOT_W;
h = LEVELSHOT_H;
UI_ScaleCoords( &x, &y, &w, &h );
UI_ScaleCoords( &x, &y, &w, &h );
if( uiSaveGame.games[uiSaveGame.currentGame].map[0] )
{
string pathJPG;
if( uiStatic.realTime - uiSaveGame.fadeTime >= 3000 )
{
uiSaveGame.fadeTime = uiStatic.realTime;
uiSaveGame.currentLevelShot++;
if( uiSaveGame.currentLevelShot == 3 )
uiSaveGame.currentLevelShot = 0;
}
prev = uiSaveGame.currentLevelShot - 1;
if( prev < 0 ) prev = 2;
color[3] = bound( 0.0f, (float)(uiStatic.realTime - uiSaveGame.fadeTime) * 0.001f, 1.0f ) * 255;
com.snprintf( pathJPG, sizeof( pathJPG ), "save/save%i.jpg", uiSaveGame.currentGame );
if( !FS_FileExists( pathJPG ))
UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
else UI_DrawPic( x, y, w, h, uiColorWhite, pathJPG );
}
else UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
// draw the blurred frame
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
}
else
if( com.strlen( uiSaveGame.saveName[uiSaveGame.savesList.curItem] ))
{
if( uiSaveGame.menu.items[uiSaveGame.menu.cursor] == self )
UI_DrawPic(item->x, item->y, item->width, item->height, uiColorWhite, UI_MOVEBOXFOCUS );
else UI_DrawPic(item->x, item->y, item->width, item->height, uiColorWhite, UI_MOVEBOX );
string pathJPG;
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
com.snprintf( pathJPG, sizeof( pathJPG ), "save/%s.jpg", uiSaveGame.saveName[uiSaveGame.savesList.curItem] );
if( !FS_FileExists( pathJPG ))
UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
else UI_DrawPic( x, y, w, h, uiColorWhite, pathJPG );
}
else UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
// draw the blurred frame
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
}
}
@ -300,11 +243,14 @@ UI_SaveGame_Init
*/
static void UI_SaveGame_Init( void )
{
int i, y;
Mem_Set( &uiSaveGame, 0, sizeof( uiSaveGame_t ));
uiSaveGame.fadeTime = uiStatic.realTime;
com.strncat( uiSaveGame.hintText, "Time", TIME_LENGTH );
com.strncat( uiSaveGame.hintText, uiEmptyString, TIME_LENGTH );
com.strncat( uiSaveGame.hintText, "Game", NAME_LENGTH );
com.strncat( uiSaveGame.hintText, uiEmptyString, NAME_LENGTH );
com.strncat( uiSaveGame.hintText, "Elapsed time", GAMETIME_LENGTH );
com.strncat( uiSaveGame.hintText, uiEmptyString, GAMETIME_LENGTH );
uiSaveGame.background.generic.id = ID_BACKGROUND;
uiSaveGame.background.generic.type = QMTYPE_BITMAP;
@ -318,119 +264,76 @@ static void UI_SaveGame_Init( void )
uiSaveGame.banner.generic.id = ID_BANNER;
uiSaveGame.banner.generic.type = QMTYPE_BITMAP;
uiSaveGame.banner.generic.flags = QMF_INACTIVE;
uiSaveGame.banner.generic.x = 0;
uiSaveGame.banner.generic.y = 66;
uiSaveGame.banner.generic.width = 1024;
uiSaveGame.banner.generic.height = 46;
uiSaveGame.banner.generic.x = 65;
uiSaveGame.banner.generic.y = 92;
uiSaveGame.banner.generic.width = 690;
uiSaveGame.banner.generic.height = 120;
uiSaveGame.banner.pic = ART_BANNER;
uiSaveGame.back.generic.id = ID_BACK;
uiSaveGame.back.generic.type = QMTYPE_BITMAP;
uiSaveGame.back.generic.x = 310;
uiSaveGame.back.generic.y = 656;
uiSaveGame.back.generic.width = 198;
uiSaveGame.back.generic.height = 38;
uiSaveGame.back.generic.callback = UI_SaveGame_Callback;
uiSaveGame.back.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.back.pic = UI_BACKBUTTON;
uiSaveGame.save.generic.id = ID_SAVE;
uiSaveGame.save.generic.type = QMTYPE_BITMAP;
uiSaveGame.save.generic.x = 516;
uiSaveGame.save.generic.y = 656;
uiSaveGame.save.generic.width = 198;
uiSaveGame.save.generic.height = 38;
uiSaveGame.save.generic.type = QMTYPE_ACTION;
uiSaveGame.save.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiSaveGame.save.generic.x = 72;
uiSaveGame.save.generic.y = 230;
uiSaveGame.save.generic.name = "Save";
uiSaveGame.save.generic.statusText = "Save saved game";
uiSaveGame.save.generic.callback = UI_SaveGame_Callback;
uiSaveGame.save.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.save.pic = UI_SAVEBUTTON;
uiSaveGame.listBack.generic.id = ID_LISTBACK;
uiSaveGame.listBack.generic.type = QMTYPE_BITMAP;
uiSaveGame.listBack.generic.flags = QMF_INACTIVE;
uiSaveGame.listBack.generic.x = 42;
uiSaveGame.listBack.generic.y = 146;
uiSaveGame.listBack.generic.width = 462;
uiSaveGame.listBack.generic.height = 476;
uiSaveGame.listBack.pic = ART_LISTBACK;
uiSaveGame.delete.generic.id = ID_DELETE;
uiSaveGame.delete.generic.type = QMTYPE_ACTION;
uiSaveGame.delete.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiSaveGame.delete.generic.x = 72;
uiSaveGame.delete.generic.y = 280;
uiSaveGame.delete.generic.name = "Delete";
uiSaveGame.delete.generic.statusText = "Delete saved game";
uiSaveGame.delete.generic.callback = UI_SaveGame_Callback;
uiSaveGame.gameTitle.generic.id = ID_GAMETITLE;
uiSaveGame.gameTitle.generic.type = QMTYPE_ACTION;
uiSaveGame.gameTitle.generic.flags = QMF_INACTIVE;
uiSaveGame.gameTitle.generic.x = 42;
uiSaveGame.gameTitle.generic.y = 146;
uiSaveGame.gameTitle.generic.width = 462;
uiSaveGame.gameTitle.generic.height = 24;
uiSaveGame.gameTitle.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.cancel.generic.id = ID_CANCEL;
uiSaveGame.cancel.generic.type = QMTYPE_ACTION;
uiSaveGame.cancel.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiSaveGame.cancel.generic.x = 72;
uiSaveGame.cancel.generic.y = 330;
uiSaveGame.cancel.generic.name = "Cancel";
uiSaveGame.cancel.generic.statusText = "Return back to main menu";
uiSaveGame.cancel.generic.callback = UI_SaveGame_Callback;
for( i = 0, y = 182; i < UI_MAXGAMES; i++, y += 32 )
{
uiSaveGame.listGames[i].generic.id = ID_LISTGAMES+i;
uiSaveGame.listGames[i].generic.type = QMTYPE_ACTION;
uiSaveGame.listGames[i].generic.flags = QMF_SILENT;
uiSaveGame.listGames[i].generic.x = 42;
uiSaveGame.listGames[i].generic.y = y;
uiSaveGame.listGames[i].generic.width = 462;
uiSaveGame.listGames[i].generic.height = 24;
uiSaveGame.listGames[i].generic.callback = UI_SaveGame_Callback;
uiSaveGame.listGames[i].generic.ownerdraw = UI_SaveGame_Ownerdraw;
}
uiSaveGame.hintMessage.generic.id = ID_TABLEHINT;
uiSaveGame.hintMessage.generic.type = QMTYPE_ACTION;
uiSaveGame.hintMessage.generic.flags = QMF_INACTIVE|QMF_SMALLFONT;
uiSaveGame.hintMessage.generic.color = uiColorLtGrey;
uiSaveGame.hintMessage.generic.name = uiSaveGame.hintText;
uiSaveGame.hintMessage.generic.x = 360;
uiSaveGame.hintMessage.generic.y = 225;
uiSaveGame.levelShot.generic.id = ID_LEVELSHOT;
uiSaveGame.levelShot.generic.type = QMTYPE_BITMAP;
uiSaveGame.levelShot.generic.flags = QMF_INACTIVE;
uiSaveGame.levelShot.generic.x = 568;
uiSaveGame.levelShot.generic.y = 208;
uiSaveGame.levelShot.generic.width = 414;
uiSaveGame.levelShot.generic.height = 206;
uiSaveGame.levelShot.generic.x = LEVELSHOT_X;
uiSaveGame.levelShot.generic.y = LEVELSHOT_Y;
uiSaveGame.levelShot.generic.width = LEVELSHOT_W;
uiSaveGame.levelShot.generic.height = LEVELSHOT_H;
uiSaveGame.levelShot.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.levelShot.pic = ART_LEVELSHOTBLUR;
uiSaveGame.newGame.generic.id = ID_NEWGAME;
uiSaveGame.newGame.generic.type = QMTYPE_BITMAP;
uiSaveGame.newGame.generic.x = 676;
uiSaveGame.newGame.generic.y = 468;
uiSaveGame.newGame.generic.width = 198;
uiSaveGame.newGame.generic.height = 38;
uiSaveGame.newGame.generic.callback = UI_SaveGame_Callback;
uiSaveGame.newGame.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.newGame.pic = UI_NEWGAMEBUTTON;
uiSaveGame.loadGame.generic.id = ID_LOADGAME;
uiSaveGame.loadGame.generic.type = QMTYPE_BITMAP;
uiSaveGame.loadGame.generic.x = 676;
uiSaveGame.loadGame.generic.y = 516;
uiSaveGame.loadGame.generic.width = 198;
uiSaveGame.loadGame.generic.height = 38;
uiSaveGame.loadGame.generic.callback = UI_SaveGame_Callback;
uiSaveGame.loadGame.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.loadGame.pic = UI_LOADBUTTON;
uiSaveGame.deleteGame.generic.id = ID_DELETEGAME;
uiSaveGame.deleteGame.generic.type = QMTYPE_BITMAP;
uiSaveGame.deleteGame.generic.x = 676;
uiSaveGame.deleteGame.generic.y = 564;
uiSaveGame.deleteGame.generic.width = 198;
uiSaveGame.deleteGame.generic.height = 38;
uiSaveGame.deleteGame.generic.callback = UI_SaveGame_Callback;
uiSaveGame.deleteGame.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.deleteGame.pic = UI_DELETEBUTTON;
uiSaveGame.savesList.generic.id = ID_SAVELIST;
uiSaveGame.savesList.generic.type = QMTYPE_SCROLLLIST;
uiSaveGame.savesList.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_SMALLFONT;
uiSaveGame.savesList.generic.x = 360;
uiSaveGame.savesList.generic.y = 255;
uiSaveGame.savesList.generic.width = 640;
uiSaveGame.savesList.generic.height = 440;
uiSaveGame.savesList.generic.callback = UI_SaveGame_Callback;
UI_SaveGame_GetGameList();
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.background );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.banner );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.back );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.save );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.listBack );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.gameTitle );
for( i = 0; i < UI_MAXGAMES; i++ )
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.listGames[i] );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.delete );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.cancel );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.hintMessage );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.levelShot );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.newGame );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.loadGame );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.deleteGame );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.savesList );
}
/*
@ -444,7 +347,6 @@ void UI_SaveGame_Precache( void )
re->RegisterShader( ART_BACKGROUND, SHADER_NOMIP );
re->RegisterShader( ART_BANNER, SHADER_NOMIP );
re->RegisterShader( ART_LISTBACK, SHADER_NOMIP );
re->RegisterShader( ART_LEVELSHOTBLUR, SHADER_NOMIP );
}
@ -455,6 +357,11 @@ UI_SaveGame_Menu
*/
void UI_SaveGame_Menu( void )
{
string libpath;
Com_BuildPath( "server", libpath );
if( !FS_FileExists( libpath )) return;
UI_SaveGame_Precache();
UI_SaveGame_Init();

View File

@ -0,0 +1,462 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "common.h"
#include "ui_local.h"
#include "client.h"
#define ART_BACKGROUND "gfx/shell/splash"
#define ART_BANNER "gfx/shell/banners/savegame_t"
#define ART_LISTBACK "gfx/shell/segments/files_box"
#define ART_LEVELSHOTBLUR "gfx/shell/segments/sp_mapshot"
#define ID_BACKGROUND 0
#define ID_BANNER 1
#define ID_BACK 2
#define ID_SAVE 3
#define ID_LISTBACK 4
#define ID_GAMETITLE 5
#define ID_LISTGAMES 6
#define ID_LEVELSHOT 20
#define ID_NEWGAME 21
#define ID_LOADGAME 22
#define ID_DELETEGAME 23
typedef struct
{
char map[80];
char time[16];
char date[16];
char name[32];
bool valid;
} uiSaveGameGame_t;
static rgba_t uiSaveGameColor = { 0, 76, 127, 255 };
typedef struct
{
uiSaveGameGame_t games[UI_MAXGAMES];
int currentGame;
int currentLevelShot;
long fadeTime;
menuFramework_s menu;
menuBitmap_s background;
menuBitmap_s banner;
menuBitmap_s back;
menuBitmap_s save;
menuBitmap_s listBack;
menuAction_s gameTitle;
menuAction_s listGames[UI_MAXGAMES];
menuBitmap_s levelShot;
menuBitmap_s newGame;
menuBitmap_s loadGame;
menuBitmap_s deleteGame;
} uiSaveGame_t;
static uiSaveGame_t uiSaveGame;
/*
=================
UI_SaveGame_GetGameList
=================
*/
static void UI_SaveGame_GetGameList( void )
{
string name;
int i;
for( i = 0; i < UI_MAXGAMES; i++ )
{
if( !SV_GetComment( name, i ))
{
// get name string even if not found - SV_GetComment can be mark saves
// as <CORRUPTED> <OLD VERSION> <EMPTY> etc
com.strncpy(uiSaveGame.games[i].name, name, sizeof( uiSaveGame.games[i].name ));
com.strncpy(uiSaveGame.games[i].map, "", sizeof( uiSaveGame.games[i].map ));
com.strncpy(uiSaveGame.games[i].time, "", sizeof( uiSaveGame.games[i].time ));
com.strncpy(uiSaveGame.games[i].date, "", sizeof( uiSaveGame.games[i].date ));
uiSaveGame.games[i].valid = false;
continue;
}
com.strncpy( uiSaveGame.games[i].map, name + CS_SIZE + (CS_TIME * 2), CS_SIZE );
com.strncpy( uiSaveGame.games[i].time, name + CS_SIZE + CS_TIME, CS_TIME );
com.strncpy( uiSaveGame.games[i].date, name + CS_SIZE, CS_TIME );
com.strncpy( uiSaveGame.games[i].name, name, CS_SIZE );
uiSaveGame.games[i].valid = true;
}
// select first empty slot
for( i = 0; i < UI_MAXGAMES; i++ )
{
if( !uiSaveGame.games[i].valid )
{
uiSaveGame.listGames[i].generic.color = uiSaveGameColor;
uiSaveGame.currentGame = i;
break;
}
}
// couldn't find an empty slot, so select first
if( i == UI_MAXGAMES )
{
uiSaveGame.listGames[i].generic.color = uiSaveGameColor;
uiSaveGame.currentGame = 0;
}
}
/*
=================
UI_SaveGame_Callback
=================
*/
static void UI_SaveGame_Callback( void *self, int event )
{
menuCommon_s *item = (menuCommon_s *)self;
if( event != QM_ACTIVATED )
return;
if( item->type == QMTYPE_ACTION )
{
// reset color, get current game, set color
uiSaveGame.listGames[uiSaveGame.currentGame].generic.color = uiColorWhite;
uiSaveGame.currentGame = item->id - ID_LISTGAMES;
uiSaveGame.listGames[uiSaveGame.currentGame].generic.color = uiSaveGameColor;
// restart levelshot animation
uiSaveGame.currentLevelShot = 0;
uiSaveGame.fadeTime = uiStatic.realTime;
return;
}
switch( item->id )
{
case ID_BACK:
UI_PopMenu();
break;
case ID_SAVE:
if( Host_ServerState())
{
Cbuf_ExecuteText( EXEC_APPEND, va( "save save%i\n", uiSaveGame.currentGame ));
UI_CloseMenu();
}
break;
case ID_NEWGAME:
UI_NewGame_Menu();
break;
case ID_LOADGAME:
UI_LoadGame_Menu();
break;
case ID_DELETEGAME:
Cbuf_ExecuteText( EXEC_NOW, va( "delete save%i\n", uiSaveGame.currentGame ));
UI_SaveGame_GetGameList();
break;
}
}
/*
=================
UI_SaveGame_Ownerdraw
=================
*/
static void UI_SaveGame_Ownerdraw( void *self )
{
menuCommon_s *item = (menuCommon_s *)self;
if( item->type == QMTYPE_ACTION )
{
rgba_t color;
char *time, *date, *name;
bool centered;
if( item->id == ID_GAMETITLE )
{
time = "Time";
date = "Date";
name = "Map Name";
centered = false;
}
else
{
time = uiSaveGame.games[item->id - ID_LISTGAMES].time;
date = uiSaveGame.games[item->id - ID_LISTGAMES].date;
name = uiSaveGame.games[item->id - ID_LISTGAMES].name;
centered = !uiSaveGame.games[item->id - ID_LISTGAMES].valid;
if( com.strstr( uiSaveGame.games[item->id - ID_LISTGAMES].name, "<empty>" ))
centered = true;
if( com.strstr( uiSaveGame.games[item->id - ID_LISTGAMES].name, "<corrupted>" ))
centered = true;
}
if( !centered )
{
UI_DrawString( item->x, item->y, 82*uiStatic.scaleX, item->height, time, item->color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX, item->y, 82*uiStatic.scaleX, item->height, date, item->color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX + 83*uiStatic.scaleX, item->y, 296*uiStatic.scaleX, item->height, name, item->color, true, item->charWidth, item->charHeight, 1, true );
}
else UI_DrawString( item->x, item->y, item->width, item->height, name, item->color, true, item->charWidth, item->charHeight, 1, true );
if( self != UI_ItemAtCursor( item->parent ))
return;
*(uint *)color = *(uint *)item->color;
color[3] = 255 * (0.5 + 0.5 * com.sin( uiStatic.realTime / UI_PULSE_DIVISOR ));
if( !centered )
{
UI_DrawString( item->x, item->y, 82*uiStatic.scaleX, item->height, time, color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX, item->y, 82*uiStatic.scaleX, item->height, date, color, true, item->charWidth, item->charHeight, 1, true );
UI_DrawString( item->x + 83*uiStatic.scaleX + 83*uiStatic.scaleX, item->y, 296*uiStatic.scaleX, item->height, name, color, true, item->charWidth, item->charHeight, 1, true );
}
else UI_DrawString( item->x, item->y, item->width, item->height, name, color, true, item->charWidth, item->charHeight, 1, true );
}
else
{
if( item->id == ID_LEVELSHOT )
{
int x, y, w, h;
int prev;
rgba_t color = { 255, 255, 255, 255 };
// draw the levelshot
x = 570;
y = 210;
w = 410;
h = 202;
UI_ScaleCoords( &x, &y, &w, &h );
if( uiSaveGame.games[uiSaveGame.currentGame].map[0] )
{
string pathJPG;
if( uiStatic.realTime - uiSaveGame.fadeTime >= 3000 )
{
uiSaveGame.fadeTime = uiStatic.realTime;
uiSaveGame.currentLevelShot++;
if( uiSaveGame.currentLevelShot == 3 )
uiSaveGame.currentLevelShot = 0;
}
prev = uiSaveGame.currentLevelShot - 1;
if( prev < 0 ) prev = 2;
color[3] = bound( 0.0f, (float)(uiStatic.realTime - uiSaveGame.fadeTime) * 0.001f, 1.0f ) * 255;
com.snprintf( pathJPG, sizeof( pathJPG ), "save/save%i.jpg", uiSaveGame.currentGame );
if( !FS_FileExists( pathJPG ))
UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
else UI_DrawPic( x, y, w, h, uiColorWhite, pathJPG );
}
else UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/hud/static" );
// draw the blurred frame
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
}
else
{
if( uiSaveGame.menu.items[uiSaveGame.menu.cursor] == self )
UI_DrawPic(item->x, item->y, item->width, item->height, uiColorWhite, UI_MOVEBOXFOCUS );
else UI_DrawPic(item->x, item->y, item->width, item->height, uiColorWhite, UI_MOVEBOX );
UI_DrawPic( item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic );
}
}
}
/*
=================
UI_SaveGame_Init
=================
*/
static void UI_SaveGame_Init( void )
{
int i, y;
Mem_Set( &uiSaveGame, 0, sizeof( uiSaveGame_t ));
uiSaveGame.fadeTime = uiStatic.realTime;
uiSaveGame.background.generic.id = ID_BACKGROUND;
uiSaveGame.background.generic.type = QMTYPE_BITMAP;
uiSaveGame.background.generic.flags = QMF_INACTIVE;
uiSaveGame.background.generic.x = 0;
uiSaveGame.background.generic.y = 0;
uiSaveGame.background.generic.width = 1024;
uiSaveGame.background.generic.height = 768;
uiSaveGame.background.pic = ART_BACKGROUND;
uiSaveGame.banner.generic.id = ID_BANNER;
uiSaveGame.banner.generic.type = QMTYPE_BITMAP;
uiSaveGame.banner.generic.flags = QMF_INACTIVE;
uiSaveGame.banner.generic.x = 0;
uiSaveGame.banner.generic.y = 66;
uiSaveGame.banner.generic.width = 1024;
uiSaveGame.banner.generic.height = 46;
uiSaveGame.banner.pic = ART_BANNER;
uiSaveGame.back.generic.id = ID_BACK;
uiSaveGame.back.generic.type = QMTYPE_BITMAP;
uiSaveGame.back.generic.x = 310;
uiSaveGame.back.generic.y = 656;
uiSaveGame.back.generic.width = 198;
uiSaveGame.back.generic.height = 38;
uiSaveGame.back.generic.callback = UI_SaveGame_Callback;
uiSaveGame.back.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.back.pic = UI_BACKBUTTON;
uiSaveGame.save.generic.id = ID_SAVE;
uiSaveGame.save.generic.type = QMTYPE_BITMAP;
uiSaveGame.save.generic.x = 516;
uiSaveGame.save.generic.y = 656;
uiSaveGame.save.generic.width = 198;
uiSaveGame.save.generic.height = 38;
uiSaveGame.save.generic.callback = UI_SaveGame_Callback;
uiSaveGame.save.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.save.pic = UI_SAVEBUTTON;
uiSaveGame.listBack.generic.id = ID_LISTBACK;
uiSaveGame.listBack.generic.type = QMTYPE_BITMAP;
uiSaveGame.listBack.generic.flags = QMF_INACTIVE;
uiSaveGame.listBack.generic.x = 42;
uiSaveGame.listBack.generic.y = 146;
uiSaveGame.listBack.generic.width = 462;
uiSaveGame.listBack.generic.height = 476;
uiSaveGame.listBack.pic = ART_LISTBACK;
uiSaveGame.gameTitle.generic.id = ID_GAMETITLE;
uiSaveGame.gameTitle.generic.type = QMTYPE_ACTION;
uiSaveGame.gameTitle.generic.flags = QMF_INACTIVE;
uiSaveGame.gameTitle.generic.x = 42;
uiSaveGame.gameTitle.generic.y = 146;
uiSaveGame.gameTitle.generic.width = 462;
uiSaveGame.gameTitle.generic.height = 24;
uiSaveGame.gameTitle.generic.ownerdraw = UI_SaveGame_Ownerdraw;
for( i = 0, y = 182; i < UI_MAXGAMES; i++, y += 32 )
{
uiSaveGame.listGames[i].generic.id = ID_LISTGAMES+i;
uiSaveGame.listGames[i].generic.type = QMTYPE_ACTION;
uiSaveGame.listGames[i].generic.flags = QMF_SILENT;
uiSaveGame.listGames[i].generic.x = 42;
uiSaveGame.listGames[i].generic.y = y;
uiSaveGame.listGames[i].generic.width = 462;
uiSaveGame.listGames[i].generic.height = 24;
uiSaveGame.listGames[i].generic.callback = UI_SaveGame_Callback;
uiSaveGame.listGames[i].generic.ownerdraw = UI_SaveGame_Ownerdraw;
}
uiSaveGame.levelShot.generic.id = ID_LEVELSHOT;
uiSaveGame.levelShot.generic.type = QMTYPE_BITMAP;
uiSaveGame.levelShot.generic.flags = QMF_INACTIVE;
uiSaveGame.levelShot.generic.x = 568;
uiSaveGame.levelShot.generic.y = 208;
uiSaveGame.levelShot.generic.width = 414;
uiSaveGame.levelShot.generic.height = 206;
uiSaveGame.levelShot.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.levelShot.pic = ART_LEVELSHOTBLUR;
uiSaveGame.newGame.generic.id = ID_NEWGAME;
uiSaveGame.newGame.generic.type = QMTYPE_BITMAP;
uiSaveGame.newGame.generic.x = 676;
uiSaveGame.newGame.generic.y = 468;
uiSaveGame.newGame.generic.width = 198;
uiSaveGame.newGame.generic.height = 38;
uiSaveGame.newGame.generic.callback = UI_SaveGame_Callback;
uiSaveGame.newGame.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.newGame.pic = UI_NEWGAMEBUTTON;
uiSaveGame.loadGame.generic.id = ID_LOADGAME;
uiSaveGame.loadGame.generic.type = QMTYPE_BITMAP;
uiSaveGame.loadGame.generic.x = 676;
uiSaveGame.loadGame.generic.y = 516;
uiSaveGame.loadGame.generic.width = 198;
uiSaveGame.loadGame.generic.height = 38;
uiSaveGame.loadGame.generic.callback = UI_SaveGame_Callback;
uiSaveGame.loadGame.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.loadGame.pic = UI_LOADBUTTON;
uiSaveGame.deleteGame.generic.id = ID_DELETEGAME;
uiSaveGame.deleteGame.generic.type = QMTYPE_BITMAP;
uiSaveGame.deleteGame.generic.x = 676;
uiSaveGame.deleteGame.generic.y = 564;
uiSaveGame.deleteGame.generic.width = 198;
uiSaveGame.deleteGame.generic.height = 38;
uiSaveGame.deleteGame.generic.callback = UI_SaveGame_Callback;
uiSaveGame.deleteGame.generic.ownerdraw = UI_SaveGame_Ownerdraw;
uiSaveGame.deleteGame.pic = UI_DELETEBUTTON;
UI_SaveGame_GetGameList();
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.background );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.banner );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.back );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.save );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.listBack );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.gameTitle );
for( i = 0; i < UI_MAXGAMES; i++ )
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.listGames[i] );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.levelShot );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.newGame );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.loadGame );
UI_AddItem( &uiSaveGame.menu, (void *)&uiSaveGame.deleteGame );
}
/*
=================
UI_SaveGame_Precache
=================
*/
void UI_SaveGame_Precache( void )
{
if( !re ) return;
re->RegisterShader( ART_BACKGROUND, SHADER_NOMIP );
re->RegisterShader( ART_BANNER, SHADER_NOMIP );
re->RegisterShader( ART_LISTBACK, SHADER_NOMIP );
re->RegisterShader( ART_LEVELSHOTBLUR, SHADER_NOMIP );
}
/*
=================
UI_SaveGame_Menu
=================
*/
void UI_SaveGame_Menu( void )
{
UI_SaveGame_Precache();
UI_SaveGame_Init();
UI_PushMenu( &uiSaveGame.menu );
}

View File

@ -525,8 +525,8 @@ const char* com_timestamp( int format )
strftime(timestring, sizeof (timestring), "%Y", crt_tm);
break;
case TIME_FILENAME:
// Build a timestamp that can use for filename (ex: "Nov2006-26 (19.14)");
strftime(timestring, sizeof (timestring), "%b%Y-%d (%H.%M)", crt_tm);
// Build a timestamp that can use for filename (ex: "Nov2006-26 (19.14.28)");
strftime(timestring, sizeof (timestring), "%b%Y-%d_%H.%M.%S", crt_tm);
break;
default: return NULL;
}

View File

@ -141,6 +141,7 @@ typedef struct render_exp_s
bool (*RegisterModel)( const char *name, int cl_index ); // also build replacement index table
shader_t (*RegisterShader)( const char *name, int shaderType );
void (*EndRegistration)( const char *skyname );
void (*FreeShader)( const char *shadername );
// prepare frame to rendering
bool (*AddRefEntity)( edict_t *pRefEntity, int ed_type );

View File

@ -2390,6 +2390,7 @@ render_exp_t DLLEXPORT *CreateAPI(stdlib_api_t *input, render_imp_t *engfuncs )
re.RegisterModel = R_UploadModel;
re.RegisterShader = Mod_RegisterShader;
re.EndRegistration = R_EndRegistration;
re.FreeShader = Mod_FreeShader;
re.AddLightStyle = R_AddLightStyle;
re.AddRefEntity = R_AddEntityToScene;

View File

@ -2715,6 +2715,38 @@ void Shader_FreeShader( ref_shader_t *shader )
Mem_Set( shader, 0, sizeof( ref_shader_t ));
}
void Mod_FreeShader( const char *name )
{
ref_shader_t *shader;
string shortname;
ref_script_t *cache = NULL;
uint i, hashKey, length;
if( !name || !name[0] ) return;
for( i = ( name[0] == '/' || name[0] == '\\' ), length = 0; name[i] && ( length < sizeof( shortname )-1 ); i++ )
{
if( name[i] == '\\' ) shortname[length++] = '/';
else shortname[length++] = com.tolower( name[i] );
}
if( !length ) return;
shortname[length] = 0;
// see if already loaded
hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE );
for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash )
{
if( !com.stricmp( shader->name, shortname ))
{
// remove shader
Shader_FreeShader( shader );
return;
}
}
}
void R_ShutdownShaders( void )
{
int i;

View File

@ -347,6 +347,7 @@ void R_ShutdownShaders( void );
void R_ShaderList_f( void );
void R_ShaderDump_f( void );
ref_shader_t *R_LoadShader( const char *name, int type, bool forceDefault, int addFlags, int ignoreType );
void Mod_FreeShader( const char *name ); // used for delete save menu previews only
// misc utilities
void R_ShaderFreeUnused( void );