Fix corrupted player skins. Fix player colours not always applying properly. Allow richer player colours.

This commit is contained in:
Shpoike 2021-09-11 04:07:03 +01:00
parent a019a2cfc4
commit d7d167c1e9
16 changed files with 260 additions and 193 deletions

View file

@ -329,7 +329,7 @@ void CL_Record_Prespawn(void)
void CL_Record_Spawn(void) void CL_Record_Spawn(void)
{ {
const char *cmd; const char *cmd;
int i; int i, c;
// player names, colors, and frag counts // player names, colors, and frag counts
for (i = 0; i < cl.maxclients; i++) for (i = 0; i < cl.maxclients; i++)
@ -342,7 +342,12 @@ void CL_Record_Spawn(void)
MSG_WriteShort (&net_message, cl.scores[i].frags); MSG_WriteShort (&net_message, cl.scores[i].frags);
MSG_WriteByte (&net_message, svc_updatecolors); MSG_WriteByte (&net_message, svc_updatecolors);
MSG_WriteByte (&net_message, i); MSG_WriteByte (&net_message, i);
MSG_WriteByte (&net_message, cl.scores[i].colors); c = 0;
if (cl.scores[i].shirt.type == 1)
c |= (cl.scores[i].shirt.rgb[0]<<4)&0xf;
if (cl.scores[i].pants.type == 1)
c |= (cl.scores[i].pants.rgb[0]<<0)&0xf;
MSG_WriteByte (&net_message, c);
} }
// send all current light styles // send all current light styles

View file

@ -1382,15 +1382,67 @@ static void CL_ServerExtension_ServerinfoUpdate_f(void)
Info_SetKey(cl.serverinfo, sizeof(cl.serverinfo), newserverkey, newservervalue); Info_SetKey(cl.serverinfo, sizeof(cl.serverinfo), newserverkey, newservervalue);
} }
int Sbar_ColorForMap (int m);
byte *CL_PLColours_ToRGB(plcolour_t *c)
{
if (c->type == 2)
return c->rgb;
else if (c->type == 1)
return (byte *)(d_8to24table + (c->basic<<4)+8);
else
return (byte*)&d_8to24table[15];
}
char *CL_PLColours_ToString(plcolour_t c)
{
if (c.type == 2)
return va("0x%02x%02x%02x", c.rgb[0], c.rgb[1], c.rgb[2]);
else if (c.type == 1)
return va("%i", c.basic);
return "0";
}
plcolour_t CL_PLColours_Parse(const char *s)
{
plcolour_t c;
unsigned int v = strtoul(s, NULL, 0);
if (!strncmp(s, "0x", 2))
{
c.type = 2;
c.basic = 0;
c.rgb[0] = 0xff&(v>>16);
c.rgb[1] = 0xff&(v>>8);
c.rgb[2] = 0xff&(v>>0);
}
else if (*s)
{
c.type = 1;
c.basic = v;
c.rgb[0] = c.rgb[1] = c.rgb[2] = v&0xf;
}
else
{
c.type = 0;
c.rgb[0] = c.rgb[1] = c.rgb[2] = 0;
}
return c;
}
static void CL_UserinfoChanged(scoreboard_t *sb) static void CL_UserinfoChanged(scoreboard_t *sb)
{ {
char tmp[64]; char tmp[64];
plcolour_t top, bot;
Info_GetKey(sb->userinfo, "name", sb->name, sizeof(sb->name)); Info_GetKey(sb->userinfo, "name", sb->name, sizeof(sb->name));
Info_GetKey(sb->userinfo, "topcolor", tmp, sizeof(tmp)); Info_GetKey(sb->userinfo, "topcolor", tmp, sizeof(tmp));
sb->colors = (atoi(tmp)&15)<<4; top = CL_PLColours_Parse(tmp);
Info_GetKey(sb->userinfo, "bottomcolor", tmp, sizeof(tmp)); Info_GetKey(sb->userinfo, "bottomcolor", tmp, sizeof(tmp));
sb->colors |= (atoi(tmp)&15); bot = CL_PLColours_Parse(tmp);
if (!CL_PLColours_Equals(top, sb->shirt) || !CL_PLColours_Equals(bot, sb->pants))
{
sb->shirt = top;
sb->pants = bot;
R_TranslateNewPlayerSkin (sb-cl.scores);
}
} }
static void CL_ServerExtension_FullUserinfo_f(void) static void CL_ServerExtension_FullUserinfo_f(void)
{ {

View file

@ -1972,10 +1972,14 @@ static void CL_ParseClientdata (void)
CL_NewTranslation CL_NewTranslation
===================== =====================
*/ */
static void CL_NewTranslation (int slot) static void CL_NewTranslation (int slot, int vanillacolour)
{ {
if (slot > cl.maxclients) if (slot > cl.maxclients)
Sys_Error ("CL_NewTranslation: slot > cl.maxclients"); Sys_Error ("CL_NewTranslation: slot > cl.maxclients");
//clumsy, but ensures its initialised properly.
cl.scores[slot].shirt = CL_PLColours_Parse(va("%i", (vanillacolour>>4)&0xf));
cl.scores[slot].pants = CL_PLColours_Parse(va("%i", (vanillacolour>>0)&0xf));
R_TranslatePlayerSkin (slot); R_TranslatePlayerSkin (slot);
} }
@ -2586,8 +2590,7 @@ void CL_ParseServerMessage (void)
i = MSG_ReadByte (); i = MSG_ReadByte ();
if (i >= cl.maxclients) if (i >= cl.maxclients)
Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD"); Host_Error ("CL_ParseServerMessage: svc_updatecolors > MAX_SCOREBOARD");
cl.scores[i].colors = MSG_ReadByte (); CL_NewTranslation (i, MSG_ReadByte());
CL_NewTranslation (i);
break; break;
case svc_particle: case svc_particle:

View file

@ -38,9 +38,9 @@ typedef struct
char name[MAX_SCOREBOARDNAME]; char name[MAX_SCOREBOARDNAME];
float entertime; float entertime;
int frags; int frags;
int colors; // two 4 bit fields plcolour_t shirt;
plcolour_t pants;
int ping; int ping;
byte translations[VID_GRADES*256];
char userinfo[8192]; char userinfo[8192];
} scoreboard_t; } scoreboard_t;

