diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 45d1e696a..721bb9cb2 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -3006,6 +3006,14 @@ void CL_NewTranslation (int slot) top = cl_teamtopcolor; if (cl_teambottomcolor != ~0) bottom = cl_teambottomcolor; + + if (player->colourised) + { + if (player->colourised->topcolour != ~0) + top = player->colourised->topcolour; + if (player->colourised->bottomcolour != ~0) + bottom = player->colourised->bottomcolour; + } } else { @@ -3074,6 +3082,8 @@ void CL_ProcessUserInfo (int slot, player_info_t *player) */ player->model = NULL; + player->colourised = TP_FindColours(player->name); + // If it's us if (slot == cl.playernum[0] && player->name[0]) { diff --git a/engine/client/client.h b/engine/client/client.h index 2698d15af..54922d408 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -126,6 +126,14 @@ typedef struct } q2player_state_t; #endif +typedef struct colourised_s { + char name[64]; + unsigned int topcolour; + unsigned int bottomcolour; + char skin[64]; + struct colourised_s *next; +} colourised_t; + #define MAX_SCOREBOARDNAME 64 #define MAX_DISPLAYEDNAME 16 typedef struct player_info_s @@ -143,6 +151,8 @@ typedef struct player_info_s qboolean ignored; + colourised_t *colourised; + // skin information unsigned int rtopcolor; //real, according to their userinfo unsigned int rbottomcolor; @@ -389,6 +399,8 @@ typedef struct int signon; #endif translation_t language; + + colourised_t *colourised; } client_static_t; extern client_static_t cls; diff --git a/engine/client/skin.c b/engine/client/skin.c index 679319d38..4f25ebab4 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -92,6 +92,11 @@ char *Skin_FindName (player_info_t *sc) */ if (!skinname || !skinname[0]) skinname = teammate ? cl_teamskin.string : cl_enemyskin.string; + + //per-player skin forcing + if (teammate && sc->colourised && *sc->colourised->skin) + skinname = sc->colourised->skin; + if (skinname[0] && !strchr(skinname, '/')) // a '/' in a skin name is deemed as a model name, so we ignore it. Q_strncpyz(name, skinname, sizeof(name)); } diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 326a188aa..72c8baf3d 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -1785,7 +1785,29 @@ static unsigned int TP_ForceColour(char *col) return ~0; if (!strncmp(col, "0x", 2)) { - bitval = 0x01000000 | strtoul(col+2, NULL, 16); + if (strlen(col+2) == 3) + { + bitval = strtoul(col+2, NULL, 16); + bitval = ((bitval & 0xf00)<<12) | ((bitval & 0x0f0)<<8) | ((bitval & 0x00f)<<4); + bitval |= 0x01000000; + } + else + bitval = 0x01000000 | strtoul(col+2, NULL, 16); + if (bitval == ~0) + bitval = 0x01ffffff; + return bitval; + } + if (!strncmp(col, "x", 1)) + { + if (strlen(col+1) == 3) + { + bitval = strtoul(col+1, NULL, 16); + bitval = ((bitval & 0xf00)<<12) | ((bitval & 0x0f0)<<8) | ((bitval & 0x00f)<<4) + | ((bitval & 0xf00)<< 8) | ((bitval & 0x0f0)<<4) | ((bitval & 0x00f)<<0); + bitval |= 0x01000000; + } + else + bitval = 0x01000000 | strtoul(col+1, NULL, 16); if (bitval == ~0) bitval = 0x01ffffff; return bitval; @@ -1801,6 +1823,81 @@ static unsigned int TP_ForceColour(char *col) return atoi(col); } +colourised_t *TP_FindColours(char *name) +{ + colourised_t *col; + for (col = cls.colourised; col; col = col->next) + { + if (!strncmp(col->name, name, sizeof(col->name)-1)) + { + return col; + } + } + return NULL; +} + +static void TP_Colourise_f (void) +{ + int i; + unsigned char *topstr, *botstr; + colourised_t *col, *last; + if (Cmd_Argc() == 1) + { + return; + } + + col = TP_FindColours(Cmd_Argv(1)); + + if (Cmd_Argc() == 2) + { + if (col) + { + if (col == cls.colourised) + cls.colourised = col->next; + else + { + for (last = cls.colourised; last; last = last->next) + { + if (last->next == col) + { + last->next = col->next; + break; + } + } + } + Z_Free(col); + } + } + else + { + if (!col) + { + col = Z_Malloc(sizeof(*col)); + col->next = cls.colourised; + cls.colourised = col; + Q_strncpyz(col->name, Cmd_Argv(1), sizeof(col->skin)); + } + + topstr = Cmd_Argv(2); + botstr = strchr(topstr, '.'); + if (botstr) + *botstr++ = '\0'; + else + botstr = topstr; + + col->topcolour = TP_ForceColour(topstr); + col->bottomcolour = TP_ForceColour(botstr); + Q_strncpyz(col->skin, Cmd_Argv(3), sizeof(col->skin)); + } + + Skin_FlushPlayers(); + for (i = 0; i < MAX_CLIENTS; i++) + { + cl.players[i].colourised = TP_FindColours(cl.players[i].name); + CL_NewTranslation(i); + } +} + static void TP_TeamColor_f (void) { unsigned int top, bottom; @@ -3170,6 +3267,10 @@ void TP_Init (void) Cmd_AddCommand ("tp_pickup", TP_Pickup_f); Cmd_AddCommand ("tp_point", TP_Point_f); + Cmd_AddCommand ("colourise", TP_Colourise_f); //uk + Cmd_AddCommand ("colorize", TP_Colourise_f); //us + //Cmd_AddCommand ("colorise", TP_Colourise_f); //piss off both. + TP_InitMacros(); }