1
0
Fork 0
forked from fte/fteqw

Allow queueing of centerprints.

This commit is contained in:
Shpoike 2023-09-11 07:31:13 +01:00
parent 7b5d2745ed
commit e39b29b130
3 changed files with 112 additions and 47 deletions

View file

@ -262,10 +262,11 @@ void *scr_curcursor;
static void SCR_CPrint_f(void) static void SCR_CPrint_f(void)
{ {
int seat = CL_TargettedSplit(false);
if (Cmd_Argc() == 2) if (Cmd_Argc() == 2)
SCR_CenterPrint(0, Cmd_Argv(1), true); SCR_CenterPrint(seat, Cmd_Argv(1), true);
else else
SCR_CenterPrint(0, Cmd_Args(), true); SCR_CenterPrint(seat, Cmd_Args(), true);
} }
extern char cl_screengroup[]; extern char cl_screengroup[];
@ -317,7 +318,7 @@ CENTER PRINTING
=============================================================================== ===============================================================================
*/ */
typedef struct { typedef struct cprint_s {
unsigned int flags; unsigned int flags;
conchar_t *string; conchar_t *string;
@ -331,9 +332,11 @@ typedef struct {
int erase_center; int erase_center;
int oldmousex, oldmousey; //so the cursorchar can be changed by keyboard without constantly getting stomped on. int oldmousex, oldmousey; //so the cursorchar can be changed by keyboard without constantly getting stomped on.
struct cprint_s *queue; //switch to the next on timeout.
} cprint_t; } cprint_t;
cprint_t scr_centerprint[MAX_SPLITS]; static cprint_t *scr_centerprint[MAX_SPLITS];
// SCR_StringToRGB: takes in "<index>" or "<r> <g> <b>" and converts to an RGB vector // SCR_StringToRGB: takes in "<index>" or "<r> <g> <b>" and converts to an RGB vector
void SCR_StringToRGB (char *rgbstring, float *rgb, float rgbinputscale) void SCR_StringToRGB (char *rgbstring, float *rgb, float rgbinputscale)
@ -397,6 +400,22 @@ void SCR_StringToRGB (char *rgbstring, float *rgb, float rgbinputscale)
} // i contains the crosshair color } // i contains the crosshair color
} }
static qboolean SCR_CenterPrintPop(int pnum)
{
cprint_t *p = scr_centerprint[pnum];
if (!p)
return false;
scr_centerprint[pnum] = p->queue;
Z_Free(p->string);
Z_Free(p);
//timers start NOW (not when its first queued, obviously)
p = scr_centerprint[pnum];
if (p)
p->time_start = cl.time;
return true;
}
/* /*
============== ==============
SCR_CenterPrint SCR_CenterPrint
@ -409,7 +428,9 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
{ {
unsigned int pfl = 0; unsigned int pfl = 0;
size_t i; size_t i;
cprint_t *p; cprint_t *p, **l;
qboolean doqueue = false;
qboolean donotify = ((scr_logcenterprint.ival && !cl.deathmatch) || scr_logcenterprint.ival == 2);
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
if (scr_usekfont.ival) if (scr_usekfont.ival)
pfl |= PFS_FORCEUTF8; pfl |= PFS_FORCEUTF8;
@ -417,11 +438,8 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
if (!str) if (!str)
{ {
if (cl.intermissionmode == IM_NONE) if (cl.intermissionmode == IM_NONE)
{ while(SCR_CenterPrintPop(pnum))
p = &scr_centerprint[pnum]; ;
p->flags = 0;
p->time_off = 0;
}
return; return;
} }
if (!skipgamecode) if (!skipgamecode)
@ -445,10 +463,11 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
} }
} }
p = &scr_centerprint[pnum]; p = Z_Malloc(sizeof(*p));
p->flags = 0; p->flags = 0;
p->titleimage[0] = 0; p->titleimage[0] = 0;
p->cursorchar = NULL; p->cursorchar = NULL;
p->time_off = scr_centertime.value;
if (*str != '/') if (*str != '/')
{ {
@ -477,10 +496,22 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
p->flags |= CPRINT_CURSOR; //this can be a little jarring if there's no links, so this forces consistent behaviour. p->flags |= CPRINT_CURSOR; //this can be a little jarring if there's no links, so this forces consistent behaviour.
else if (str[1] == 'W') //wait between each char else if (str[1] == 'W') //wait between each char
p->flags ^= CPRINT_TYPEWRITER; p->flags ^= CPRINT_TYPEWRITER;
else if (str[1] == 'Q') //queue
doqueue = true;
else if (str[1] == 'D') //explicit delay
{
p->time_off = strtod(str+2, (char**)&str);
continue;
}
else if (str[1] == 'S') //Stay else if (str[1] == 'S') //Stay
p->flags ^= CPRINT_PERSIST; p->flags ^= CPRINT_PERSIST;
else if (str[1] == 'M') //'Mask' the background so that its readable. else if (str[1] == 'M') //'Mask' the background so that its readable.
p->flags ^= CPRINT_BACKGROUND; p->flags ^= CPRINT_BACKGROUND;
else if (str[1] == 'N') //'Notify' spam it to the console even in deathmatch.
{
donotify = strtol(str+2, (char**)&str, 10);
continue;
}
else if (str[1] == 'O') //Obituaries are shown at the bottom, ish. else if (str[1] == 'O') //Obituaries are shown at the bottom, ish.
p->flags ^= CPRINT_OBITUARTY; p->flags ^= CPRINT_OBITUARTY;
else if (str[1] == 'B') else if (str[1] == 'B')
@ -549,7 +580,16 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
str += 2; str += 2;
} }
if (((scr_logcenterprint.ival && !cl.deathmatch) || scr_logcenterprint.ival == 2) && !(p->flags & CPRINT_PERSIST)) if (!doqueue) //kill all prior ones if we're not queueing
while (SCR_CenterPrintPop(pnum))
;
//add it to the end
for (l = &scr_centerprint[pnum]; *l; l = &(*l)->queue)
;
*l = p;
if (donotify && !(p->flags & CPRINT_PERSIST))
{ {
//don't spam too much. //don't spam too much.
if (*str && strncmp(cl.lastcenterprint, str, sizeof(cl.lastcenterprint)-1)) if (*str && strncmp(cl.lastcenterprint, str, sizeof(cl.lastcenterprint)-1))
@ -585,7 +625,6 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
} }
} }
p->time_off = scr_centertime.value;
p->time_start = cl.time; p->time_start = cl.time;
VRUI_SnapAngle(); VRUI_SnapAngle();
} }
@ -594,16 +633,17 @@ void VARGS Stats_Message(char *msg, ...)
{ {
va_list argptr; va_list argptr;
char str[2048]; char str[2048];
cprint_t *p = &scr_centerprint[0]; cprint_t *p = scr_centerprint[0];
if (!scr_showobituaries.ival) if (!scr_showobituaries.ival)
return; return;
if (p->time_off >= 0) if (p) //don't show if one is shown... FIXME: queue these too (some depth cutoff?)
return; return;
va_start (argptr, msg); va_start (argptr, msg);
vsnprintf (str,sizeof(str)-1, msg, argptr); vsnprintf (str,sizeof(str)-1, msg, argptr);
va_end (argptr); va_end (argptr);
p = scr_centerprint[0] = Z_Malloc(sizeof(*p));
p->flags = CPRINT_OBITUARTY; p->flags = CPRINT_OBITUARTY;
p->titleimage[0] = 0; p->titleimage[0] = 0;
@ -788,6 +828,7 @@ int SCR_DrawCenterString (vrect_t *playerrect, cprint_t *p, struct font_s *font)
Font_BeginString(font, rect.x, y, &left, &top); Font_BeginString(font, rect.x, y, &left, &top);
} }
x = (left+right)/2;
for (l = 0; l < linecount; l++, y += ch) for (l = 0; l < linecount; l++, y += ch)
{ {
if (y >= bottom) if (y >= bottom)
@ -825,9 +866,11 @@ int SCR_DrawCenterString (vrect_t *playerrect, cprint_t *p, struct font_s *font)
remaining -= line_end[l]-line_start[l]; remaining -= line_end[l]-line_start[l];
if (remaining <= 0) if (remaining <= 0)
{ {
if (p->time_off && (p->flags&(CPRINT_TYPEWRITER|CPRINT_PERSIST))==CPRINT_TYPEWRITER)
p->time_off = scr_centertime.value; //reset the timeout while we're still truncating it.
line_end[l] += remaining; line_end[l] += remaining;
if (line_end[l] <= line_start[l]) if (line_end[l] <= line_start[l])
break; line_end[l] = line_start[l];
} }
if (p->cursorchar && p->cursorchar >= line_start[l] && p->cursorchar < line_end[l] && *p->cursorchar == CON_LINKSTART) if (p->cursorchar && p->cursorchar >= line_start[l] && p->cursorchar < line_end[l] && *p->cursorchar == CON_LINKSTART)
@ -849,6 +892,16 @@ int SCR_DrawCenterString (vrect_t *playerrect, cprint_t *p, struct font_s *font)
} }
Font_LineDraw(x, y, line_start[l], line_end[l]); Font_LineDraw(x, y, line_start[l], line_end[l]);
if (remaining <= 0 || l == linecount-1)
{
if ((p->flags&(CPRINT_TYPEWRITER|CPRINT_PERSIST))==CPRINT_TYPEWRITER && l < linecount && ((int)(realtime*4)&1))
{
x = x+Font_LineWidth(line_start[l], line_end[l]);
Font_DrawChar(x, y, CON_WHITEMASK, 0xe00b);
}
break;
}
} }
Font_EndString(font); Font_EndString(font);
@ -859,7 +912,7 @@ int SCR_DrawCenterString (vrect_t *playerrect, cprint_t *p, struct font_s *font)
static void Key_CenterPrintActivate(int pnum) static void Key_CenterPrintActivate(int pnum)
{ {
char *link; char *link;
cprint_t *p = &scr_centerprint[pnum]; cprint_t *p = scr_centerprint[pnum];
link = SCR_CopyCenterPrint(p); link = SCR_CopyCenterPrint(p);
if (link) if (link)
{ {
@ -915,7 +968,6 @@ qboolean Key_Centerprint(int key, int unicode, unsigned int devid)
//figure out which player has the cursor //figure out which player has the cursor
for (pnum = 0; pnum < cl.splitclients; pnum++) for (pnum = 0; pnum < cl.splitclients; pnum++)
{ {
p = &scr_centerprint[pnum];
if (cl.playerview[pnum].gamerectknown == cls.framecount) if (cl.playerview[pnum].gamerectknown == cls.framecount)
Key_CenterPrintActivate(pnum); Key_CenterPrintActivate(pnum);
} }
@ -925,8 +977,9 @@ qboolean Key_Centerprint(int key, int unicode, unsigned int devid)
{ {
for (pnum = 0; pnum < cl.splitclients; pnum++) for (pnum = 0; pnum < cl.splitclients; pnum++)
{ {
p = &scr_centerprint[pnum]; p = scr_centerprint[pnum];
p->flags &= ~CPRINT_CURSOR; if (p)
p->flags &= ~CPRINT_CURSOR;
} }
return true; return true;
} }
@ -934,8 +987,8 @@ qboolean Key_Centerprint(int key, int unicode, unsigned int devid)
key == K_KP_ENTER || key == K_KP_ENTER ||
key == K_GP_DIAMOND_RIGHT) && devid < countof(scr_centerprint)) key == K_GP_DIAMOND_RIGHT) && devid < countof(scr_centerprint))
{ {
p = &scr_centerprint[devid]; p = scr_centerprint[devid];
if (p->cursorchar) if (p && p->cursorchar)
Key_CenterPrintActivate(devid); Key_CenterPrintActivate(devid);
return true; return true;
} }
@ -946,15 +999,18 @@ qboolean Key_Centerprint(int key, int unicode, unsigned int devid)
key == K_GP_DPAD_UP || key == K_GP_DPAD_UP ||
key == K_GP_DPAD_LEFT) && devid < countof(scr_centerprint)) key == K_GP_DPAD_LEFT) && devid < countof(scr_centerprint))
{ {
p = &scr_centerprint[devid]; p = scr_centerprint[devid];
if (!p->cursorchar) if (p)
p->cursorchar = p->string + p->charcount;
while (--p->cursorchar >= p->string)
{ {
if (*p->cursorchar == CON_LINKSTART) if (!p->cursorchar)
return true; //found one p->cursorchar = p->string + p->charcount;
while (--p->cursorchar >= p->string)
{
if (*p->cursorchar == CON_LINKSTART)
return true; //found one
}
p->cursorchar = NULL;
} }
p->cursorchar = NULL;
return true; return true;
} }
else if ((key == K_DOWNARROW || else if ((key == K_DOWNARROW ||
@ -964,15 +1020,18 @@ qboolean Key_Centerprint(int key, int unicode, unsigned int devid)
key == K_GP_DPAD_DOWN || key == K_GP_DPAD_DOWN ||
key == K_GP_DPAD_RIGHT) && devid < countof(scr_centerprint)) key == K_GP_DPAD_RIGHT) && devid < countof(scr_centerprint))
{ {
p = &scr_centerprint[devid]; p = scr_centerprint[devid];
if (!p->cursorchar) if (p)
p->cursorchar = p->string-1;
while (++p->cursorchar < p->string + p->charcount)
{ {
if (*p->cursorchar == CON_LINKSTART) if (!p->cursorchar)
return true; //found one p->cursorchar = p->string-1;
while (++p->cursorchar < p->string + p->charcount)
{
if (*p->cursorchar == CON_LINKSTART)
return true; //found one
}
p->cursorchar = NULL; //hit the end
} }
p->cursorchar = NULL; //hit the end
return true; return true;
} }
@ -988,8 +1047,6 @@ void SCR_CheckDrawCenterString (void)
for (pnum = 0; pnum < cl.splitclients; pnum++) for (pnum = 0; pnum < cl.splitclients; pnum++)
{ {
p = &scr_centerprint[pnum];
#ifdef QUAKESTATS #ifdef QUAKESTATS
if (IN_DrawWeaponWheel(pnum)) if (IN_DrawWeaponWheel(pnum))
{ //we won't draw the cprint, but it also won't fade while the wwheel is shown. { //we won't draw the cprint, but it also won't fade while the wwheel is shown.
@ -997,8 +1054,15 @@ void SCR_CheckDrawCenterString (void)
} }
#endif #endif
if (p->time_off <= 0 && !(p->flags & CPRINT_PERSIST)) p = scr_centerprint[pnum];
continue; //'/P' prefix doesn't time out if (!p)
continue;
if (p->time_off <= 0 && !(p->flags & CPRINT_PERSIST)) //'/P' prefix doesn't time out
{ //this one is done. move to the next.
if (SCR_CenterPrintPop(pnum))
pnum++;
continue;
}
p->time_off -= host_frametime; p->time_off -= host_frametime;
@ -1461,8 +1525,8 @@ void SCR_ShowPic_ClearAll(qboolean persistflag)
for (pnum = 0; pnum < MAX_SPLITS; pnum++) for (pnum = 0; pnum < MAX_SPLITS; pnum++)
{ {
scr_centerprint[pnum].flags = 0; while (SCR_CenterPrintPop(pnum))
scr_centerprint[pnum].charcount = 0; ;
} }
if (!persistflag) if (!persistflag)
@ -3415,7 +3479,8 @@ void SCR_BringDownConsole (void)
for (pnum = 0; pnum < cl.splitclients; pnum++) for (pnum = 0; pnum < cl.splitclients; pnum++)
{ {
scr_centerprint[pnum].charcount = 0; while (SCR_CenterPrintPop(pnum))
;
cl.playerview[pnum].cshifts[CSHIFT_CONTENTS].percent = 0; // no area contents palette on next frame cl.playerview[pnum].cshifts[CSHIFT_CONTENTS].percent = 0; // no area contents palette on next frame
} }
} }
@ -3571,8 +3636,8 @@ void SCR_DeInit (void)
} }
for (i = 0; i < countof(scr_centerprint); i++) for (i = 0; i < countof(scr_centerprint); i++)
{ {
Z_Free(scr_centerprint[i].string); while (SCR_CenterPrintPop(i))
memset(&scr_centerprint[i], 0, sizeof(scr_centerprint[i])); ;
} }
if (scr_initialized) if (scr_initialized)
{ {

View file

@ -543,7 +543,7 @@ int M_GameType(void);
//plugin functions //plugin functions
#ifdef PLUGINS #ifdef PLUGINS
qboolean Plug_CenterPrintMessage(char *buffer, int clientnum); qboolean Plug_CenterPrintMessage(const char *buffer, int clientnum);
qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags); qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags);
void Plug_Command_f(void); void Plug_Command_f(void);
int Plug_ConnectionlessClientPacket(char *buffer, int size); int Plug_ConnectionlessClientPacket(char *buffer, int size);

View file

@ -1538,7 +1538,7 @@ qboolean Plug_ChatMessage(char *buffer, int talkernum, int tpflags)
return ret; // true to display message, false to supress return ret; // true to display message, false to supress
} }
qboolean Plug_CenterPrintMessage(char *buffer, int clientnum) qboolean Plug_CenterPrintMessage(const char *buffer, int clientnum)
{ {
qboolean ret = true; qboolean ret = true;