View file

@ -26,6 +26,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// draw.h -- these are the only functions outside the refresh allowed // draw.h -- these are the only functions outside the refresh allowed
// to touch the vid buffer // to touch the vid buffer
typedef struct
{
byte type; //0 for none, 1 for legacy colours, 2 for rgb.
byte basic;
byte rgb[3];
} plcolour_t;
plcolour_t CL_PLColours_Parse(const char *s);
char *CL_PLColours_ToString(plcolour_t c);
byte *CL_PLColours_ToRGB(plcolour_t *c);
#define CL_PLColours_Equals(a,b) (!memcmp(&a,&b, sizeof(plcolour_t)))
extern qpic_t *draw_disc; // also used on sbar extern qpic_t *draw_disc; // also used on sbar
void Draw_Init (void); void Draw_Init (void);
@ -33,10 +44,11 @@ void Draw_Character (int x, int y, int num);
void Draw_DebugChar (char num); void Draw_DebugChar (char num);
void Draw_Pic (int x, int y, qpic_t *pic); void Draw_Pic (int x, int y, qpic_t *pic);
void Draw_SubPic (float x, float y, float w, float h, qpic_t *pic, float s1, float t1, float s2, float t2); void Draw_SubPic (float x, float y, float w, float h, qpic_t *pic, float s1, float t1, float s2, float t2);
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom); //johnfitz -- more parameters void Draw_TransPicTranslate (int x, int y, qpic_t *pic, plcolour_t top, plcolour_t bottom); //johnfitz -- more parameters
void Draw_ConsoleBackground (void); //johnfitz -- removed parameter int lines void Draw_ConsoleBackground (void); //johnfitz -- removed parameter int lines
void Draw_TileClear (int x, int y, int w, int h); void Draw_TileClear (int x, int y, int w, int h);
void Draw_Fill (int x, int y, int w, int h, int c, float alpha); //johnfitz -- added alpha void Draw_Fill (int x, int y, int w, int h, int c, float alpha); //johnfitz -- added alpha
void Draw_FillPlayer (int x, int y, int w, int h, plcolour_t c, float alpha); //Spike - for richer player colours.
void Draw_FadeScreen (void); void Draw_FadeScreen (void);
void Draw_String (int x, int y, const char *str); void Draw_String (int x, int y, const char *str);
qpic_t *Draw_PicFromWad2 (const char *name, unsigned int texflags); qpic_t *Draw_PicFromWad2 (const char *name, unsigned int texflags);

View file

