mirror of
https://git.code.sf.net/p/quake/newtree
synced 2024-11-10 06:42:26 +00:00
cl_ents.c: misc. tweaks to CL_ParsePacketEntities ()
rest: Myriad stuff. r_netgraph now recognizes and abides by the cl_hudswap Cvar. show_fps and show_time are on the same line now, and stay out of each others' way. New Draw_ function: Draw_TextBox(). It's like M_DrawTextBox(), except it doesn't screw around with the screen coordinates.
This commit is contained in:
parent
d0b1fc7816
commit
0c662b0e6a
8 changed files with 199 additions and 79 deletions
|
@ -38,6 +38,7 @@ void Draw_Init_Cvars (void);
|
|||
void Draw_Character8 (int x, int y, int num);
|
||||
void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height);
|
||||
void Draw_Pic (int x, int y, qpic_t *pic);
|
||||
void Draw_TextBox (int x, int y, int width, int lines);
|
||||
void Draw_TransPic (int x, int y, qpic_t *pic);
|
||||
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte *translation);
|
||||
void Draw_ConsoleBackground (int lines);
|
||||
|
|
|
@ -380,14 +380,11 @@ CL_ParsePacketEntities (qboolean delta)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!word) {
|
||||
while (oldindex < oldp->num_entities) { // copy all the rest of
|
||||
// the entities from the
|
||||
// old packet
|
||||
//Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
|
||||
if (!word) { // copy rest of ents from old packet
|
||||
while (oldindex < oldp->num_entities) {
|
||||
// Con_Printf ("copy %i\n", oldp->entities[oldindex].number);
|
||||
if (newindex >= MAX_PACKET_ENTITIES)
|
||||
Host_EndGame
|
||||
("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
|
||||
Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
|
||||
newp->entities[newindex] = oldp->entities[oldindex];
|
||||
newindex++;
|
||||
oldindex++;
|
||||
|
@ -395,9 +392,7 @@ CL_ParsePacketEntities (qboolean delta)
|
|||
break;
|
||||
}
|
||||
newnum = word & 511;
|
||||
oldnum =
|
||||
oldindex >=
|
||||
oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
|
||||
oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
|
||||
|
||||
while (newnum > oldnum) {
|
||||
if (full) {
|
||||
|
@ -405,21 +400,18 @@ CL_ParsePacketEntities (qboolean delta)
|
|||
FlushEntityPacket ();
|
||||
return;
|
||||
}
|
||||
//Con_Printf ("copy %i\n", oldnum);
|
||||
// Con_Printf ("copy %i\n", oldnum);
|
||||
// copy one of the old entities over to the new packet unchanged
|
||||
if (newindex >= MAX_PACKET_ENTITIES)
|
||||
Host_EndGame
|
||||
("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
|
||||
Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
|
||||
newp->entities[newindex] = oldp->entities[oldindex];
|
||||
newindex++;
|
||||
oldindex++;
|
||||
oldnum =
|
||||
oldindex >=
|
||||
oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
|
||||
oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number;
|
||||
}
|
||||
|
||||
if (newnum < oldnum) { // new from baseline
|
||||
//Con_Printf ("baseline %i\n", newnum);
|
||||
// Con_Printf ("baseline %i\n", newnum);
|
||||
if (word & U_REMOVE) {
|
||||
if (full) {
|
||||
cl.validsequence = 0;
|
||||
|
@ -430,10 +422,8 @@ CL_ParsePacketEntities (qboolean delta)
|
|||
continue;
|
||||
}
|
||||
if (newindex >= MAX_PACKET_ENTITIES)
|
||||
Host_EndGame
|
||||
("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
|
||||
CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex],
|
||||
word);
|
||||
Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES");
|
||||
CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word);
|
||||
newindex++;
|
||||
continue;
|
||||
}
|
||||
|
@ -447,9 +437,8 @@ CL_ParsePacketEntities (qboolean delta)
|
|||
oldindex++;
|
||||
continue;
|
||||
}
|
||||
//Con_Printf ("delta %i\n",newnum);
|
||||
CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex],
|
||||
word);
|
||||
// Con_Printf ("delta %i\n",newnum);
|
||||
CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word);
|
||||
newindex++;
|
||||
oldindex++;
|
||||
}
|
||||
|
|
|
@ -128,7 +128,57 @@ Draw_CachePic (char *path)
|
|||
return dat;
|
||||
}
|
||||
|
||||
void
|
||||
Draw_TextBox (int x, int y, int width, int lines)
|
||||
{
|
||||
qpic_t *p;
|
||||
int cx, cy;
|
||||
int n;
|
||||
|
||||
// draw left side
|
||||
cx = x;
|
||||
cy = y;
|
||||
p = Draw_CachePic ("gfx/box_tl.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
p = Draw_CachePic ("gfx/box_ml.lmp");
|
||||
for (n = 0; n < lines; n++) {
|
||||
cy += 8;
|
||||
Draw_Pic (cx, cy, p);
|
||||
}
|
||||
p = Draw_CachePic ("gfx/box_bl.lmp");
|
||||
Draw_Pic (cx, cy + 8, p);
|
||||
|
||||
// draw middle
|
||||
cx += 8;
|
||||
while (width > 0) {
|
||||
cy = y;
|
||||
p = Draw_CachePic ("gfx/box_tm.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
p = Draw_CachePic ("gfx/box_mm.lmp");
|
||||
for (n = 0; n < lines; n++) {
|
||||
cy += 8;
|
||||
if (n == 1)
|
||||
p = Draw_CachePic ("gfx/box_mm2.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
}
|
||||
p = Draw_CachePic ("gfx/box_bm.lmp");
|
||||
Draw_Pic (cx, cy + 8, p);
|
||||
width -= 2;
|
||||
cx += 16;
|
||||
}
|
||||
|
||||
// draw right side
|
||||
cy = y;
|
||||
p = Draw_CachePic ("gfx/box_tr.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
p = Draw_CachePic ("gfx/box_mr.lmp");
|
||||
for (n = 0; n < lines; n++) {
|
||||
cy += 8;
|
||||
Draw_Pic (cx, cy, p);
|
||||
}
|
||||
p = Draw_CachePic ("gfx/box_br.lmp");
|
||||
Draw_Pic (cx, cy + 8, p);
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
|
|
|
@ -218,7 +218,7 @@ static int numcachepics;
|
|||
|
||||
static byte menuplyr_pixels[4096];
|
||||
|
||||
qpic_t *
|
||||
qpic_t *
|
||||
Draw_PicFromWad (char *name)
|
||||
{
|
||||
qpic_t *p;
|
||||
|
@ -274,7 +274,7 @@ Draw_ClearCache (void)
|
|||
Draw_CachePic
|
||||
================
|
||||
*/
|
||||
qpic_t *
|
||||
qpic_t *
|
||||
Draw_CachePic (char *path)
|
||||
{
|
||||
cachepic_t *pic;
|
||||
|
@ -395,6 +395,58 @@ Draw_TextureMode_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Draw_TextBox (int x, int y, int width, int lines)
|
||||
{
|
||||
qpic_t *p;
|
||||
int cx, cy;
|
||||
int n;
|
||||
|
||||
// draw left side
|
||||
cx = x;
|
||||
cy = y;
|
||||
p = Draw_CachePic ("gfx/box_tl.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
p = Draw_CachePic ("gfx/box_ml.lmp");
|
||||
for (n = 0; n < lines; n++) {
|
||||
cy += 8;
|
||||
Draw_Pic (cx, cy, p);
|
||||
}
|
||||
p = Draw_CachePic ("gfx/box_bl.lmp");
|
||||
Draw_Pic (cx, cy + 8, p);
|
||||
|
||||
// draw middle
|
||||
cx += 8;
|
||||
while (width > 0) {
|
||||
cy = y;
|
||||
p = Draw_CachePic ("gfx/box_tm.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
p = Draw_CachePic ("gfx/box_mm.lmp");
|
||||
for (n = 0; n < lines; n++) {
|
||||
cy += 8;
|
||||
if (n == 1)
|
||||
p = Draw_CachePic ("gfx/box_mm2.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
}
|
||||
p = Draw_CachePic ("gfx/box_bm.lmp");
|
||||
Draw_Pic (cx, cy + 8, p);
|
||||
width -= 2;
|
||||
cx += 16;
|
||||
}
|
||||
|
||||
// draw right side
|
||||
cy = y;
|
||||
p = Draw_CachePic ("gfx/box_tr.lmp");
|
||||
Draw_Pic (cx, cy, p);
|
||||
p = Draw_CachePic ("gfx/box_mr.lmp");
|
||||
for (n = 0; n < lines; n++) {
|
||||
cy += 8;
|
||||
Draw_Pic (cx, cy, p);
|
||||
}
|
||||
p = Draw_CachePic ("gfx/box_br.lmp");
|
||||
Draw_Pic (cx, cy + 8, p);
|
||||
}
|
||||
|
||||
extern void glrmain_init ();
|
||||
extern void glrsurf_init ();
|
||||
|
||||
|
@ -634,10 +686,7 @@ Draw_Pic (int x, int y, qpic_t *pic)
|
|||
Scrap_Upload ();
|
||||
#endif
|
||||
gl = (glpic_t *) pic->data;
|
||||
if (lighthalf)
|
||||
glColor3f (0.4, 0.4, 0.4);
|
||||
else
|
||||
glColor3f (0.8, 0.8, 0.8);
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, gl->texnum);
|
||||
glBegin (GL_QUADS);
|
||||
glTexCoord2f (gl->sl, gl->tl);
|
||||
|
@ -649,7 +698,6 @@ Draw_Pic (int x, int y, qpic_t *pic)
|
|||
glTexCoord2f (gl->sl, gl->th);
|
||||
glVertex2f (x, y + pic->height);
|
||||
glEnd ();
|
||||
glColor3ubv (lighthalf_v);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -58,10 +58,14 @@
|
|||
#include "cl_parse.h"
|
||||
|
||||
|
||||
extern byte *draw_chars; // 8*8 graphic characters
|
||||
extern byte *draw_chars; // 8*8 graphic characters
|
||||
extern qboolean lighthalf;
|
||||
|
||||
int netgraphtexture; // netgraph texture
|
||||
extern cvar_t *r_netgraph;
|
||||
extern cvar_t *r_netgraph_alpha;
|
||||
extern cvar_t *r_netgraph_box;
|
||||
|
||||
int netgraphtexture; // netgraph texture
|
||||
|
||||
#define NET_GRAPHHEIGHT 32
|
||||
|
||||
|
@ -144,14 +148,26 @@ R_NetGraph (void)
|
|||
for (x = 0; x < NET_TIMINGS; x++)
|
||||
ngraph_pixels[y][x] = d_8to24table[ngraph_texels[y][x]];
|
||||
|
||||
x = -((vid.width - 320) >> 1);
|
||||
x = cl_hudswap->int_val ? vid.width - (NET_TIMINGS + 16): 0 ;
|
||||
y = vid.height - sb_lines - 24 - NET_GRAPHHEIGHT - 1;
|
||||
|
||||
M_DrawTextBox (x, y, NET_TIMINGS / 8, NET_GRAPHHEIGHT / 8 + 1);
|
||||
if (r_netgraph_alpha->value < 0.995) // roundoff
|
||||
glColor4f (1, 1, 1, r_netgraph_alpha->value);
|
||||
|
||||
if (r_netgraph_box->int_val)
|
||||
Draw_TextBox (x, y, NET_TIMINGS / 8, NET_GRAPHHEIGHT / 8 + 1);
|
||||
|
||||
y += 8;
|
||||
|
||||
snprintf (st, sizeof (st), "%3i%% packet loss", lost);
|
||||
Draw_String8 (8, y, st);
|
||||
if (cl_hudswap->int_val) {
|
||||
Draw_String8 (vid.width - ((strlen (st) * 8) + 8), y, st);
|
||||
} else {
|
||||
Draw_String8 (8, y, st);
|
||||
}
|
||||
|
||||
x = cl_hudswap->int_val ? vid.width - (NET_TIMINGS + 8) : 8;
|
||||
|
||||
y += 8;
|
||||
|
||||
glBindTexture (GL_TEXTURE_2D, netgraphtexture);
|
||||
|
@ -163,7 +179,6 @@ R_NetGraph (void)
|
|||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
x = 8;
|
||||
glBegin (GL_QUADS);
|
||||
glTexCoord2f (0, 0);
|
||||
glVertex2f (x, y);
|
||||
|
@ -174,4 +189,6 @@ R_NetGraph (void)
|
|||
glTexCoord2f (0, 1);
|
||||
glVertex2f (x, y + NET_GRAPHHEIGHT);
|
||||
glEnd ();
|
||||
|
||||
glColor3ubv (lighthalf_v);
|
||||
}
|
||||
|
|
|
@ -64,8 +64,13 @@ qboolean VID_Is8bit (void);
|
|||
void R_InitBubble ();
|
||||
void R_FireColor_f (void);
|
||||
|
||||
cvar_t *gl_fires;
|
||||
cvar_t *gl_fires;
|
||||
cvar_t *r_netgraph_alpha;
|
||||
cvar_t *r_netgraph_box;
|
||||
|
||||
extern cvar_t *r_netgraph;
|
||||
extern cvar_t *gl_lerp_anim;
|
||||
|
||||
qboolean allowskybox; // allow skyboxes? --KB
|
||||
|
||||
/*
|
||||
|
@ -226,7 +231,10 @@ R_Init_Cvars (void)
|
|||
r_dynamic = Cvar_Get ("r_dynamic", "1", CVAR_NONE, "None");
|
||||
r_novis = Cvar_Get ("r_novis", "0", CVAR_NONE, "None");
|
||||
r_speeds = Cvar_Get ("r_speeds", "0", CVAR_NONE, "None");
|
||||
r_netgraph = Cvar_Get ("r_netgraph", "0", CVAR_NONE, "None");
|
||||
|
||||
r_netgraph = Cvar_Get ("r_netgraph", "0", CVAR_ARCHIVE, "Graph network stats");
|
||||
r_netgraph_alpha = Cvar_Get ("r_netgraph_alpha", "0.5", CVAR_ARCHIVE, "Net graph translucency");
|
||||
r_netgraph_box = Cvar_Get ("r_netgraph_box", "1", CVAR_ARCHIVE, "Draw box around net graph?");
|
||||
|
||||
gl_clear = Cvar_Get ("gl_clear", "0", CVAR_NONE, "None");
|
||||
gl_texsort = Cvar_Get ("gl_texsort", "1", CVAR_NONE, "None");
|
||||
|
|
|
@ -470,15 +470,17 @@ SCR_DrawNet (void)
|
|||
Draw_Pic (scr_vrect.x + 64, scr_vrect.y, scr_net);
|
||||
}
|
||||
|
||||
extern cvar_t *show_time;
|
||||
extern cvar_t *show_fps;
|
||||
|
||||
void
|
||||
SCR_DrawFPS (void)
|
||||
{
|
||||
extern cvar_t *show_fps;
|
||||
static double lastframetime;
|
||||
double t;
|
||||
extern int fps_count;
|
||||
static int lastfps;
|
||||
int x, y;
|
||||
int i, x, y;
|
||||
char st[80];
|
||||
|
||||
if (!show_fps->int_val)
|
||||
|
@ -490,11 +492,20 @@ SCR_DrawFPS (void)
|
|||
fps_count = 0;
|
||||
lastframetime = t;
|
||||
}
|
||||
snprintf (st, sizeof (st), "%-3d FPS", lastfps);
|
||||
/* Misty: New trick! (for me) the ? makes this work like a if then else -
|
||||
snprintf (st, sizeof (st), "%3d FPS", lastfps);
|
||||
/*
|
||||
Misty: New trick! (for me) the ? makes this work like a if then else -
|
||||
IE: if cl_hudswap->int_val is not null, do first case, else (else is a
|
||||
: here) do second case. Deek taught me this trick */
|
||||
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + 8) : 8;
|
||||
: here) do second case. Deek taught me this trick
|
||||
*/
|
||||
if (show_time->int_val <= 0) {
|
||||
i = 8;
|
||||
} else if (show_time->int_val == 1) {
|
||||
i = 56;
|
||||
} else {
|
||||
i = 80;
|
||||
}
|
||||
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + i) : i;
|
||||
y = vid.height - sb_lines - 8;
|
||||
Draw_String8 (x, y, st);
|
||||
|
||||
|
@ -504,34 +515,28 @@ SCR_DrawFPS (void)
|
|||
void
|
||||
SCR_DrawTime (void)
|
||||
{
|
||||
extern cvar_t *show_time;
|
||||
int x, y;
|
||||
char st[80];
|
||||
char local_time[120];
|
||||
time_t systime;
|
||||
|
||||
/* any cvar that can take multiple settings must be able to handle abuse.
|
||||
*/
|
||||
// any cvar that can take multiple settings must be able to handle abuse.
|
||||
if (show_time->int_val <= 0)
|
||||
return;
|
||||
|
||||
/* actually find the time and set systime to it */
|
||||
time (&systime);
|
||||
|
||||
if (show_time->int_val == 1) {
|
||||
/* now set local_time to 24 hour time using hours:minutes format */
|
||||
strftime (local_time, sizeof (local_time), "%k:%M",
|
||||
localtime (&systime));
|
||||
} else if (show_time->int_val >= 2) {
|
||||
/* >= is another cvar abuse protector */
|
||||
strftime (local_time, sizeof (local_time), "%l:%M %P",
|
||||
localtime (&systime));
|
||||
if (show_time->int_val == 1) { // International format
|
||||
strftime (local_time, sizeof (local_time), "%H:%M", localtime (&systime));
|
||||
} else if (show_time->int_val >= 2) { // AM/PM display
|
||||
strftime (local_time, sizeof (local_time), "%I:%M %P", localtime (&systime));
|
||||
}
|
||||
|
||||
/* now actually print it to the screen directly above where show_fps is */
|
||||
// Print it next to the fps meter
|
||||
snprintf (st, sizeof (st), "%s", local_time);
|
||||
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + 8) : 8;
|
||||
y = vid.height - sb_lines - 16;
|
||||
x = cl_hudswap->int_val ? (vid.width - ((strlen (st) * 8) + 8)) : 8;
|
||||
y = vid.height - (sb_lines + 8);
|
||||
Draw_String8 (x, y, st);
|
||||
}
|
||||
|
||||
|
|
|
@ -487,15 +487,17 @@ SCR_DrawNet (void)
|
|||
Draw_Pic (scr_vrect.x + 64, scr_vrect.y, scr_net);
|
||||
}
|
||||
|
||||
extern cvar_t *show_fps;
|
||||
extern cvar_t *show_time;
|
||||
|
||||
void
|
||||
SCR_DrawFPS (void)
|
||||
{
|
||||
extern cvar_t *show_fps;
|
||||
static double lastframetime;
|
||||
double t;
|
||||
extern int fps_count;
|
||||
static int lastfps;
|
||||
int x, y;
|
||||
int i, x, y;
|
||||
char st[80];
|
||||
|
||||
if (!show_fps->int_val)
|
||||
|
@ -507,48 +509,48 @@ SCR_DrawFPS (void)
|
|||
fps_count = 0;
|
||||
lastframetime = t;
|
||||
}
|
||||
snprintf (st, sizeof (st), "%-3d FPS", lastfps);
|
||||
snprintf (st, sizeof (st), "%3d FPS", lastfps);
|
||||
/* Misty: New trick! (for me) the ? makes this work like a if then else -
|
||||
IE: if cl_hudswap->int_val is not null, do first case, else (else is a
|
||||
: here) do second case. Deek taught me this trick */
|
||||
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + 8) : 8;
|
||||
y = vid.height - sb_lines - 8;
|
||||
if (show_time->int_val <= 0) {
|
||||
i = 8;
|
||||
} else if (show_time->int_val == 1) {
|
||||
i = 56;
|
||||
} else {
|
||||
i = 80;
|
||||
}
|
||||
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + i) : i;
|
||||
y = vid.height - (sb_lines + 8);
|
||||
Draw_String8 (x, y, st);
|
||||
|
||||
}
|
||||
|
||||
/* Misty: I like to see the time */
|
||||
void
|
||||
SCR_DrawTime (void)
|
||||
{
|
||||
extern cvar_t *show_time;
|
||||
int x, y;
|
||||
char st[80];
|
||||
char local_time[120];
|
||||
time_t systime;
|
||||
|
||||
/* any cvar that can take multiple settings must be able to handle abuse.
|
||||
*/
|
||||
// any cvar that can take multiple settings must be able to handle abuse.
|
||||
if (show_time->int_val <= 0)
|
||||
return;
|
||||
|
||||
/* actually find the time and set systime to it */
|
||||
time (&systime);
|
||||
|
||||
if (show_time->int_val == 1) {
|
||||
/* now set local_time to 24 hour time using hours:minutes format */
|
||||
strftime (local_time, sizeof (local_time), "%k:%M",
|
||||
localtime (&systime));
|
||||
} else if (show_time->int_val >= 2) {
|
||||
/* >= is another cvar abuse protector */
|
||||
strftime (local_time, sizeof (local_time), "%l:%M %P",
|
||||
localtime (&systime));
|
||||
if (show_time->int_val == 1) { // International format
|
||||
strftime (local_time, sizeof (local_time), "%k:%M", localtime (&systime));
|
||||
} else if (show_time->int_val >= 2) { // AM/PM display
|
||||
strftime (local_time, sizeof (local_time), "%l:%M %P", localtime (&systime));
|
||||
}
|
||||
|
||||
/* now actually print it to the screen directly above where show_fps is */
|
||||
// Print it next to the fps meter
|
||||
snprintf (st, sizeof (st), "%s", local_time);
|
||||
x = cl_hudswap->int_val ? vid.width - ((strlen (st) * 8) + 8) : 8;
|
||||
y = vid.height - sb_lines - 16;
|
||||
x = cl_hudswap->int_val ? (vid.width - ((strlen (st) * 8) + 8)) : 8;
|
||||
y = vid.height - (sb_lines + 8);
|
||||
Draw_String8 (x, y, st);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue