mirror of
https://github.com/blendogames/thirtyflightsofloving.git
synced 2024-11-15 00:41:21 +00:00
add4c7cc46
Added new SCR_DrawPic() variants in cl_screen.c. Added new graphics for text fields and sliders in menus. Improved mouse interaction for menu sliders. Added resettargets developer command to default Lazarus and missionpack DLLs. Added hint_test developer command to missionpack DLL. Fixed freeze developer command in default Lazarus and missionpack DLLs so it can be used more than once. More tweaks to Tactician Gunner prox mine safety checks in misssionpack DLL.
1024 lines
24 KiB
C
1024 lines
24 KiB
C
/*
|
|
===========================================================================
|
|
Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
This file is part of Quake 2 source code.
|
|
|
|
Quake 2 source code 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.
|
|
|
|
Quake 2 source code 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 Quake 2 source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// console.c
|
|
|
|
#include "client.h"
|
|
|
|
console_t con;
|
|
|
|
cvar_t *con_notifytime;
|
|
qboolean newconback_found = false; // whether to draw Q3-style console
|
|
|
|
extern char key_lines[32][MAXCMDLINE];
|
|
extern int edit_line;
|
|
extern int key_linepos;
|
|
|
|
|
|
/*
|
|
================
|
|
Con_DrawString
|
|
================
|
|
*/
|
|
void Con_DrawString (int x, int y, char *string, fontslot_t font, int alpha)
|
|
{
|
|
CL_DrawStringGeneric (x, y, string, font, alpha, FONT_SIZE, SCALETYPE_CONSOLE, false);
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Key_ClearTyping
|
|
================
|
|
*/
|
|
void Key_ClearTyping (void)
|
|
{
|
|
key_lines[edit_line][1] = 0; // clear any typing
|
|
key_linepos = 1;
|
|
con.backedit = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_ToggleConsole_f
|
|
================
|
|
*/
|
|
void Con_ToggleConsole_f (void)
|
|
{
|
|
// SCR_EndLoadingPlaque (); // get rid of loading plaque
|
|
|
|
// Knightmare- allow disconnected menu
|
|
if (cls.state == ca_disconnected && cls.key_dest != key_menu)
|
|
{ // start the demo loop again
|
|
Cbuf_AddText ("d1\n");
|
|
return;
|
|
}
|
|
|
|
Key_ClearTyping ();
|
|
Con_ClearNotify ();
|
|
|
|
if (cls.consoleActive) // Knightmare changed
|
|
//if (cls.key_dest == key_console)
|
|
{
|
|
cls.consoleActive = false; // Knightmare added
|
|
|
|
//UI_ForceMenuOff ();
|
|
//if (cls.key_dest != key_menu)
|
|
if (Cvar_VariableValue ("maxclients") == 1
|
|
&& Com_ServerState () && cls.key_dest != key_menu)
|
|
Cvar_Set ("paused", "0");
|
|
}
|
|
else
|
|
{
|
|
cls.consoleActive = true; // Knightmare added
|
|
//UI_ForceMenuOff ();
|
|
//cls.key_dest = key_console;
|
|
|
|
if (Cvar_VariableValue ("maxclients") == 1
|
|
&& Com_ServerState () && cls.key_dest != key_menu)
|
|
Cvar_Set ("paused", "1");
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
Con_ToggleChat_f
|
|
================
|
|
*/
|
|
void Con_ToggleChat_f (void)
|
|
{
|
|
Key_ClearTyping ();
|
|
|
|
if (cls.consoleActive) // Knightmare added
|
|
//if (cls.key_dest == key_console)
|
|
{
|
|
if (cls.state == ca_active)
|
|
{
|
|
UI_ForceMenuOff ();
|
|
cls.consoleActive = false; // Knightmare added
|
|
cls.key_dest = key_game;
|
|
}
|
|
}
|
|
else
|
|
//cls.key_dest = key_console;
|
|
cls.consoleActive = true; // Knightmare added
|
|
|
|
Con_ClearNotify ();
|
|
}
|
|
|
|
/*
|
|
================
|
|
Con_Clear_f
|
|
================
|
|
*/
|
|
void Con_Clear_f (void)
|
|
{
|
|
memset (con.text, ' ', CON_TEXTSIZE);
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_Dump_f
|
|
|
|
Save the console contents out to a file
|
|
================
|
|
*/
|
|
void Con_Dump_f (void)
|
|
{
|
|
int l, x;
|
|
char *line;
|
|
FILE *f;
|
|
char buffer[1024];
|
|
char name[MAX_OSPATH];
|
|
|
|
if (Cmd_Argc() != 2)
|
|
{
|
|
Com_Printf ("usage: condump <filename>\n");
|
|
return;
|
|
}
|
|
|
|
Com_sprintf (name, sizeof(name), "%s/%s.txt", FS_Savegamedir(), Cmd_Argv(1)); // was FS_Gamedir()
|
|
|
|
Com_Printf ("Dumped console text to %s.\n", name);
|
|
FS_CreatePath (name);
|
|
f = fopen (name, "w");
|
|
if (!f)
|
|
{
|
|
Com_Printf ("ERROR: couldn't open.\n");
|
|
return;
|
|
}
|
|
|
|
// skip empty lines
|
|
for (l = con.current - con.totallines + 1 ; l <= con.current ; l++)
|
|
{
|
|
line = con.text + (l%con.totallines)*con.linewidth;
|
|
for (x=0 ; x<con.linewidth ; x++)
|
|
if (line[x] != ' ')
|
|
break;
|
|
if (x != con.linewidth)
|
|
break;
|
|
}
|
|
|
|
// write the remaining lines
|
|
buffer[con.linewidth] = 0;
|
|
for ( ; l <= con.current ; l++)
|
|
{
|
|
line = con.text + (l%con.totallines)*con.linewidth;
|
|
strncpy (buffer, line, con.linewidth);
|
|
for (x=con.linewidth-1 ; x>=0 ; x--)
|
|
{
|
|
if (buffer[x] == ' ')
|
|
buffer[x] = 0;
|
|
else
|
|
break;
|
|
}
|
|
for (x=0; buffer[x]; x++)
|
|
buffer[x] &= 0x7f;
|
|
|
|
fprintf (f, "%s\n", buffer);
|
|
}
|
|
|
|
fclose (f);
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_ClearNotify
|
|
================
|
|
*/
|
|
void Con_ClearNotify (void)
|
|
{
|
|
int i;
|
|
|
|
for (i=0 ; i<NUM_CON_TIMES ; i++)
|
|
con.times[i] = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_MessageMode_f
|
|
================
|
|
*/
|
|
void Con_MessageMode_f (void)
|
|
{
|
|
chat_team = false;
|
|
cls.key_dest = key_message;
|
|
cls.consoleActive = false; // Knightmare added
|
|
}
|
|
|
|
/*
|
|
================
|
|
Con_MessageMode2_f
|
|
================
|
|
*/
|
|
void Con_MessageMode2_f (void)
|
|
{
|
|
chat_team = true;
|
|
cls.key_dest = key_message;
|
|
cls.consoleActive = false; // Knightmare added
|
|
}
|
|
|
|
/*
|
|
================
|
|
Con_CheckResize
|
|
|
|
If the line width has changed, reformat the buffer.
|
|
================
|
|
*/
|
|
void Con_CheckResize (void)
|
|
{
|
|
int i, j, width, oldwidth, oldtotallines, numlines, numchars;
|
|
char tbuf[CON_TEXTSIZE];
|
|
|
|
if (con_font_size)
|
|
width = viddef.width/FONT_SIZE - 2;
|
|
else // (viddef.width / 8) - 2
|
|
width = (viddef.width >> 3) - 2;
|
|
width = min((MAXCMDLINE - 2), width); // clamp width to MAXCMDLINE - 2 to prevent buffer overflow
|
|
|
|
if (width == con.linewidth)
|
|
return;
|
|
|
|
if (width < 1) // video hasn't been initialized yet
|
|
{
|
|
width = 78; // was 38
|
|
con.linewidth = width;
|
|
con.backedit = 0;
|
|
con.totallines = CON_TEXTSIZE / con.linewidth;
|
|
memset (con.text, ' ', CON_TEXTSIZE);
|
|
}
|
|
else
|
|
{
|
|
oldwidth = con.linewidth;
|
|
con.linewidth = width;
|
|
con.backedit = 0;
|
|
oldtotallines = con.totallines;
|
|
con.totallines = CON_TEXTSIZE / con.linewidth;
|
|
numlines = oldtotallines;
|
|
|
|
if (con.totallines < numlines)
|
|
numlines = con.totallines;
|
|
|
|
numchars = oldwidth;
|
|
|
|
if (con.linewidth < numchars)
|
|
numchars = con.linewidth;
|
|
|
|
memcpy (tbuf, con.text, CON_TEXTSIZE);
|
|
memset (con.text, ' ', CON_TEXTSIZE);
|
|
|
|
for (i=0 ; i<numlines ; i++)
|
|
{
|
|
for (j=0 ; j<numchars ; j++)
|
|
{
|
|
con.text[(con.totallines - 1 - i) * con.linewidth + j] =
|
|
tbuf[((con.current - i + oldtotallines) %
|
|
oldtotallines) * oldwidth + j];
|
|
}
|
|
}
|
|
|
|
Con_ClearNotify ();
|
|
}
|
|
|
|
con.current = con.totallines - 1;
|
|
con.display = con.current;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_Init
|
|
================
|
|
*/
|
|
void Con_Init (void)
|
|
{
|
|
con.linewidth = -1;
|
|
con.backedit = 0;
|
|
|
|
Con_CheckResize ();
|
|
|
|
Com_Printf ("Console initialized.\n");
|
|
|
|
//
|
|
// register our commands
|
|
//
|
|
con_notifytime = Cvar_Get ("con_notifytime", "4", 0); // Knightmare- increased for fade
|
|
Cvar_SetDescription ("con_notifytime", "Time in seconds for console notify messages to fade away.");
|
|
|
|
Cmd_AddCommand ("toggleconsole", Con_ToggleConsole_f);
|
|
Cmd_AddCommand ("togglechat", Con_ToggleChat_f);
|
|
Cmd_AddCommand ("messagemode", Con_MessageMode_f);
|
|
Cmd_AddCommand ("messagemode2", Con_MessageMode2_f);
|
|
Cmd_AddCommand ("clear", Con_Clear_f);
|
|
Cmd_AddCommand ("condump", Con_Dump_f);
|
|
|
|
// whether to use new-style console background
|
|
newconback_found = false;
|
|
if ( (FS_LoadFile("gfx/ui/newconback.tga", NULL) != -1)
|
|
#ifdef PNG_SUPPORT
|
|
|| (FS_LoadFile("gfx/ui/newconback.png", NULL) != -1)
|
|
#endif // PNG_SUPPORT
|
|
|| (FS_LoadFile("gfx/ui/newconback.jpg", NULL) != -1) )
|
|
newconback_found = true;
|
|
|
|
con.initialized = true;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_Shutdown
|
|
================
|
|
*/
|
|
void Con_Shutdown (void)
|
|
{
|
|
Cmd_RemoveCommand ("toggleconsole");
|
|
Cmd_RemoveCommand ("togglechat");
|
|
Cmd_RemoveCommand ("messagemode");
|
|
Cmd_RemoveCommand ("messagemode2");
|
|
Cmd_RemoveCommand ("clear");
|
|
Cmd_RemoveCommand ("condump");
|
|
|
|
con.initialized = false;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
Con_StringSetParams
|
|
===============
|
|
*/
|
|
qboolean Con_StringSetParams (char modifier, char *colorCode, qboolean *bold, qboolean *shadow, qboolean *italic, qboolean *alt)
|
|
{
|
|
// sanity check
|
|
if (!colorCode || !bold || !shadow || !italic || !alt)
|
|
return false;
|
|
|
|
switch (modifier)
|
|
{
|
|
case 'R':
|
|
case 'r':
|
|
*colorCode = 0;
|
|
*bold = *shadow = *italic = *alt = false;
|
|
return true;
|
|
case 'B':
|
|
case 'b':
|
|
if (*bold)
|
|
*bold = false;
|
|
else
|
|
*bold = true;
|
|
return true;
|
|
case 'S':
|
|
case 's':
|
|
if (*shadow)
|
|
*shadow = false;
|
|
else
|
|
*shadow = true;
|
|
return true;
|
|
case 'I':
|
|
case 'i':
|
|
if (*italic)
|
|
*italic = false;
|
|
else
|
|
*italic = true;
|
|
return true;
|
|
case COLOR_RED:
|
|
case COLOR_GREEN:
|
|
case COLOR_YELLOW:
|
|
case COLOR_BLUE:
|
|
case COLOR_CYAN:
|
|
case COLOR_MAGENTA:
|
|
case COLOR_WHITE:
|
|
case COLOR_BLACK:
|
|
case COLOR_ORANGE:
|
|
case COLOR_GRAY:
|
|
*colorCode = modifier;
|
|
return true;
|
|
case 'A': // alt text color
|
|
case 'a':
|
|
*alt = true;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
===============
|
|
Con_Linefeed
|
|
===============
|
|
*/
|
|
void Con_Linefeed (char colorCode, qboolean bold, qboolean shadow, qboolean italic, qboolean alt)
|
|
{
|
|
int y;
|
|
|
|
con.x = 0;
|
|
if (con.display == con.current)
|
|
con.display++;
|
|
con.current++;
|
|
memset (&con.text[(con.current%con.totallines)*con.linewidth]
|
|
, ' ', con.linewidth);
|
|
|
|
// add any wrapped formatting
|
|
y = con.current % con.totallines;
|
|
if (colorCode != 0)
|
|
{
|
|
con.text[y*con.linewidth+con.x] = '^';
|
|
con.x++;
|
|
con.text[y*con.linewidth+con.x] = colorCode;
|
|
con.x++;
|
|
}
|
|
if (bold)
|
|
{
|
|
con.text[y*con.linewidth+con.x] = '^';
|
|
con.x++;
|
|
con.text[y*con.linewidth+con.x] = 'b';
|
|
con.x++;
|
|
}
|
|
if (shadow)
|
|
{
|
|
con.text[y*con.linewidth+con.x] = '^';
|
|
con.x++;
|
|
con.text[y*con.linewidth+con.x] = 's';
|
|
con.x++;
|
|
}
|
|
if (italic)
|
|
{
|
|
con.text[y*con.linewidth+con.x] = '^';
|
|
con.x++;
|
|
con.text[y*con.linewidth+con.x] = 'i';
|
|
con.x++;
|
|
}
|
|
if (alt)
|
|
{
|
|
con.text[y*con.linewidth+con.x] = '^';
|
|
con.x++;
|
|
con.text[y*con.linewidth+con.x] = 'a';
|
|
con.x++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
Con_Print
|
|
|
|
Handles cursor positioning, line wrapping, etc
|
|
All console printing must go through this in order to be logged to disk
|
|
If no console is visible, the text will appear at the top of the game window
|
|
================
|
|
*/
|
|
void Con_Print (char *txt)
|
|
{
|
|
int y, c, l; //, i;
|
|
static int cr;
|
|
int mask;
|
|
// vars for format wrapping
|
|
char modifier, colorCode = 0;
|
|
qboolean nextCharModifierCheck = false, bold = false, shadow = false, italic = false, alt = false;
|
|
|
|
if (!con.initialized)
|
|
return;
|
|
|
|
if (txt[0] == 1 || txt[0] == 2)
|
|
{
|
|
mask = 128; // go to colored text
|
|
txt++;
|
|
}
|
|
else
|
|
mask = 0;
|
|
|
|
|
|
while ( (c = *txt) )
|
|
{
|
|
// count word length
|
|
for (l=0 ; l< con.linewidth ; l++)
|
|
if ( txt[l] <= ' ')
|
|
break;
|
|
|
|
// word wrap
|
|
if (l != con.linewidth && (con.x + l > con.linewidth) ) {
|
|
con.x = 0;
|
|
}
|
|
|
|
txt++;
|
|
|
|
if (cr)
|
|
{
|
|
con.current--;
|
|
cr = false;
|
|
}
|
|
|
|
if (!con.x)
|
|
{
|
|
Con_Linefeed (colorCode, bold, shadow, italic, alt);
|
|
// mark time for transparent overlay
|
|
if (con.current >= 0)
|
|
con.times[con.current % NUM_CON_TIMES] = cls.realtime;
|
|
}
|
|
|
|
// track formatting codes for word wrap
|
|
modifier = (c & ~128);
|
|
if (nextCharModifierCheck) // last char was a ^
|
|
{
|
|
Con_StringSetParams (modifier, &colorCode, &bold, &shadow, &italic, &alt);
|
|
nextCharModifierCheck = false;
|
|
}
|
|
else {
|
|
// set var to check modifier if char is ^
|
|
nextCharModifierCheck = (modifier == '^') ? true : false;
|
|
}
|
|
|
|
switch (c)
|
|
{
|
|
case '\n':
|
|
con.x = 0;
|
|
colorCode = 0;
|
|
bold = shadow = italic = alt = false;
|
|
break;
|
|
|
|
case '\r':
|
|
con.x = 0;
|
|
cr = 1;
|
|
colorCode = 0;
|
|
bold = shadow = italic = alt = false;
|
|
break;
|
|
|
|
default: // display character and advance
|
|
y = con.current % con.totallines;
|
|
con.text[y*con.linewidth+con.x] = c | mask | con.ormask;
|
|
con.x++;
|
|
if (con.x >= con.linewidth)
|
|
con.x = 0;
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
==============
|
|
Con_CenteredPrint
|
|
==============
|
|
*/
|
|
void Con_CenteredPrint (char *text)
|
|
{
|
|
int l;
|
|
char buffer[1024];
|
|
|
|
l = (int)strlen(text);
|
|
l = (con.linewidth-l)/2;
|
|
if (l < 0)
|
|
l = 0;
|
|
memset (buffer, ' ', l);
|
|
// strncpy (buffer+l, text);
|
|
// strncat (buffer, "\n");
|
|
Q_strncpyz (buffer+l, sizeof(buffer)-1, text);
|
|
Q_strncatz (buffer, sizeof(buffer), "\n");
|
|
Con_Print (buffer);
|
|
}
|
|
|
|
/*
|
|
==============================================================================
|
|
|
|
DRAWING
|
|
|
|
==============================================================================
|
|
*/
|
|
|
|
|
|
/*
|
|
================
|
|
Con_DrawInput
|
|
The input line scrolls horizontally if typing goes beyond the right edge
|
|
================
|
|
*/
|
|
void Con_DrawInput (void)
|
|
{
|
|
int y;
|
|
int i;
|
|
char *text, output[2048], addch[8];
|
|
float conLeft = 0;
|
|
|
|
if (!cls.consoleActive && cls.state == ca_active)
|
|
return; // don't draw anything (always draw if not active)
|
|
|
|
SCR_ScaleCoords (&conLeft, NULL, NULL, NULL, ALIGN_STRETCH);
|
|
|
|
/*if (cls.key_dest == key_menu)
|
|
return;
|
|
if (cls.key_dest != key_console && cls.state == ca_active)
|
|
return;*/ // don't draw anything (always draw if not active)
|
|
|
|
text = key_lines[edit_line];
|
|
|
|
// add the cursor frame
|
|
if (con.backedit)
|
|
text[key_linepos] = ' ';
|
|
else
|
|
text[key_linepos] = 10+((int)(cls.realtime>>8)&1);
|
|
|
|
// fill out remainder with spaces
|
|
for (i=key_linepos+1 ; i< con.linewidth ; i++)
|
|
text[i] = ' ';
|
|
|
|
// prestep if horizontally scrolling
|
|
if (key_linepos >= con.linewidth)
|
|
text += 1 + key_linepos - con.linewidth;
|
|
|
|
// draw it
|
|
y = con.vislines-FONT_SIZE*2; // was 16
|
|
|
|
Com_sprintf (output, sizeof(output), "");
|
|
for (i=0; i<con.linewidth; i++)
|
|
{
|
|
if (con.backedit == key_linepos-i && ((int)(cls.realtime>>8)&1)) {
|
|
// Com_sprintf (output, sizeof(output), "%s%c", output, 11 );
|
|
addch[0] = 11;
|
|
addch[1] = '\0';
|
|
Q_strncatz (output, sizeof(output), addch);
|
|
}
|
|
else {
|
|
// Com_sprintf (output, sizeof(output), "%s%c", output, text[i]);
|
|
addch[0] = text[i];
|
|
addch[1] = '\0';
|
|
Q_strncatz (output, sizeof(output), addch);
|
|
}
|
|
}
|
|
Con_DrawString ( (int)conLeft + FONT_SIZE/2, con.vislines - (int)(2.75*FONT_SIZE), output, FONT_CONSOLE, 255);
|
|
|
|
// remove cursor
|
|
key_lines[edit_line][key_linepos] = 0;
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_DrawNotify
|
|
Draws the last few lines of output transparently over the game top
|
|
================
|
|
*/
|
|
void Con_DrawNotify (void)
|
|
{
|
|
int x;
|
|
char *text, output[2048], addch[8];
|
|
int i, j;
|
|
// int time;
|
|
char *s;
|
|
int alpha, lines;
|
|
float v, time, conLeft, conWidth;
|
|
|
|
lines = 0;
|
|
v = 0;
|
|
|
|
conLeft = 0;
|
|
conWidth = SCREEN_WIDTH;
|
|
SCR_ScaleCoords (&conLeft, NULL, &conWidth, NULL, ALIGN_STRETCH);
|
|
|
|
Com_sprintf (output, sizeof(output), "");
|
|
|
|
// this is the say msg while typeing...
|
|
if (cls.key_dest == key_message)
|
|
{
|
|
if (chat_team)
|
|
Com_sprintf (output, sizeof(output), "%s", " say_team: ");
|
|
else
|
|
Com_sprintf (output, sizeof(output), "%s", " say: ");
|
|
|
|
s = chat_buffer;
|
|
x = 0;
|
|
if (chat_bufferlen > (viddef.width/FONT_SIZE)-(strlen(output)+1))
|
|
x += chat_bufferlen - (int)((viddef.width/FONT_SIZE)-(strlen(output)+1));
|
|
|
|
while (s[x])
|
|
{
|
|
if ( chat_backedit && (chat_backedit == chat_bufferlen-x) && ((int)(cls.realtime>>8)&1) ) {
|
|
// Com_sprintf (output, sizeof(output), "%s%c", output, 11 );
|
|
addch[0] = 11;
|
|
addch[1] = '\0';
|
|
Q_strncatz (output, sizeof(output), addch);
|
|
}
|
|
else {
|
|
// Com_sprintf (output, sizeof(output), "%s%c", output, (char)s[x]);
|
|
addch[0] = s[x];
|
|
addch[1] = '\0';
|
|
Q_strncatz (output, sizeof(output), addch);
|
|
}
|
|
|
|
x++;
|
|
}
|
|
|
|
if (!chat_backedit) {
|
|
// Com_sprintf (output, sizeof(output), "%s%c", output, 10+((int)(cls.realtime>>8)&1) );
|
|
addch[0] = 10+((int)(cls.realtime>>8)&1);
|
|
addch[1] = '\0';
|
|
Q_strncatz (output, sizeof(output), addch);
|
|
}
|
|
|
|
Con_DrawString ((int)conLeft, v, output, FONT_SCREEN, 255);
|
|
|
|
v += FONT_SIZE*2; // make extra space so we have room
|
|
}
|
|
|
|
for (i = con.current-NUM_CON_TIMES+1; i <= con.current; i++)
|
|
{
|
|
if (i < 0)
|
|
continue;
|
|
time = con.times[i % NUM_CON_TIMES];
|
|
if (time == 0)
|
|
continue;
|
|
time = cls.realtime - time;
|
|
if (time > con_notifytime->value*1000)
|
|
continue;
|
|
|
|
// vertical offset set by closest to dissapearing
|
|
lines++;
|
|
}
|
|
|
|
// v = 0;
|
|
if (lines)
|
|
for (j = 0, i = con.current-NUM_CON_TIMES+1; i <= con.current; i++, j++)
|
|
{
|
|
if (i < 0)
|
|
continue;
|
|
time = con.times[i % NUM_CON_TIMES];
|
|
if (time == 0)
|
|
continue;
|
|
time = cls.realtime - time;
|
|
if (time > con_notifytime->value*1000)
|
|
continue;
|
|
|
|
text = con.text + (i % con.totallines)*con.linewidth;
|
|
|
|
alpha = 255 * sqrt( (1.0-time/(con_notifytime->value*1000.0+1.0)) * (((float)v+8.0)) / (8.0*lines) );
|
|
// alpha = (1-time/(con_notifytime->value*1000.0+2)) * (255*(v+16)) / (4*lines);
|
|
if (alpha < 0) alpha = 0;
|
|
if (alpha > 255) alpha = 255;
|
|
|
|
Com_sprintf (output, sizeof(output), "");
|
|
for (x = 0; x < con.linewidth; x++) {
|
|
// Com_sprintf (output, sizeof(output), "%s%c", output, (char)text[x]);
|
|
addch[0] = (char)text[x];
|
|
addch[1] = '\0';
|
|
Q_strncatz (output, sizeof(output), addch);
|
|
}
|
|
|
|
Con_DrawString ((int)conLeft + FONT_SIZE/2, v, output, FONT_SCREEN, alpha);
|
|
|
|
v += FONT_SIZE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_DrawDownloadProgress
|
|
|
|
Draws a download progress bar
|
|
================
|
|
*/
|
|
void Con_DrawDownloadProgress (float conLeft, float conWidth, float conLineHeight, int verLen, int red, int green, int blue)
|
|
{
|
|
int i, j, x, y, len;
|
|
char *text;
|
|
char dlbar[1024];
|
|
int graph_x, graph_y, graph_h, graph_w;
|
|
|
|
if ((text = strrchr(cls.downloadname, '/')) != NULL)
|
|
text++;
|
|
else
|
|
text = cls.downloadname;
|
|
|
|
memset (dlbar, 0, sizeof(dlbar)); // clear dlbar
|
|
|
|
// make this a little shorter in case of longer version string
|
|
x = con.linewidth - ((con.linewidth * 7) / 40) - (verLen-14);
|
|
|
|
if (cls.downloadrate > 0.0f)
|
|
y = x - (int)strlen(text) - 19;
|
|
else
|
|
y = x - (int)strlen(text) - 8;
|
|
i = con.linewidth/3;
|
|
if (strlen(text) > i)
|
|
{
|
|
y = x - i - 11;
|
|
strncpy(dlbar, text, i);
|
|
dlbar[i] = 0;
|
|
// strncat(dlbar, "...");
|
|
Q_strncatz(dlbar, sizeof(dlbar), "...");
|
|
}
|
|
else
|
|
// strncpy(dlbar, text);
|
|
Q_strncpyz(dlbar, sizeof(dlbar), text);
|
|
// strncat(dlbar, ": ");
|
|
Q_strncatz(dlbar, sizeof(dlbar), ": ");
|
|
i = (int)strlen(dlbar);
|
|
|
|
// init solid color download bar
|
|
graph_x = (i+1)*FONT_SIZE;
|
|
graph_y = con.vislines - (int)(FONT_SIZE*1.5) - (int)conLineHeight; // was -12
|
|
graph_w = y*FONT_SIZE;
|
|
graph_h = FONT_SIZE;
|
|
|
|
for (j = 0; j < y; j++) // add blank spaces
|
|
Com_sprintf(dlbar + strlen(dlbar), sizeof(dlbar)-strlen(dlbar), " ");
|
|
|
|
if (cls.downloadrate > 0.0f)
|
|
Com_sprintf(dlbar + strlen(dlbar), sizeof(dlbar)-strlen(dlbar), " %2d%% (%4.2fKB/s)", cls.downloadpercent, cls.downloadrate);
|
|
else
|
|
Com_sprintf(dlbar + strlen(dlbar), sizeof(dlbar)-strlen(dlbar), " %2d%%", cls.downloadpercent);
|
|
|
|
// draw it
|
|
//y = graph_y;
|
|
len = (int)strlen(dlbar);
|
|
for (i = 0; i < len; i++)
|
|
if (dlbar[i] != ' ')
|
|
R_DrawChar((int)conLeft + (i+1)*FONT_SIZE, graph_y, dlbar[i], FONT_CONSOLE, CON_FONT_SCALE, 255, 255, 255, 255, false, (i==(len-1)) );
|
|
|
|
// new solid color download bar
|
|
graph_x--; graph_y--; graph_w+=2; graph_h+=2;
|
|
R_DrawFill ((int)conLeft + graph_x, graph_y, graph_w, graph_h, 255, 255, 255, 90);
|
|
R_DrawFill ((int)conLeft + (int)(graph_x+graph_h*0.2), (int)(graph_y+graph_h*0.2),
|
|
(int)((graph_w-graph_h*0.4)*cls.downloadpercent*0.01), (int)(graph_h*0.6),
|
|
red, green, blue, 255);
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
Con_DrawConsole
|
|
Draws the console with the solid background
|
|
================
|
|
*/
|
|
|
|
void Con_DrawConsole (float frac, qboolean trans)
|
|
{
|
|
int i, x, y;
|
|
int rows;
|
|
char *text, output[1024], addch[8];
|
|
int row;
|
|
int lines;
|
|
char version[64];
|
|
float alpha, barheight, conLeft, conWidth, picLeft, picWidth, picHeight, pboxWidth;
|
|
// changeable download bar color
|
|
int red, green, blue;
|
|
vec4_t picColor;
|
|
drawStruct_t ds;
|
|
|
|
// CL_TextColor ((int)alt_text_color->value, &red, &green, &blue);
|
|
CL_TextColor (alt_text_color->integer, &red, &green, &blue);
|
|
|
|
// Q3-style console bottom bar
|
|
conLeft = picLeft = 0;
|
|
conWidth = picWidth = SCREEN_WIDTH;
|
|
picHeight = SCREEN_HEIGHT;
|
|
SCR_ScaleCoords (&picLeft, NULL, &picWidth, &picHeight, ALIGN_CENTER);
|
|
|
|
// if ( (newconback_found && scr_newconback->value) || scr_oldconbar->value ) {
|
|
if ( (newconback_found && scr_newconback->integer) || scr_oldconbar->integer ) {
|
|
barheight = 2;
|
|
SCR_ScaleCoords (&conLeft, NULL, &conWidth, &barheight, ALIGN_STRETCH);
|
|
}
|
|
else {
|
|
barheight = 0;
|
|
SCR_ScaleCoords (&conLeft, NULL, &conWidth, NULL, ALIGN_STRETCH);
|
|
}
|
|
|
|
lines = viddef.height * frac;
|
|
if (lines <= 0)
|
|
return;
|
|
|
|
if (lines > viddef.height)
|
|
lines = viddef.height;
|
|
|
|
// Psychospaz's transparent console
|
|
//alpha = (trans) ? ((frac/ (newconback_found?0.5:scr_conheight->value) )*scr_conalpha->value) : 1;
|
|
// alpha = trans ? ((newconback_found && scr_newconback->value) ? scr_conalpha->value : 2*frac*scr_conalpha->value) : 1;
|
|
alpha = trans ? ((newconback_found && scr_newconback->integer) ? scr_conalpha->value : 2*frac*scr_conalpha->value) : 1;
|
|
Vector4Set (picColor, 1.0f, 1.0f, 1.0f, alpha);
|
|
|
|
// draw the background
|
|
//i = newconback_found ? lines - barheight : lines*(1/scr_conheight->value);
|
|
//j = newconback_found ? 0 : (scr_conheight->value-1)*i - barheight;
|
|
y = lines - barheight;
|
|
|
|
memset (&ds, 0, sizeof(drawStruct_t));
|
|
Vector2Copy (vec2_origin, ds.offset);
|
|
Vector4Copy (picColor, ds.color);
|
|
|
|
if (y < 1) y = 0;
|
|
/* else if (newconback_found && scr_newconback->integer) // Q3-style console
|
|
R_DrawStretchPic ((int)picLeft, 0, picWidth, lines-barheight, "/gfx/ui/newconback.pcx", alpha);
|
|
else
|
|
R_DrawStretchPic ((int)picLeft, (lines-(int)picHeight-(int)barheight), picWidth, (int)picHeight, "conback", alpha);
|
|
*/
|
|
else if (newconback_found && scr_newconback->integer) { // Q3-style console
|
|
ds.pic = "/gfx/ui/newconback.pcx";
|
|
// ds.x = (int)conLeft; ds.w = conWidth;
|
|
ds.x = (int)picLeft; ds.w = picWidth;
|
|
ds.y = 0; ds.h = lines-(int)barheight;
|
|
R_DrawPic (ds);
|
|
}
|
|
else {
|
|
ds.pic = "conback";
|
|
// ds.x = (int)conLeft; ds.w = conWidth;
|
|
ds.x = (int)picLeft; ds.w = picWidth;
|
|
ds.y = (lines-(int)picHeight-(int)barheight); ds.h = (int)picHeight;
|
|
R_DrawPic (ds);
|
|
}
|
|
|
|
// pillarbox sides if console is wider than scaled pic
|
|
if (conWidth > picWidth)
|
|
{
|
|
pboxWidth = picLeft - conLeft;
|
|
R_DrawFill ((int)conLeft, 0, (int)pboxWidth, lines-(int)barheight, 0, 0, 0, (int)(alpha*255.0f));
|
|
R_DrawFill ((int)picLeft + (int)picWidth, 0, (int)pboxWidth, lines-(int)barheight, 0, 0, 0, (int)(alpha*255.0f));
|
|
}
|
|
|
|
// changed to "KMQuake2 vx.xx"
|
|
#ifdef ERASER_COMPAT_BUILD
|
|
Com_sprintf (version, sizeof(version), S_COLOR_BOLD S_COLOR_SHADOW S_COLOR_ALT"KMQuake2 v%4.2fu%d (Eraser compatible)", VERSION, VERSION_UPDATE);
|
|
#else // ERASER_COMPAT_BUILD
|
|
Com_sprintf (version, sizeof(version), S_COLOR_BOLD S_COLOR_SHADOW S_COLOR_ALT"KMQuake2 v%4.2fu%d", VERSION, VERSION_UPDATE);
|
|
#endif // NEW_ENTITY_STATE_MEMBERS
|
|
|
|
Con_DrawString ((int)(conLeft+conWidth)-FONT_SIZE*(stringLen((const char *)&version))-3, y-(int)(1.25*FONT_SIZE), version, FONT_CONSOLE, 255);
|
|
|
|
// if ( (newconback_found && scr_newconback->value) || scr_oldconbar->value ) // Q3-style console bottom bar
|
|
if ( (newconback_found && scr_newconback->integer) || scr_oldconbar->integer ) // Q3-style console bottom bar
|
|
R_DrawFill ((int)conLeft, y, conWidth, barheight, red, green, blue, 255);
|
|
|
|
// draw the text
|
|
con.vislines = lines;
|
|
rows = (lines-(int)(2.75*FONT_SIZE))/FONT_SIZE; // rows of text to draw
|
|
y = lines - (int)(3.75*FONT_SIZE);
|
|
|
|
// draw from the bottom up
|
|
if (con.display != con.current)
|
|
{
|
|
// draw arrows to show the buffer is backscrolled
|
|
for (x = 0; x < con.linewidth; x+=4)
|
|
R_DrawChar ((int)conLeft + (x+1)*FONT_SIZE, y, '^', FONT_CONSOLE, CON_FONT_SCALE, 255, 0, 0, 255, false, ((x+4)>=con.linewidth) );
|
|
|
|
y -= FONT_SIZE;
|
|
rows--;
|
|
}
|
|
|
|
row = con.display;
|
|
for (i=0; i<rows; i++, y-=FONT_SIZE, row--)
|
|
{
|
|
if (row < 0)
|
|
break;
|
|
if (con.current - row >= con.totallines)
|
|
break; // past scrollback wrap point
|
|
|
|
text = con.text + (row % con.totallines)*con.linewidth;
|
|
|
|
Com_sprintf (output, sizeof(output), "");
|
|
for (x=0; x<con.linewidth; x++) {
|
|
// Com_sprintf (output, sizeof(output), "%s%c", output, text[x]);
|
|
addch[0] = text[x];
|
|
addch[1] = '\0';
|
|
Q_strncatz (output, sizeof(output), addch);
|
|
}
|
|
Con_DrawString ((int)conLeft + 4, y, output, FONT_CONSOLE, 255);
|
|
}
|
|
|
|
// ZOID- draw the download bar
|
|
#ifdef USE_CURL // HTTP downloading from R1Q2
|
|
if ( cls.downloadname[0] && (cls.download || cls.downloadposition) )
|
|
#else
|
|
if (cls.download)
|
|
#endif // USE_CURL
|
|
{
|
|
Con_DrawDownloadProgress (conLeft, conWidth, barheight, stringLen((const char *)&version), red, green, blue);
|
|
}
|
|
//ZOID
|
|
|
|
// draw the input prompt, user text, and cursor if desired
|
|
Con_DrawInput ();
|
|
}
|