@ -705,12 +705,12 @@ Draw_TransPicTranslate -- johnfitz -- rewritten to use texmgr to do translation
Only used for the player color selection menu Only used for the player color selection menu
============= =============
*/ */
void Draw_TransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom) void Draw_TransPicTranslate (int x, int y, qpic_t *pic, plcolour_t top, plcolour_t bottom)
{ {
static int oldtop = -2; static plcolour_t oldtop = {-2};
static int oldbottom = -2; static plcolour_t oldbottom = {-2};
if (top != oldtop || bottom != oldbottom) if (!CL_PLColours_Equals(top, oldtop) || !CL_PLColours_Equals(bottom, oldbottom))
{ {
glpic_t *p = (glpic_t *)pic->data; glpic_t *p = (glpic_t *)pic->data;
gltexture_t *glt = p->gltexture; gltexture_t *glt = p->gltexture;
@ -827,6 +827,31 @@ void Draw_Fill (int x, int y, int w, int h, int c, float alpha) //johnfitz -- ad
glEnable (GL_ALPHA_TEST); //johnfitz -- for alpha glEnable (GL_ALPHA_TEST); //johnfitz -- for alpha
glEnable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_2D);
} }
void Draw_FillPlayer (int x, int y, int w, int h, plcolour_t c, float alpha)
{
glDisable (GL_TEXTURE_2D);
glEnable (GL_BLEND); //johnfitz -- for alpha
glDisable (GL_ALPHA_TEST); //johnfitz -- for alpha
if (c.type == 2)
glColor4f (c.rgb[0]/255.0, c.rgb[1]/255.0, c.rgb[2]/255.0, alpha); //johnfitz -- added alpha
else
{
byte *pal = (byte *)&d_8to24table[(c.basic<<4) + 8]; //johnfitz -- use d_8to24table instead of host_basepal
glColor4f (pal[0]/255.0, pal[1]/255.0, pal[2]/255.0, alpha); //johnfitz -- added alpha
}
glBegin (GL_QUADS);
glVertex2f (x,y);
glVertex2f (x+w, y);
glVertex2f (x+w, y+h);
glVertex2f (x, y+h);
glEnd ();
glColor3f (1,1,1);
glDisable (GL_BLEND); //johnfitz -- for alpha
glEnable (GL_ALPHA_TEST); //johnfitz -- for alpha
glEnable (GL_TEXTURE_2D);
}
/* /*
================ ================

View file

@ -26,6 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quakedef.h" #include "quakedef.h"
extern gltexture_t *playertextures[MAX_SCOREBOARD]; //spike - to ensure skins don't get screwed randomly.
qmodel_t *loadmodel; qmodel_t *loadmodel;
char loadname[32]; // for hunk tags char loadname[32]; // for hunk tags
@ -324,6 +326,7 @@ qmodel_t *Mod_LoadModel (qmodel_t *mod, qboolean crash)
byte *buf; byte *buf;
byte stackbuf[1024]; // avoid dirtying the cache heap byte stackbuf[1024]; // avoid dirtying the cache heap
int mod_type; int mod_type;
int i;
if (!mod->needload) if (!mod->needload)
{ {
@ -457,6 +460,10 @@ qmodel_t *Mod_LoadModel (qmodel_t *mod, qboolean crash)
Mod_SetExtraFlags (mod); //johnfitz. spike -- moved this to be generic, because most of the flags are anyway. Mod_SetExtraFlags (mod); //johnfitz. spike -- moved this to be generic, because most of the flags are anyway.
for (i = 0; i < countof(playertextures); i++)
if (playertextures[i] && playertextures[i]->owner == mod)
R_TranslateNewPlayerSkin(i);
return mod; return mod;
} }

View file

@ -254,15 +254,10 @@ R_TranslatePlayerSkin -- johnfitz -- rewritten. also, only handles new colors,
*/ */
void R_TranslatePlayerSkin (int playernum) void R_TranslatePlayerSkin (int playernum)
{ {
int top, bottom;
top = (cl.scores[playernum].colors & 0xf0)>>4;
bottom = cl.scores[playernum].colors &15;
//FIXME: if gl_nocolors is on, then turned off, the textures may be out of sync with the scoreboard colors. //FIXME: if gl_nocolors is on, then turned off, the textures may be out of sync with the scoreboard colors.
if (!gl_nocolors.value) if (!gl_nocolors.value)
if (playertextures[playernum]) if (playertextures[playernum])
TexMgr_ReloadImage (playertextures[playernum], top, bottom); TexMgr_ReloadImage (playertextures[playernum], cl.scores[playernum].shirt, cl.scores[playernum].pants);
} }
/* /*

View file

@ -37,6 +37,8 @@ static int numgltextures;
static gltexture_t *active_gltextures, *free_gltextures; static gltexture_t *active_gltextures, *free_gltextures;
gltexture_t *notexture, *nulltexture; gltexture_t *notexture, *nulltexture;
plcolour_t plcolour_none = {0};
unsigned int d_8to24table[256]; unsigned int d_8to24table[256];
unsigned int d_8to24table_fbright[256]; unsigned int d_8to24table_fbright[256];
unsigned int d_8to24table_fbright_fence[256]; unsigned int d_8to24table_fbright_fence[256];
@ -1321,7 +1323,7 @@ static void TexMgr_LoadImage8 (gltexture_t *glt, byte *data)
extern cvar_t gl_fullbrights; extern cvar_t gl_fullbrights;
qboolean padw = false, padh = false; qboolean padw = false, padh = false;
byte padbyte; byte padbyte;
unsigned int *usepal; unsigned int *usepal, translation[256];
int i; int i;
// HACK HACK HACK -- taken from tomazquake // HACK HACK HACK -- taken from tomazquake
@ -1373,6 +1375,68 @@ static void TexMgr_LoadImage8 (gltexture_t *glt, byte *data)
padbyte = 255; padbyte = 255;
} }
if (glt->shirt.type || glt->pants.type)
{
int shirt, pants, m;
//create new translation table
for (i = 0; i < 256; i++)
translation[i] = usepal[i];
if (glt->shirt.type == 2)
{
for (i = 0; i < 16; i++)
{
m = i|(i<<4);
((byte *) &translation[TOP_RANGE+i])[0] = (m * glt->shirt.rgb[0])>>8;
((byte *) &translation[TOP_RANGE+i])[1] = (m * glt->shirt.rgb[1])>>8;
((byte *) &translation[TOP_RANGE+i])[2] = (m * glt->shirt.rgb[2])>>8;
((byte *) &translation[TOP_RANGE+i])[3] = 255;
}
}
else if (glt->shirt.type == 1)
{
shirt = glt->shirt.rgb[0] * 16;
if (shirt < 128)
{
for (i = 0; i < 16; i++)
translation[TOP_RANGE+i] = usepal[shirt + i];
}
else
{
for (i = 0; i < 16; i++)
translation[TOP_RANGE+i] = usepal[shirt+15-i];
}
}
if (glt->pants.type == 2)
{
for (i = 0; i < 16; i++)
{
m = i|(i<<4);
((byte *) &translation[BOTTOM_RANGE+i])[0] = (m * glt->pants.rgb[0])>>8;
((byte *) &translation[BOTTOM_RANGE+i])[1] = (m * glt->pants.rgb[1])>>8;
((byte *) &translation[BOTTOM_RANGE+i])[2] = (m * glt->pants.rgb[2])>>8;
((byte *) &translation[BOTTOM_RANGE+i])[3] = 255;
}
}
else if (glt->pants.type == 1)
{
pants = glt->pants.rgb[0] * 16;
if (pants < 128)
{
for (i = 0; i < 16; i++)
translation[BOTTOM_RANGE+i] = usepal[pants + i];
}
else
{
for (i = 0; i < 16; i++)
translation[BOTTOM_RANGE+i] = usepal[pants+15-i];
}
}
usepal = translation;
}
// pad each dimention, but only if it's not going to be downsampled later // pad each dimention, but only if it's not going to be downsampled later
if (glt->flags & TEXPREF_PAD) if (glt->flags & TEXPREF_PAD)
{ {
@ -1467,8 +1531,8 @@ gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int
glt->width = width; glt->width = width;
glt->height = height; glt->height = height;
glt->flags = flags; glt->flags = flags;
glt->shirt = -1; glt->shirt.type = 0;
glt->pants = -1; glt->pants.type = 0;
q_strlcpy (glt->source_file, source_file, sizeof(glt->source_file)); q_strlcpy (glt->source_file, source_file, sizeof(glt->source_file));
glt->source_offset = source_offset; glt->source_offset = source_offset;
glt->source_format = format; glt->source_format = format;
@ -1539,11 +1603,10 @@ gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int
TexMgr_ReloadImage -- reloads a texture, and colormaps it if needed TexMgr_ReloadImage -- reloads a texture, and colormaps it if needed
================ ================
*/ */
void TexMgr_ReloadImage (gltexture_t *glt, int shirt, int pants) void TexMgr_ReloadImage (gltexture_t *glt, plcolour_t shirt, plcolour_t pants)
{ {
byte translation[256]; byte *data = NULL;
byte *src, *dst, *data = NULL, *translated; int mark, size;
int mark, size, i;
qboolean malloced = false; qboolean malloced = false;
enum srcformat fmt = glt->source_format; enum srcformat fmt = glt->source_format;
// //
@ -1584,9 +1647,9 @@ invalid: Con_Printf ("TexMgr_ReloadImage: invalid source for %s\n", glt->name);
// //
// if shirt and pants are -1,-1, use existing shirt and pants colors // if shirt and pants are -1,-1, use existing shirt and pants colors
// if existing shirt and pants colors are -1,-1, don't bother colormapping // if existing shirt and pants colors are -1,-1, don't bother colormapping
if (shirt > -1 && pants > -1) if (shirt.type || pants.type)
{ {
if (glt->source_format == SRC_INDEXED) if (fmt == SRC_INDEXED)
{ {
glt->shirt = shirt; glt->shirt = shirt;
glt->pants = pants; glt->pants = pants;
@ -1594,50 +1657,11 @@ invalid: Con_Printf ("TexMgr_ReloadImage: invalid source for %s\n", glt->name);
else else
Con_Printf ("TexMgr_ReloadImage: can't colormap a non SRC_INDEXED texture: %s\n", glt->name); Con_Printf ("TexMgr_ReloadImage: can't colormap a non SRC_INDEXED texture: %s\n", glt->name);
} }
if (glt->shirt > -1 && glt->pants > -1)
{
//create new translation table
for (i = 0; i < 256; i++)
translation[i] = i;
shirt = glt->shirt * 16;
if (shirt < 128)
{
for (i = 0; i < 16; i++)
translation[TOP_RANGE+i] = shirt + i;
}
else
{
for (i = 0; i < 16; i++)
translation[TOP_RANGE+i] = shirt+15-i;
}
pants = glt->pants * 16;
if (pants < 128)
{
for (i = 0; i < 16; i++)
translation[BOTTOM_RANGE+i] = pants + i;
}
else
{
for (i = 0; i < 16; i++)
translation[BOTTOM_RANGE+i] = pants+15-i;
}
//translate texture
size = glt->width * glt->height;
dst = translated = (byte *) Hunk_Alloc (size);
src = data;
for (i = 0; i < size; i++)
*dst++ = translation[*src++];
data = translated;
}
// //
// upload it // upload it
// //
switch (glt->source_format) switch (fmt)
{ {
case SRC_INDEXED: case SRC_INDEXED:
TexMgr_LoadImage8 (glt, data); TexMgr_LoadImage8 (glt, data);
@ -1681,7 +1705,7 @@ void TexMgr_ReloadImages (void)
for (glt = active_gltextures; glt; glt = glt->next) for (glt = active_gltextures; glt; glt = glt->next)
{ {
glGenTextures(1, &glt->texnum); glGenTextures(1, &glt->texnum);
TexMgr_ReloadImage (glt, -1, -1); TexMgr_ReloadImage (glt, plcolour_none, plcolour_none);
} }
in_reload_images = false; in_reload_images = false;
@ -1698,7 +1722,7 @@ void TexMgr_ReloadNobrightImages (void)
for (glt = active_gltextures; glt; glt = glt->next) for (glt = active_gltextures; glt; glt = glt->next)
if (glt->flags & TEXPREF_NOBRIGHT) if (glt->flags & TEXPREF_NOBRIGHT)
TexMgr_ReloadImage(glt, -1, -1); TexMgr_ReloadImage(glt, plcolour_none, plcolour_none);
} }
/* /*

View file

@ -62,8 +62,8 @@ typedef struct gltexture_s {
unsigned int source_width; //size of image in source data unsigned int source_width; //size of image in source data
unsigned int source_height; //size of image in source data unsigned int source_height; //size of image in source data
unsigned short source_crc; //generated by source data before modifications unsigned short source_crc; //generated by source data before modifications
signed char shirt; //0-13 shirt color, or -1 if never colormapped plcolour_t shirt;
signed char pants; //0-13 pants color, or -1 if never colormapped plcolour_t pants;
//used for rendering //used for rendering
int visframe; //matches r_framecount if texture was bound this frame int visframe; //matches r_framecount if texture was bound this frame
} gltexture_t; } gltexture_t;
@ -98,7 +98,7 @@ void TexMgr_BlockSize (enum srcformat format, int *bytes, int *width, int *heigh
// IMAGE LOADING // IMAGE LOADING
gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int height, enum srcformat format, gltexture_t *TexMgr_LoadImage (qmodel_t *owner, const char *name, int width, int height, enum srcformat format,
byte *data, const char *source_file, src_offset_t source_offset, unsigned flags); byte *data, const char *source_file, src_offset_t source_offset, unsigned flags);
void TexMgr_ReloadImage (gltexture_t *glt, int shirt, int pants); void TexMgr_ReloadImage (gltexture_t *glt, plcolour_t shirt, plcolour_t pants);
void TexMgr_ReloadImages (void); void TexMgr_ReloadImages (void);
void TexMgr_ReloadNobrightImages (void); void TexMgr_ReloadNobrightImages (void);

View file

@ -1671,7 +1671,7 @@ void Host_Color_f(void)
if (Cmd_Argc() == 1) if (Cmd_Argc() == 1)
{ {
Con_Printf ("\"%s\" is \"%i %i\"\n", Cmd_Argv(0), ((int)cl_topcolor.value), ((int)cl_bottomcolor.value)); Con_Printf ("\"%s\" is \"%s %s\"\n", Cmd_Argv(0), CL_PLColours_ToString(CL_PLColours_Parse(cl_topcolor.string)), CL_PLColours_ToString(CL_PLColours_Parse(cl_bottomcolor.string)));
Con_Printf ("color <0-13> [0-13]\n"); Con_Printf ("color <0-13> [0-13]\n");
return; return;
} }

View file

@ -569,7 +569,7 @@ byte *Image_LoadImage (const char *name, int *width, int *height, enum srcformat
q_snprintf (loadfilename, sizeof(loadfilename), "%s%s.lmp", "", name); q_snprintf (loadfilename, sizeof(loadfilename), "%s%s.lmp", "", name);
COM_FOpenFile (loadfilename, &f, NULL); COM_FOpenFile (loadfilename, &f, NULL);
if (f) if (f)
return Image_LoadLMP (f, width, height); return Image_LoadLMP (f, width, height, fmt);
return NULL; return NULL;
} }
@ -1011,13 +1011,11 @@ typedef struct
Image_LoadLMP Image_LoadLMP
============ ============
*/ */
byte *Image_LoadLMP (FILE *f, int *width, int *height) byte *Image_LoadLMP (FILE *f, int *width, int *height, enum srcformat *fmt)
{ {
lmpheader_t qpic; lmpheader_t qpic;
size_t pix; size_t pix;
void *data; void *data;
byte *src;
unsigned int *dest;
fread(&qpic, sizeof(qpic), 1, f); fread(&qpic, sizeof(qpic), 1, f);
qpic.width = LittleLong (qpic.width); qpic.width = LittleLong (qpic.width);
@ -1031,19 +1029,13 @@ byte *Image_LoadLMP (FILE *f, int *width, int *height)
return NULL; return NULL;
} }
data = (byte *) Hunk_Alloc(pix*4); //+1 to allow reading padding byte on last line data = (byte *) Hunk_Alloc(pix); //+1 to allow reading padding byte on last line
dest = data; fread(data, 1, pix, f);
src = (byte *)data + pix*(4-1);
fread(src, 1, pix, f);
while(pix --> 0)
*dest++ = d_8to24table[*src++];
fclose(f); fclose(f);
*width = qpic.width; *width = qpic.width;
*height = qpic.height; *height = qpic.height;
*fmt = SRC_INDEXED;
return data; return data;
} }

View file

@ -25,11 +25,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//image.h -- image reading / writing //image.h -- image reading / writing
enum srcformat;
//be sure to free the hunk after using these loading functions //be sure to free the hunk after using these loading functions
byte *Image_LoadTGA (FILE *f, int *width, int *height); byte *Image_LoadTGA (FILE *f, int *width, int *height);
byte *Image_LoadPCX (FILE *f, int *width, int *height); byte *Image_LoadPCX (FILE *f, int *width, int *height);
byte *Image_LoadLMP (FILE *f, int *width, int *height); byte *Image_LoadLMP (FILE *f, int *width, int *height, enum srcformat *fmt);
enum srcformat;
byte *Image_LoadImage (const char *name, int *width, int *height, enum srcformat *fmt, qboolean *malloced); byte *Image_LoadImage (const char *name, int *width, int *height, enum srcformat *fmt, qboolean *malloced);
qboolean Image_WriteTGA (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown); qboolean Image_WriteTGA (const char *name, byte *data, int width, int height, int bpp, qboolean upsidedown);

View file

@ -138,7 +138,7 @@ void M_DrawPic (int x, int y, qpic_t *pic)
Draw_Pic (x, y, pic); //johnfitz -- simplified becuase centering is handled elsewhere Draw_Pic (x, y, pic); //johnfitz -- simplified becuase centering is handled elsewhere
} }
void M_DrawTransPicTranslate (int x, int y, qpic_t *pic, int top, int bottom) //johnfitz -- more parameters void M_DrawTransPicTranslate (int x, int y, qpic_t *pic, plcolour_t top, plcolour_t bottom) //johnfitz -- more parameters
{ {
Draw_TransPicTranslate (x, y, pic, top, bottom); //johnfitz -- simplified becuase centering is handled elsewhere Draw_TransPicTranslate (x, y, pic, top, bottom); //johnfitz -- simplified becuase centering is handled elsewhere
} }
@ -653,15 +653,28 @@ void M_MultiPlayer_Key (int key)
//============================================================================= //=============================================================================
/* SETUP MENU */ /* SETUP MENU */
int setup_cursor = 4; static int setup_cursor = 4;
int setup_cursor_table[] = {40, 56, 80, 104, 140}; static int setup_cursor_table[] = {40, 56, 80, 104, 140};
char setup_hostname[16]; static char setup_hostname[16];
char setup_myname[16]; static char setup_myname[16];
int setup_oldtop; static plcolour_t setup_oldtop;
int setup_oldbottom; static plcolour_t setup_oldbottom;
int setup_top; static plcolour_t setup_top;
int setup_bottom; static plcolour_t setup_bottom;
void M_AdjustColour(plcolour_t *tr, int dir)
{
{
tr->type = 1;
if (tr->basic+dir < 0)
tr->basic = 13;
else if (tr->basic+dir > 13)
tr->basic = 0;
else
tr->basic += dir;
}
}
#define NUM_SETUP_CMDS 5 #define NUM_SETUP_CMDS 5
@ -672,8 +685,8 @@ void M_Menu_Setup_f (void)
m_entersound = true; m_entersound = true;
Q_strcpy(setup_myname, cl_name.string); Q_strcpy(setup_myname, cl_name.string);
Q_strcpy(setup_hostname, hostname.string); Q_strcpy(setup_hostname, hostname.string);
setup_top = setup_oldtop = ((int)cl_topcolor.value) >> 4; setup_top = setup_oldtop = CL_PLColours_Parse(cl_topcolor.string);
setup_bottom = setup_oldbottom = ((int)cl_bottomcolor.value) & 15; setup_bottom = setup_oldbottom = CL_PLColours_Parse(cl_bottomcolor.string);
IN_UpdateGrabs(); IN_UpdateGrabs();
} }
@ -744,9 +757,9 @@ void M_Setup_Key (int k)
return; return;
S_LocalSound ("misc/menu3.wav"); S_LocalSound ("misc/menu3.wav");
if (setup_cursor == 2) if (setup_cursor == 2)
setup_top = setup_top - 1; M_AdjustColour(&setup_top, -1);
if (setup_cursor == 3) if (setup_cursor == 3)
setup_bottom = setup_bottom - 1; M_AdjustColour(&setup_bottom, -1);
break; break;
case K_RIGHTARROW: case K_RIGHTARROW:
if (setup_cursor < 2) if (setup_cursor < 2)
@ -754,9 +767,9 @@ void M_Setup_Key (int k)
forward: forward:
S_LocalSound ("misc/menu3.wav"); S_LocalSound ("misc/menu3.wav");
if (setup_cursor == 2) if (setup_cursor == 2)
setup_top = setup_top + 1; M_AdjustColour(&setup_top, +1);
if (setup_cursor == 3) if (setup_cursor == 3)
setup_bottom = setup_bottom + 1; M_AdjustColour(&setup_bottom, +1);
break; break;
case K_ENTER: case K_ENTER:
@ -773,8 +786,8 @@ forward:
Cbuf_AddText ( va ("name \"%s\"\n", setup_myname) ); Cbuf_AddText ( va ("name \"%s\"\n", setup_myname) );
if (Q_strcmp(hostname.string, setup_hostname) != 0) if (Q_strcmp(hostname.string, setup_hostname) != 0)
Cvar_Set("hostname", setup_hostname); Cvar_Set("hostname", setup_hostname);
if (setup_top != setup_oldtop || setup_bottom != setup_oldbottom) if (!CL_PLColours_Equals(setup_top, setup_oldtop) || !CL_PLColours_Equals(setup_bottom, setup_oldbottom))
Cbuf_AddText( va ("color %i %i\n", setup_top, setup_bottom) ); Cbuf_AddText( va ("color %s %s\n", CL_PLColours_ToString(setup_top), CL_PLColours_ToString(setup_bottom)) );
m_entersound = true; m_entersound = true;
M_Menu_MultiPlayer_f (); M_Menu_MultiPlayer_f ();
break; break;
@ -793,15 +806,6 @@ forward:
} }
break; break;
} }
if (setup_top > 13)
setup_top = 0;
if (setup_top < 0)
setup_top = 13;
if (setup_bottom > 13)
setup_bottom = 0;
if (setup_bottom < 0)
setup_bottom = 13;
} }

