fteqw/engine/client/m_single.c
Spoike 9ae7e2621d SOFTWARE RENDERING IS BROKEN: DO NOT USE ASM VERSION.
Lots of changes.
CSQC should be functional, but is still tied to debug builds. It WILL have some bugs still, hopefully I'll be able to clean them up better if people test it a bit.
Precompiled headers are working properly now. Compile times are now much quicker in msvc. This takes most of the files this commit.
Restructured how client commands work. They're buffered outside the network message, some multithreaded code is in. It needs a bit of testing before it's active.


git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@885 fc73d0e0-1445-4013-8a0c-d673dee63da5
2005-02-28 07:16:19 +00:00

482 lines
12 KiB
C

//read menu.h
#include "quakedef.h"
#include "winquake.h"
#ifndef CLIENTONLY
//=============================================================================
/* LOAD/SAVE MENU */
#define FTESAVEGAME_VERSION 25000
typedef struct {
int issave;
int cursorpos;
menutext_t *cursoritem;
} loadsavemenuinfo_t;
#define MAX_SAVEGAMES 20
char m_filenames[MAX_SAVEGAMES][SAVEGAME_COMMENT_LENGTH+1];
int loadable[MAX_SAVEGAMES];
menubutton_t *VARGS MC_AddConsoleCommandf(menu_t *menu, int x, int y, char *text, char *command, ...);
void M_ScanSaves (void)
{
int i, j;
char name[MAX_OSPATH];
FILE *f;
int version;
for (i=0 ; i<MAX_SAVEGAMES ; i++)
{
strcpy (m_filenames[i], "--- UNUSED SLOT ---");
loadable[i] = false;
sprintf (name, "%s/saves/s%i/info.fsv", com_gamedir, i);
f = fopen (name, "rb");
if (f)
{
fscanf (f, "%i\n", &version);
if (version != FTESAVEGAME_VERSION)
{
Q_strncpyz (m_filenames[i], "Incompatable version", sizeof(m_filenames[i]));
fclose (f);
continue;
}
fscanf (f, "%79s\n", name);
Q_strncpyz (m_filenames[i], name, sizeof(m_filenames[i]));
// change _ back to space
for (j=0 ; j<SAVEGAME_COMMENT_LENGTH ; j++)
if (m_filenames[i][j] == '_')
m_filenames[i][j] = ' ';
loadable[i] = true;
fclose (f);
continue;
}
/*
sprintf (name, "%s/s%i.sav", com_gamedir, i);
f = fopen (name, "rb");
if (!f)
continue;
fscanf (f, "%i\n", &version);
if (version != SAVEGAME_VERSION && version != 5 && version != 6)
{
Q_strncpyz (m_filenames[i], "Incompatable version", sizeof(m_filenames[i]));
fclose (f);
continue;
}
else
{
fscanf (f, "%79s\n", name);
Q_strncpyz (m_filenames[i], name, sizeof(m_filenames[i]));
}
// change _ back to space
for (j=0 ; j<SAVEGAME_COMMENT_LENGTH ; j++)
if (m_filenames[i][j] == '_')
m_filenames[i][j] = ' ';
loadable[i] = true;
fclose (f);*/
}
}
void M_Menu_Save_f (void)
{
menuoption_t *op = NULL;
menu_t *menu;
int i;
if (!sv.state)
return;
if (cl.intermission)
return;
key_dest = key_menu;
m_state = m_complex;
m_entersound = true;
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
menu->data = menu+1;
MC_AddCenterPicture (menu, 4, "gfx/p_save.lmp");
menu->cursoritem = (menuoption_t *)MC_AddRedText(menu, 8, 32, NULL, false);
M_ScanSaves ();
for (i=0 ; i< MAX_SAVEGAMES; i++)
{
op = (menuoption_t *)MC_AddConsoleCommandf(menu, 16, 32+8*i, m_filenames[i], "savegame s%i\ntogglemenu\n", i);
if (!menu->selecteditem)
menu->selecteditem = op;
}
}
void M_Menu_Load_f (void)
{
menuoption_t *op = NULL;
menu_t *menu;
int i;
key_dest = key_menu;
m_state = m_complex;
m_entersound = true;
menu = M_CreateMenu(sizeof(loadsavemenuinfo_t));
menu->data = menu+1;
MC_AddCenterPicture(menu, 4, "gfx/p_load.lmp");
menu->cursoritem = (menuoption_t *)MC_AddRedText(menu, 8, 32, NULL, false);
M_ScanSaves ();
for (i=0 ; i< MAX_SAVEGAMES; i++)
{
if (loadable[i])
op = (menuoption_t *)MC_AddConsoleCommandf(menu, 16, 32+8*i, m_filenames[i], "loadgame s%i\ntogglemenu\n", i);
else
MC_AddWhiteText(menu, 16, 32+8*i, m_filenames[i], false);
if (!menu->selecteditem && op)
menu->selecteditem = op;
}
}
#endif
void M_Menu_SinglePlayer_f (void)
{
int q1, q2, h2;
menubutton_t *b;
menu_t *menu;
mpic_t *p;
key_dest = key_menu;
m_state = m_complex;
m_entersound = true;
q1 = COM_FDepthFile("gfx/sp_menu.lmp", true);
h2 = COM_FDepthFile("gfx/menu/title2.lmp", true);
q2 = COM_FDepthFile("pics/m_banner_game.pcx", true);
if (q2 < h2 && q2 < q1)
{ //q2...
menu = M_CreateMenu(0);
MC_AddCenterPicture(menu, 4, "m_banner_game");
menu->selecteditem = (menuoption_t*)
MC_AddConsoleCommand (menu, 64, 40, "Easy", "skill 0;deathmatch 0; coop 0;newgame\n");
MC_AddConsoleCommand (menu, 64, 48, "Medium", "skill 1;deathmatch 0; coop 0;newgame\n");
MC_AddConsoleCommand (menu, 64, 56, "Hard", "skill 2;deathmatch 0; coop 0;newgame\n");
MC_AddConsoleCommand (menu, 64, 72, "Load Game", "menu_load\n");
MC_AddConsoleCommand (menu, 64, 80, "Save Game", "menu_save\n");
return;
}
else if (h2 < q1)
{ //h2
menu = M_CreateMenu(0);
MC_AddPicture(menu, 16, 0, "gfx/menu/hplaque.lmp");
MC_AddCenterPicture(menu, 0, "gfx/menu/title1.lmp");
menu->selecteditem = (menuoption_t*)
MC_AddConsoleCommand (menu, 64, 64, "Easy", "togglemenu\nskill 0;deathmatch 0; coop 0;map demo1\n");
MC_AddConsoleCommand (menu, 64, 72, "Medium", "togglemenu\nskill 1;deathmatch 0; coop 0;map demo1\n");
MC_AddConsoleCommand (menu, 64, 80, "Hard", "togglemenu\nskill 2;deathmatch 0; coop 0;map demo1\n");
// MC_AddConsoleCommand (menu, 64, 96, "Load Game", "menu_load\n");
MC_AddConsoleCommand (menu, 64, 104, "Save Game", "menu_save\n");
return;
}
else
{ //q1
menu = M_CreateMenu(0);
MC_AddPicture(menu, 16, 4, "gfx/qplaque.lmp");
MC_AddCenterPicture(menu, 4, "gfx/p_option.lmp");
}
p = Draw_CachePic("gfx/sp_menu.lmp");
if (!p)
{
MC_AddBox (menu, 60, 10*8, 23, 4);
MC_AddWhiteText(menu, 92, 12*8, "Could find file", false);
MC_AddWhiteText(menu, 92, 13*8, "gfx/sp_menu.lmp", false);
}
else
{
#ifdef CLIENTONLY
MC_AddBox (menu, 60, 10*8, 23, 4);
MC_AddWhiteText(menu, 92, 12*8, "QuakeWorld is for", false);
MC_AddWhiteText(menu, 92, 13*8, "Internet play only", false);
#else
MC_AddPicture(menu, 72, 32, "gfx/sp_menu.lmp");
b = MC_AddConsoleCommand (menu, 16, 32, "", "togglemenu\nmaxclients 1;deathmatch 0;coop 0;map start\n");
menu->selecteditem = (menuoption_t *)b;
b->common.width = p->width;
b->common.height = 20;
b = MC_AddConsoleCommand (menu, 16, 52, "", "menu_load\n");
b->common.width = p->width;
b->common.height = 20;
b = MC_AddConsoleCommand (menu, 16, 72, "", "menu_save\n");
b->common.width = p->width;
b->common.height = 20;
menu->cursoritem = (menuoption_t*)MC_AddCursor(menu, 54, 32);
#endif
}
}
typedef struct {
menucustom_t *list;
int nummatches;
int selected;
int firstshown;
int maxmatches;
int pathlen;
char *command[64]; //these let the menu be used for nearly any sort of file browser.
char *ext[64];
int numext;
struct demofilelist_s{
char name[64];
int size;
} *options;
} demomenu_t;
void M_DemoDraw(int x, int y, menucustom_t *control, menu_t *menu)
{
char *text;
int i;
demomenu_t *info = menu->data;
if (info->firstshown > info->selected)
info->firstshown = info->selected;
if ((vid.height - y)/8 < info->selected - info->firstshown+2)
info->firstshown = info->selected - (vid.height - y)/8+2;
i = info->firstshown;
while(i < info->nummatches)
{
if (info->options[i].size)
text = va("%-30s %6iKB", info->options[i].name+info->pathlen, info->options[i].size/1024);
else
text = info->options[i].name+info->pathlen;
if (i == info->selected)
Draw_Alt_String(x+8, y+8, text);
else
Draw_String(x+8, y+8, text);
y+=8;
i++;
}
}
void ShowDemoMenu (menu_t *menu, char *path);
qboolean M_DemoKey(menucustom_t *control, menu_t *menu, int key)
{
demomenu_t *info = menu->data;
if (!info->nummatches)
return false;
switch (key)
{
case K_UPARROW:
info->selected--;
if (info->selected < 0)
info->selected = 0;
return true;
case K_DOWNARROW:
info->selected++;
if (info->selected > info->nummatches-1)
info->selected = info->nummatches-1;
return true;
case K_PGUP:
info->selected-=10;
if (info->selected < 0)
info->selected = 0;
return true;
case K_PGDN:
info->selected+=10;
if (info->selected > info->nummatches-1)
info->selected = info->nummatches-1;
return true;
case K_ENTER:
if (info->options[info->selected].name[strlen(info->options[info->selected].name)-1] == '/') //last char is a slash
ShowDemoMenu(menu, va("%s", info->options[info->selected].name));
else
{
int extnum;
for (extnum = 0; extnum < info->numext; extnum++)
if (!stricmp(info->options[info->selected].name + strlen(info->options[info->selected].name)-4, info->ext[extnum]))
break;
if (extnum == info->numext) //wasn't on our list of extensions.
extnum = 0;
Cbuf_AddText(va("%s \"%s\"\n", info->command[extnum], info->options[info->selected].name), RESTRICT_LOCAL);
}
return true;
}
return false;
}
int DemoAddItem(char *filename, int size, void *parm)
{
int match;
int extnum;
demomenu_t *menu = parm;
if (filename[strlen(filename)-1] != '/')
{
for (extnum = 0; extnum < menu->numext; extnum++)
if (!stricmp(filename + strlen(filename)-4, menu->ext[extnum]))
break;
if (extnum == menu->numext) //wasn't on our list of extensions.
return true;
}
if (menu->maxmatches < menu->nummatches+10)
{
menu->maxmatches = menu->nummatches+10;
menu->options = BZ_Realloc(menu->options, menu->maxmatches*sizeof(struct demofilelist_s));
}
for (match = 0; match < menu->nummatches; match++)
if (!strcmp(menu->options[match].name, filename))
return true;
Q_strncpyz(menu->options[menu->nummatches].name, filename, sizeof(menu->options[menu->nummatches].name));
menu->options[menu->nummatches].size = size;
menu->nummatches++;
return true;
}
void M_Demo_Remove (menu_t *menu)
{
demomenu_t *info = menu->data;
if (info->options)
BZ_Free(info->options);
}
void ShowDemoMenu (menu_t *menu, char *path)
{
int c;
char *s;
char match[256];
while (!strcmp(path+strlen(path)-3, "../"))
{
c = 0;
for (s = path+strlen(path)-3; s >= path; s--)
{
if (*s == '/')
{
c++;
s[1] = '\0';
if (c == 2)
break;
}
}
if (c<2)
*path = '\0';
}
((demomenu_t*)menu->data)->nummatches = 0;
((demomenu_t*)menu->data)->firstshown = 0;
((demomenu_t*)menu->data)->selected = 0;
((demomenu_t*)menu->data)->pathlen = strlen(path);
if (*path)
{
sprintf(match, "%s../", path);
DemoAddItem(match, 0, menu->data);
}
sprintf(match, "%s*", path);
COM_EnumerateFiles(match, DemoAddItem, menu->data);
}
void M_Menu_Demos_f (void)
{
demomenu_t *info;
menu_t *menu;
key_dest = key_menu;
m_state = m_complex;
m_entersound = true;
menu = M_CreateMenu(sizeof(demomenu_t));
menu->remove = M_Demo_Remove;
info = menu->data;
info->command[0] = "playdemo";
info->ext[0] = ".qwd";
info->command[1] = "playdemo";
info->ext[1] = ".dem";
info->command[2] = "playdemo";
info->ext[2] = ".dm2";
info->command[3] = "playdemo";
info->ext[3] = ".mvd";
//there are also quizmo demos (.qwz) out there...
//we don't support them, but if we were to ask quizmo to decode them for us, we could do.
info->numext = 4;
MC_AddWhiteText(menu, 24, 8, "Demos", false);
MC_AddWhiteText(menu, 16, 24, "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37", false);
info->list = MC_AddCustom(menu, 0, 32, NULL);
info->list->draw = M_DemoDraw;
info->list->key = M_DemoKey;
menu->selecteditem = (menuoption_t*)info->list;
ShowDemoMenu(menu, "");
}
void M_Menu_MediaFiles_f (void)
{
demomenu_t *info;
menu_t *menu;
key_dest = key_menu;
m_state = m_complex;
m_entersound = true;
menu = M_CreateMenu(sizeof(demomenu_t));
menu->remove = M_Demo_Remove;
info = menu->data;
info->ext[0] = ".m3u";
info->command[0] = "mediaplaylist";
info->ext[1] = ".mp3";
info->command[1] = "mediaadd";
info->ext[2] = ".wav";
info->command[2] = "mediaadd";
info->ext[3] = ".ogg"; //will this ever be added properly?
info->command[3] = "mediaadd";
info->ext[4] = ".roq";
info->command[4] = "playfilm";
info->numext = 5;
#ifdef _WIN32 //avis are only playable on windows due to a windows dll being used to decode them.
info->ext[info->numext] = ".avi";
info->command[info->numext] = "playfilm";
info->numext++;
#endif
MC_AddWhiteText(menu, 24, 8, "Media List", false);
MC_AddWhiteText(menu, 16, 24, "\35\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\36\37", false);
info->list = MC_AddCustom(menu, 0, 32, NULL);
info->list->draw = M_DemoDraw;
info->list->key = M_DemoKey;
menu->selecteditem = (menuoption_t*)info->list;
ShowDemoMenu(menu, "");
}