This repository has been archived on 2022-06-27. You can view files and clone it, but cannot push or open issues or pull requests.
Xash3DArchive/engine/uimenu/ui_savegame.c

464 lines
14 KiB
C

/*
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/misc/ui_sub_singleplayer"
#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:
if( cls.state == ca_active )
UI_InGame_Menu();
else UI_Main_Menu();
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_SinglePlayer_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/shell/menu_levelshots/unknownmap" );
else UI_DrawPic( x, y, w, h, uiColorWhite, pathJPG );
}
else UI_DrawPic( x, y, w, h, uiColorWhite, "gfx/shell/menu_levelshots/unknownmap" );
// 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 );
}