View file

@ -5435,20 +5435,20 @@ void PF_cl_playerkey_internal(int player, const char *key, qboolean retfloat)
q_snprintf(buf, sizeof(buf), "%g", cl.scores[player].entertime); q_snprintf(buf, sizeof(buf), "%g", cl.scores[player].entertime);
else if (!strcmp(key, "topcolor_rgb")) else if (!strcmp(key, "topcolor_rgb"))
{ {
byte *pal = (byte *)d_8to24table + 4*Sbar_ColorForMap((cl.scores[player].colors)&0xf0); //johnfitz -- use d_8to24table instead of host_basepal byte *pal = CL_PLColours_ToRGB(&cl.scores[player].shirt);
q_snprintf(buf, sizeof(buf), "%g %g %g", pal[0]/255.0, pal[1]/255.0, pal[2]/255.0); q_snprintf(buf, sizeof(buf), "%g %g %g", pal[0]/255.0, pal[1]/255.0, pal[2]/255.0);
} }
else if (!strcmp(key, "bottomcolor_rgb")) else if (!strcmp(key, "bottomcolor_rgb"))
{ {
byte *pal = (byte *)d_8to24table + 4*Sbar_ColorForMap((cl.scores[player].colors<<4)&0xf0); //johnfitz -- use d_8to24table instead of host_basepal byte *pal = CL_PLColours_ToRGB(&cl.scores[player].pants);
q_snprintf(buf, sizeof(buf), "%g %g %g", pal[0]/255.0, pal[1]/255.0, pal[2]/255.0); q_snprintf(buf, sizeof(buf), "%g %g %g", pal[0]/255.0, pal[1]/255.0, pal[2]/255.0);
} }
else if (!strcmp(key, "topcolor")) else if (!strcmp(key, "topcolor"))
q_snprintf(buf, sizeof(buf), "%i", (cl.scores[player].colors>>4)&0xf); ret = CL_PLColours_ToString(cl.scores[player].shirt);
else if (!strcmp(key, "bottomcolor")) else if (!strcmp(key, "bottomcolor"))
q_snprintf(buf, sizeof(buf), "%i", cl.scores[player].colors&0xf); ret = CL_PLColours_ToString(cl.scores[player].pants);
else if (!strcmp(key, "team")) //quakeworld uses team infokeys to decide teams (instead of colours). but NQ never did, so that's fun. Lets allow mods to use either so that they can favour QW and let the engine hide differences . else if (!strcmp(key, "team")) //quakeworld uses team infokeys to decide teams (instead of colours). but NQ never did, so that's fun. Lets allow mods to use either so that they can favour QW and let the engine hide differences .
q_snprintf(buf, sizeof(buf), "%i", (cl.scores[player].colors&0xf)+1); q_snprintf(buf, sizeof(buf), "%i", (cl.scores[player].pants.basic)+1);
else if (!strcmp(key, "userid")) else if (!strcmp(key, "userid"))
ret = NULL; //unknown ret = NULL; //unknown
// else if (!strcmp(key, "vignored")) //checks to see this player's voicechat is ignored. // else if (!strcmp(key, "vignored")) //checks to see this player's voicechat is ignored.
@ -6941,9 +6941,10 @@ static void PF_cl_getrenderentity(void)
{ {
int palidx = cl.entities[entnum].netstate.colormap; int palidx = cl.entities[entnum].netstate.colormap;
byte *pal; byte *pal;
if (!(cl.entities[entnum].netstate.eflags & EFLAGS_COLOURMAPPED)) if ((cl.entities[entnum].netstate.eflags & EFLAGS_COLOURMAPPED) || palidx >= cl.maxclients)
palidx = cl.scores[palidx].colors; pal = (byte *)d_8to24table + 4*Sbar_ColorForMap(palidx&0x0f);
pal = (byte *)d_8to24table + 4*Sbar_ColorForMap(palidx&0x0f); else
pal = CL_PLColours_ToRGB(&cl.scores[palidx].pants);
G_FLOAT(OFS_RETURN+0) = pal[0] / 255.0; G_FLOAT(OFS_RETURN+0) = pal[0] / 255.0;
G_FLOAT(OFS_RETURN+1) = pal[1] / 255.0; G_FLOAT(OFS_RETURN+1) = pal[1] / 255.0;
G_FLOAT(OFS_RETURN+2) = pal[2] / 255.0; G_FLOAT(OFS_RETURN+2) = pal[2] / 255.0;
@ -6953,9 +6954,10 @@ static void PF_cl_getrenderentity(void)
{ {
int palidx = cl.entities[entnum].netstate.colormap; int palidx = cl.entities[entnum].netstate.colormap;
byte *pal; byte *pal;
if (!(cl.entities[entnum].netstate.eflags & EFLAGS_COLOURMAPPED)) if ((cl.entities[entnum].netstate.eflags & EFLAGS_COLOURMAPPED) || palidx >= cl.maxclients)
palidx = cl.scores[palidx].colors; pal = (byte *)d_8to24table + 4*Sbar_ColorForMap(palidx&0xf0);
pal = (byte *)d_8to24table + 4*Sbar_ColorForMap(palidx&0xf0); else
pal = CL_PLColours_ToRGB(&cl.scores[palidx].shirt);
G_FLOAT(OFS_RETURN+0) = pal[0] / 255.0; G_FLOAT(OFS_RETURN+0) = pal[0] / 255.0;
G_FLOAT(OFS_RETURN+1) = pal[1] / 255.0; G_FLOAT(OFS_RETURN+1) = pal[1] / 255.0;
G_FLOAT(OFS_RETURN+2) = pal[2] / 255.0; G_FLOAT(OFS_RETURN+2) = pal[2] / 255.0;

View file

@ -464,11 +464,6 @@ void Sbar_DrawNum (int x, int y, int num, int digits, int color)
//============================================================================= //=============================================================================
int fragsort[MAX_SCOREBOARD]; int fragsort[MAX_SCOREBOARD];
char scoreboardtext[MAX_SCOREBOARD][20];
int scoreboardtop[MAX_SCOREBOARD];
int scoreboardbottom[MAX_SCOREBOARD];
int scoreboardcount[MAX_SCOREBOARD];
int scoreboardlines; int scoreboardlines;
/* /*
@ -510,35 +505,6 @@ int Sbar_ColorForMap (int m)
return m < 128 ? m + 8 : m + 8; return m < 128 ? m + 8 : m + 8;
} }
/*
===============
Sbar_UpdateScoreboard
===============
*/
void Sbar_UpdateScoreboard (void)
{
int i, k;
int top, bottom;
scoreboard_t *s;
Sbar_SortFrags ();
// draw the text
memset (scoreboardtext, 0, sizeof(scoreboardtext));
for (i = 0; i < scoreboardlines; i++)
{
k = fragsort[i];
s = &cl.scores[k];
sprintf (&scoreboardtext[i][1], "%3i %s", s->frags, s->name);
top = s->colors & 0xf0;
bottom = (s->colors & 15) <<4;
scoreboardtop[i] = Sbar_ColorForMap (top);
scoreboardbottom[i] = Sbar_ColorForMap (bottom);
}
}
/* /*
=============== ===============
Sbar_SoloScoreboard -- johnfitz -- new layout Sbar_SoloScoreboard -- johnfitz -- new layout
@ -829,7 +795,7 @@ Sbar_DrawFrags -- johnfitz -- heavy revision
*/ */
void Sbar_DrawFrags (void) void Sbar_DrawFrags (void)
{ {
int numscores, i, x, color; int numscores, i, x;
char num[12]; char num[12];
scoreboard_t *s; scoreboard_t *s;
@ -845,14 +811,10 @@ void Sbar_DrawFrags (void)
continue; continue;
// top color // top color
color = s->colors & 0xf0; Draw_FillPlayer (x + 10, 1, 28, 4, s->shirt, 1);
color = Sbar_ColorForMap (color);
Draw_Fill (x + 10, 1, 28, 4, color, 1);
// bottom color // bottom color
color = (s->colors & 15)<<4; Draw_FillPlayer (x + 10, 5, 28, 3, s->pants, 1);
color = Sbar_ColorForMap (color);
Draw_Fill (x + 10, 5, 28, 3, color, 1);
// number // number
sprintf (num, "%3i", s->frags); sprintf (num, "%3i", s->frags);
@ -885,32 +847,26 @@ void Sbar_DrawFace (void)
// PGM 03/02/97 - fixed so color swatch only appears in CTF modes // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
if (rogue && (cl.maxclients != 1) && (teamplay.value>3) && (teamplay.value<7)) if (rogue && (cl.maxclients != 1) && (teamplay.value>3) && (teamplay.value<7))
{ {
int top, bottom;
int xofs; int xofs;
char num[12]; char num[12];
scoreboard_t *s; scoreboard_t *s;
s = &cl.scores[cl.viewentity - 1]; s = &cl.scores[cl.viewentity - 1];
// draw background // draw background
top = s->colors & 0xf0;
bottom = (s->colors & 15)<<4;
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
if (cl.gametype == GAME_DEATHMATCH) if (cl.gametype == GAME_DEATHMATCH)
xofs = 113; xofs = 113;
else else
xofs = ((vid.width - 320)>>1) + 113; xofs = ((vid.width - 320)>>1) + 113;
Sbar_DrawPic (112, 0, rsb_teambord); Sbar_DrawPic (112, 0, rsb_teambord);
Draw_Fill (xofs, /*vid.height-*/24+3, 22, 9, top, 1); //johnfitz -- sbar coords are now relative Draw_FillPlayer (xofs, /*vid.height-*/24+3, 22, 9, s->shirt, 1); //johnfitz -- sbar coords are now relative
Draw_Fill (xofs, /*vid.height-*/24+12, 22, 9, bottom, 1); //johnfitz -- sbar coords are now relative Draw_FillPlayer (xofs, /*vid.height-*/24+12, 22, 9, s->pants, 1); //johnfitz -- sbar coords are now relative
// draw number // draw number
f = s->frags; f = s->frags;
sprintf (num, "%3i",f); sprintf (num, "%3i",f);
if (top == 8) if (s->shirt.type == 1 && s->shirt.basic == 0) //white team. FIXME: vanilla says top, but I suspect it should be the lower colour, as that's the actual team nq sees.
{ {
if (num[0] != ' ') if (num[0] != ' ')
Sbar_DrawCharacter(113, 3, 18 + num[0] - '0'); Sbar_DrawCharacter(113, 3, 18 + num[0] - '0');
@ -1240,7 +1196,6 @@ void Sbar_DeathmatchOverlay (void)
{ {
qpic_t *pic; qpic_t *pic;
int i, k, l; int i, k, l;
int top, bottom;
int x, y, f; int x, y, f;
char num[12]; char num[12];
scoreboard_t *s; scoreboard_t *s;
@ -1266,16 +1221,11 @@ void Sbar_DeathmatchOverlay (void)
continue; continue;
// draw background // draw background
top = s->colors & 0xf0;
bottom = (s->colors & 15)<<4;
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
if (S_Voip_Speaking(k)) //spike -- display an underlay for people who are speaking if (S_Voip_Speaking(k)) //spike -- display an underlay for people who are speaking
Draw_Fill ( x, y, 320-x*2, 8, ((k+1)==cl.viewentity)?75:73, 1); Draw_Fill ( x, y, 320-x*2, 8, ((k+1)==cl.viewentity)?75:73, 1);
Draw_Fill ( x, y, 40, 4, top, 1); //johnfitz -- stretched overlays Draw_FillPlayer ( x, y, 40, 4, s->shirt, 1); //johnfitz -- stretched overlays
Draw_Fill ( x, y+4, 40, 4, bottom, 1); //johnfitz -- stretched overlays Draw_FillPlayer ( x, y+4, 40, 4, s->pants, 1); //johnfitz -- stretched overlays
// draw number // draw number
f = s->frags; f = s->frags;
@ -1332,7 +1282,7 @@ Sbar_MiniDeathmatchOverlay
*/ */
void Sbar_MiniDeathmatchOverlay (void) void Sbar_MiniDeathmatchOverlay (void)
{ {
int i, k, top, bottom, x, y, f, numlines; int i, k, x, y, f, numlines;
char num[12]; char num[12];
float scale; //johnfitz float scale; //johnfitz
scoreboard_t *s; scoreboard_t *s;
@ -1372,13 +1322,8 @@ void Sbar_MiniDeathmatchOverlay (void)
continue; continue;
// colors // colors
top = s->colors & 0xf0; Draw_FillPlayer (x, y+1, 40, 4, s->shirt, 1);
bottom = (s->colors & 15)<<4; Draw_FillPlayer (x, y+5, 40, 3, s->pants, 1);
top = Sbar_ColorForMap (top);
bottom = Sbar_ColorForMap (bottom);
Draw_Fill (x, y+1, 40, 4, top, 1);
Draw_Fill (x, y+5, 40, 3, bottom, 1);
// number // number
f = s->frags; f = s->frags;