diff --git a/include/QF/skin.h b/include/QF/skin.h index 60792c42d..2267b4aaa 100644 --- a/include/QF/skin.h +++ b/include/QF/skin.h @@ -42,6 +42,13 @@ #define RSSHOT_WIDTH 320 #define RSSHOT_HEIGHT 200 +// if more than 32 clients are to be supported, then this will need to be +// updated +#define MAX_TRANSLATIONS 32 + +#define PLAYER_WIDTH 296 +#define PLAYER_HEIGHT 194 + typedef struct skin_s { const char *name; qboolean valid; // the skin was found @@ -52,6 +59,7 @@ typedef struct skin_s { } skin_t; skin_t *Skin_SetColormap (skin_t *skin, int cmap); +skin_t *Skin_SetSkin (skin_t *skin, int cmap, const char *skinname); void Skin_SetupSkin (skin_t *skin, int cmap); void Skin_SetTranslation (int cmap, int top, int bottom); void Skin_ProcessTranslation (int cmap, const byte *translation); diff --git a/libs/models/skin.c b/libs/models/skin.c index e84ed1228..cec31b72b 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -42,17 +42,25 @@ static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include +#include "QF/hash.h" #include "QF/image.h" #include "QF/model.h" +#include "QF/pcx.h" +#include "QF/quakefs.h" #include "QF/skin.h" #include "QF/sys.h" +#include "QF/va.h" #include "QF/GLSL/funcs.h" -// if more than 32 clients are to be supported, then this will need to be -// updated -#define MAX_TRANSLATIONS 32 +typedef struct skinbank_s { + char *name; + tex_t *texels; + int users; +} skinbank_t; + static byte translations[MAX_TRANSLATIONS][VID_GRADES * 256]; +static hashtab_t *skin_cache; static skin_t * new_skin (void) @@ -113,8 +121,110 @@ Skin_SetColormap (skin_t *skin, int cmap) return skin; } +skin_t * +Skin_SetSkin (skin_t *skin, int cmap, const char *skinname) +{ + char *name = 0; + skinbank_t *sb = 0; + tex_t *tex = 0; + + if (skinname) { + name = QFS_CompressPath (skinname); + QFS_StripExtension (name, name); + if (strchr (name, '.') || strchr (name, '/')) { + Sys_Printf ("Bad skin name: '%s'\n", skinname); + free (name); + name = 0; + } + } + + do { + QFile *file; + byte *ipix, *opix; + int i; + tex_t *out; + + if (!name) + break; + sb = Hash_Find (skin_cache, name); + if (sb) { + sb->users++; + tex = sb->texels; + break; + } + + if (Hash_NumElements (skin_cache) >= MAX_CACHED_SKINS) { + Sys_Printf ("Too many skins\n"); + free (name); + name = 0; + break; + } + + QFS_FOpenFile (va ("skins/%s.pcx", name), &file); + if (!file) { + Sys_Printf ("Couldn't load skin %s\n", name); + free (name); + name = 0; + break; + } + tex = LoadPCX (file, 0, vid.palette); + Qclose (file); + if (!tex || tex->width > 320 || tex->height > 200) { + Sys_Printf ("Bad skin %s\n", name); + free (name); + name = 0; + tex = 0; + break; + } + out = malloc (field_offset (tex_t, data[PLAYER_WIDTH*PLAYER_HEIGHT])); + out->width = PLAYER_WIDTH; + out->height = PLAYER_HEIGHT; + out->format = tex_palette; + out->palette = vid.palette; + memset (out->data, 0, PLAYER_WIDTH * PLAYER_HEIGHT); + opix = out->data; + ipix = tex->data; + for (i = 0; i < out->height; i++) { + memcpy (opix, ipix, min (tex->width, out->width)); + ipix += tex->width; + opix += out->width; + } + tex = out; + + sb = malloc (sizeof (skinbank_t)); + sb->texels = tex; + sb->name = name; + sb->users = 1; + Hash_Add (skin_cache, sb); + } while (0); + + if (!skin) + skin = new_skin (); + skin->texels = tex; + skin->name = name; + Skin_SetupSkin (skin, cmap); + return skin; +} + +static const char * +skin_getkey (void *sb, void *unused) +{ + return ((skinbank_t *) sb)->name; +} + +static void +skin_free (void *_sb, void *unused) +{ + skinbank_t *sb = (skinbank_t *) _sb; + + free (sb->name); + free (sb->texels); + free (sb); +} + void Skin_Init (void) { + skin_cache = Hash_NewTable (127, skin_getkey, skin_free, 0); Skin_InitTranslations (); } diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index ca5bd0a72..03cceeaa0 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -208,7 +208,6 @@ CL_LinkPacketEntities (void) entity_state_t *s1; model_t *model; packet_entities_t *pack; - //player_info_t *info; pack = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK].packet_entities; @@ -244,26 +243,12 @@ CL_LinkPacketEntities (void) // set colormap if (s1->colormap && (s1->colormap <= MAX_CLIENTS) - && cl.players[s1->colormap - 1].name[0] - && !strcmp (ent->model->name, "progs/player.mdl")) { + && cl.players[s1->colormap - 1].name[0]) { ent->skin = Skin_SetColormap (ent->skin, s1->colormap); - //info = &cl.players[s1->colormap - 1]; } else { ent->skin = Skin_SetColormap (ent->skin, 0); - //info = NULL; } -#if 0 //XXX - if (info && info->skinname && !info->skin) - Skin_Find (info); - if (info && info->skin) { - ent->skin = Skin_NewTempSkin (); - if (ent->skin) { - CL_NewTranslation (s1->colormap - 1, ent->skin); - } - } else { - ent->skin = NULL; - } -#endif + // LordHavoc: cleaned up Endy's coding style, and fixed Endy's bugs // Ender: Extend (Colormod) [QSG - Begin] // N.B: All messy code below is the sole fault of LordHavoc and @@ -494,24 +479,14 @@ CL_LinkPlayers (void) if (state->pls.modelindex == cl_playerindex) { //XXX // use custom skin -#if 0 - if (!info->skin) - Skin_Find (info); - if (info && info->skin) { - ent->skin = Skin_NewTempSkin (); - if (ent->skin) { - CL_NewTranslation (j, ent->skin); - } - } else { - ent->skin = NULL; - } -#endif + Skin_SetSkin (ent->skin, j + 1, info->skinname->value); + ent->min_light = min (cl.fbskins, cl_fb_players->value); if (ent->min_light >= 1.0) ent->fullbright = 1; } else { - ent->skin = NULL; + Skin_SetSkin (ent->skin, j + 1, 0); } // stuff entity in map