diff --git a/src/am_map.cpp b/src/am_map.cpp index 8f6871f99..28739c856 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -1850,7 +1850,7 @@ void AM_drawPlayers () { float h, s, v, r, g, b; - D_GetPlayerColor (i, &h, &s, &v); + D_GetPlayerColor (i, &h, &s, &v, NULL); HSVtoRGB (&r, &g, &b, h, s, v); color.FromRGB(clamp (int(r*255.f),0,255), clamp (int(g*255.f),0,255), clamp (int(b*255.f),0,255)); diff --git a/src/d_netinf.h b/src/d_netinf.h index c2d49630c..728bad327 100644 --- a/src/d_netinf.h +++ b/src/d_netinf.h @@ -54,7 +54,8 @@ void D_DoServerInfoChange (BYTE **stream, bool singlebit); void D_WriteUserInfoStrings (int player, BYTE **stream, bool compact=false); void D_ReadUserInfoStrings (int player, BYTE **stream, bool update); -void D_GetPlayerColor (int player, float *h, float *s, float *v); +struct FPlayerColorSet; +void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet **colorset); void D_PickRandomTeam (int player); int D_PickRandomTeam (); class player_t; diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index e31354a6e..c415ebe4a 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -65,6 +65,7 @@ EXTERN_CVAR (Bool, teamplay) CVAR (Float, autoaim, 5000.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Color, color, 0x40cf00, CVAR_USERINFO | CVAR_ARCHIVE); +CVAR (Int, colorset, 0, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, skin, "base", CVAR_USERINFO | CVAR_ARCHIVE); CVAR (Int, team, TEAM_NONE, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, gender, "male", CVAR_USERINFO | CVAR_ARCHIVE); @@ -85,6 +86,7 @@ enum INFO_MoveBob, INFO_StillBob, INFO_PlayerClass, + INFO_ColorSet, }; const char *GenderNames[3] = { "male", "female", "other" }; @@ -101,6 +103,7 @@ static const char *UserInfoStrings[] = "movebob", "stillbob", "playerclass", + "colorset", NULL }; @@ -184,10 +187,24 @@ int D_PlayerClassToInt (const char *classname) } } -void D_GetPlayerColor (int player, float *h, float *s, float *v) +void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet **set) { userinfo_t *info = &players[player].userinfo; - int color = info->color; + FPlayerColorSet *colorset = NULL; + int color; + + if (players[player].mo != NULL) + { + colorset = P_GetPlayerColorSet(players[player].mo->GetClass()->TypeName, info->colorset); + } + if (colorset != NULL) + { + color = GPalette.BaseColors[GPalette.Remap[colorset->RepresentativeColor]]; + } + else + { + color = info->color; + } RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, h, s, v); @@ -206,6 +223,10 @@ void D_GetPlayerColor (int player, float *h, float *s, float *v) *s = clamp(ts + *s * 0.15f - 0.075f, 0.f, 1.f); *v = clamp(tv + *v * 0.5f - 0.25f, 0.f, 1.f); } + if (set != NULL) + { + *set = colorset; + } } // Find out which teams are present. If there is only one, @@ -379,6 +400,7 @@ void D_SetupUserInfo () coninfo->aimdist = abs ((int)(autoaim * (float)ANGLE_1)); } coninfo->color = color; + coninfo->colorset = colorset; coninfo->skin = R_FindSkin (skin, 0); coninfo->gender = D_GenderToInt (gender); coninfo->neverswitch = neverswitchonpickup; @@ -564,6 +586,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact) "\\name\\%s" "\\autoaim\\%g" "\\color\\%x %x %x" + "\\colorset\\%d" "\\skin\\%s" "\\team\\%d" "\\gender\\%s" @@ -574,6 +597,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact) , D_EscapeUserInfo(info->netname).GetChars(), (double)info->aimdist / (float)ANGLE_1, + info->colorset, RPART(info->color), GPART(info->color), BPART(info->color), D_EscapeUserInfo(skins[info->skin].name).GetChars(), info->team, @@ -600,6 +624,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact) "\\%g" // movebob "\\%g" // stillbob "\\%s" // playerclass + "\\%d" // colorset , D_EscapeUserInfo(info->netname).GetChars(), (double)info->aimdist / (float)ANGLE_1, @@ -612,7 +637,8 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact) (float)(info->MoveBob) / 65536.f, (float)(info->StillBob) / 65536.f, info->PlayerClass == -1 ? "Random" : - D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars() + D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars(), + info->colorset ); } } @@ -716,7 +742,15 @@ void D_ReadUserInfoStrings (int i, BYTE **stream, bool update) break; case INFO_Color: - info->color = V_GetColorFromString (NULL, value); + case INFO_ColorSet: + if (infotype == INFO_Color) + { + info->color = V_GetColorFromString (NULL, value); + } + else + { + info->colorset = atoi(value); + } R_BuildPlayerTranslation (i); if (StatusBar != NULL && i == StatusBar->GetPlayer()) { @@ -806,6 +840,10 @@ FArchive &operator<< (FArchive &arc, userinfo_t &info) arc.Read (&info.netname, sizeof(info.netname)); } arc << info.team << info.aimdist << info.color << info.skin << info.gender << info.neverswitch; + if (SaveVersion >= 2193) + { + arc << info.colorset; + } return arc; } @@ -831,6 +869,7 @@ CCMD (playerinfo) Printf ("Team: %s (%d)\n", ui->team == TEAM_NONE ? "None" : Teams[ui->team].GetName (), ui->team); Printf ("Aimdist: %d\n", ui->aimdist); Printf ("Color: %06x\n", ui->color); + Printf ("ColorSet: %d\n", ui->colorset); Printf ("Skin: %s (%d)\n", skins[ui->skin].name, ui->skin); Printf ("Gender: %s (%d)\n", GenderNames[ui->gender], ui->gender); Printf ("NeverSwitch: %d\n", ui->neverswitch); diff --git a/src/d_player.h b/src/d_player.h index 3c9ad954c..64d901329 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -71,6 +71,21 @@ enum APMETA_Slot9, }; +// Standard pre-defined skin colors +struct FPlayerColorSet +{ + FName Name; // Name of this color + + int Lump; // Lump to read the translation from, otherwise use next 2 fields + BYTE FirstColor, LastColor; // Describes the range of colors to use for the translation + + BYTE RepresentativeColor; // A palette entry representative of this translation, + // for map arrows and status bar backgrounds and such +}; +void P_AddPlayerColorSet(FName classname, int setnum, const FPlayerColorSet *colorset); +FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum); +void P_EnumPlayerColorSets(FName classname, TArray *out); + class player_t; class APlayerPawn : public AActor @@ -223,6 +238,7 @@ struct userinfo_t BYTE team; int aimdist; int color; + int colorset; int skin; int gender; bool neverswitch; diff --git a/src/hu_scores.cpp b/src/hu_scores.cpp index 456652bc7..1d881bd3d 100644 --- a/src/hu_scores.cpp +++ b/src/hu_scores.cpp @@ -418,7 +418,7 @@ void HU_DrawColorBar(int x, int y, int height, int playernum) { float h, s, v, r, g, b; - D_GetPlayerColor (playernum, &h, &s, &v); + D_GetPlayerColor (playernum, &h, &s, &v, NULL); HSVtoRGB (&r, &g, &b, h, s, v); screen->Clear (x, y, x + 24*CleanXfac, y + height, -1, diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 88eac1edf..7628b336e 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -118,7 +118,7 @@ protected: // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- -void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table); +void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayerSkin *skin, FRemapTable *table); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -188,6 +188,7 @@ static void M_EditPlayerName (int choice); static void M_ChangePlayerTeam (int choice); static void M_PlayerNameChanged (FSaveGameNode *dummy); static void M_PlayerNameNotChanged (); +static void M_ChangeColorSet (int choice); static void M_SlidePlayerRed (int choice); static void M_SlidePlayerGreen (int choice); static void M_SlidePlayerBlue (int choice); @@ -269,6 +270,7 @@ static int PlayerSkin; static FState *PlayerState; static int PlayerTics; static int PlayerRotation; +static TArray PlayerColorSets; static FTexture *SavePic; static FBrokenLines *SaveComment; @@ -536,10 +538,11 @@ static oldmenuitem_t PlayerSetupMenu[] = { { 1,0,'n',NULL,M_EditPlayerName, CR_UNTRANSLATED}, { 2,0,'t',NULL,M_ChangePlayerTeam, CR_UNTRANSLATED}, + { 2,0,'c',NULL,M_ChangeColorSet, CR_UNTRANSLATED}, { 2,0,'r',NULL,M_SlidePlayerRed, CR_UNTRANSLATED}, { 2,0,'g',NULL,M_SlidePlayerGreen, CR_UNTRANSLATED}, { 2,0,'b',NULL,M_SlidePlayerBlue, CR_UNTRANSLATED}, - { 2,0,'c',NULL,M_ChangeClass, CR_UNTRANSLATED}, + { 2,0,'t',NULL,M_ChangeClass, CR_UNTRANSLATED}, { 2,0,'s',NULL,M_ChangeSkin, CR_UNTRANSLATED}, { 2,0,'e',NULL,M_ChangeGender, CR_UNTRANSLATED}, { 2,0,'a',NULL,M_ChangeAutoAim, CR_UNTRANSLATED} @@ -2088,13 +2091,16 @@ void M_PlayerSetup (void) PlayerClass = &PlayerClasses[players[consoleplayer].CurrentPlayerClass]; } PlayerSkin = players[consoleplayer].userinfo.skin; - R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); + R_GetPlayerTranslation (players[consoleplayer].userinfo.color, + P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset), + &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); PlayerState = GetDefaultByType (PlayerClass->Type)->SeeState; PlayerTics = PlayerState->GetTics(); if (FireTexture == NULL) { FireTexture = new FBackdropTexture; } + P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets); } static void M_PlayerSetupTicker (void) @@ -2112,6 +2118,7 @@ static void M_PlayerSetupTicker (void) item = (MenuTime>>2) % (ClassMenuDef.numitems-1); PlayerClass = &PlayerClasses[D_PlayerClassToInt (ClassMenuItems[item].name)]; + P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets); } else { @@ -2125,6 +2132,7 @@ static void M_PlayerSetupTicker (void) PlayerSkin = R_FindSkin (skins[PlayerSkin].name, int(PlayerClass - &PlayerClasses[0])); R_GetPlayerTranslation (players[consoleplayer].userinfo.color, + P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset), &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); } @@ -2280,19 +2288,27 @@ static void M_PlayerSetupDrawer () DTA_Clean, true, TAG_DONE); } - // Draw player color sliders - //V_DrawTextCleanMove (CR_GREY, PSetupDef.x, PSetupDef.y + LINEHEIGHT, "Color"); + // Draw player color selection and sliders + FPlayerColorSet *colorset = P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset); + x = SmallFont->StringWidth("Color") + 8 + PSetupDef.x; + screen->DrawText(SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*2+yo, "Color", DTA_Clean, true, TAG_DONE); + screen->DrawText(SmallFont, value, x, PSetupDef.y + LINEHEIGHT*2+yo, + colorset != NULL ? colorset->Name.GetChars() : "Custom", DTA_Clean, true, TAG_DONE); - screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*2+yo, "Red", DTA_Clean, true, TAG_DONE); - screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*3+yo, "Green", DTA_Clean, true, TAG_DONE); - screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*4+yo, "Blue", DTA_Clean, true, TAG_DONE); + // Only show the sliders for a custom color set. + if (colorset == NULL) + { + screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*2.875)+yo, "Red", DTA_Clean, true, TAG_DONE); + screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*3.5)+yo, "Green", DTA_Clean, true, TAG_DONE); + screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + int(LINEHEIGHT*4.125)+yo, "Blue", DTA_Clean, true, TAG_DONE); - x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x; - color = players[consoleplayer].userinfo.color; + x = SmallFont->StringWidth ("Green") + 8 + PSetupDef.x; + color = players[consoleplayer].userinfo.color; - M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*2+yo, RPART(color)); - M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*3+yo, GPART(color)); - M_DrawPlayerSlider (x, PSetupDef.y + LINEHEIGHT*4+yo, BPART(color)); + M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*2.875)+yo, RPART(color)); + M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*3.5)+yo, GPART(color)); + M_DrawPlayerSlider (x, PSetupDef.y + int(LINEHEIGHT*4.125)+yo, BPART(color)); + } // [GRB] Draw class setting int pclass = players[consoleplayer].userinfo.PlayerClass; @@ -2587,7 +2603,9 @@ static void M_ChangeSkin (int choice) PlayerSkin = (PlayerSkin < (int)numskins - 1) ? PlayerSkin + 1 : 0; } while (!PlayerClass->CheckSkin (PlayerSkin)); - R_GetPlayerTranslation (players[consoleplayer].userinfo.color, &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); + R_GetPlayerTranslation (players[consoleplayer].userinfo.color, + P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset), + &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); cvar_set ("skin", skins[PlayerSkin].name); } @@ -2708,13 +2726,50 @@ static void M_ChangePlayerTeam (int choice) } } +static void M_ChangeColorSet (int choice) +{ + int curpos = (int)PlayerColorSets.Size(); + int mycolorset = players[consoleplayer].userinfo.colorset; + while (--curpos >= 0) + { + if (PlayerColorSets[curpos] == mycolorset) + break; + } + if (choice == 0) + { + curpos--; + } + else + { + curpos++; + } + if (curpos < -1) + { + curpos = (int)PlayerColorSets.Size() - 1; + } + else if (curpos >= (int)PlayerColorSets.Size()) + { + curpos = -1; + } + mycolorset = (curpos >= 0) ? PlayerColorSets[curpos] : -1; + + char command[24]; + mysnprintf(command, countof(command), "colorset %d", mycolorset); + C_DoCommand(command); + R_GetPlayerTranslation(players[consoleplayer].userinfo.color, + P_GetPlayerColorSet(PlayerClass->Type->TypeName, mycolorset), + &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); +} + static void SendNewColor (int red, int green, int blue) { char command[24]; mysnprintf (command, countof(command), "color \"%02x %02x %02x\"", red, green, blue); C_DoCommand (command); - R_GetPlayerTranslation (MAKERGB (red, green, blue), &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); + R_GetPlayerTranslation(MAKERGB (red, green, blue), + P_GetPlayerColorSet(PlayerClass->Type->TypeName, players[consoleplayer].userinfo.colorset), + &skins[PlayerSkin], translationtables[TRANSLATION_Players][MAXPLAYERS]); } static void M_SlidePlayerRed (int choice) @@ -3646,8 +3701,31 @@ void M_Drawer () // [RH] Use options menu cursor for the player setup menu. if (skullAnimCounter < 6) { + double item; + // The green slider is halfway between lines, and the red and + // blue ones are offset slightly to make room for it. + if (itemOn < 3) + { + item = itemOn; + } + else if (itemOn > 5) + { + item = itemOn - 1; + } + else if (itemOn == 3) + { + item = 2.875; + } + else if (itemOn == 4) + { + item = 3.5; + } + else + { + item = 4.125; + } screen->DrawText (ConFont, CR_RED, x - 16, - currentMenu->y + itemOn*PLAYERSETUP_LINEHEIGHT + + currentMenu->y + int(item*PLAYERSETUP_LINEHEIGHT) + (!(gameinfo.gametype & (GAME_DoomStrifeChex)) ? 6 : -1), "\xd", DTA_Clean, true, TAG_DONE); } @@ -4037,4 +4115,5 @@ static void PickPlayerClass () } PlayerClass = &PlayerClasses[pclass]; + P_EnumPlayerColorSets(PlayerClass->Type->TypeName, &PlayerColorSets); } diff --git a/src/p_user.cpp b/src/p_user.cpp index ff1a80dae..78e6eeb2e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -55,6 +55,9 @@ static FRandom pr_skullpop ("SkullPop"); +// Color set class name -> mapping table +typedef TMap FPlayerColorSetMap; +TMap PlayerToColorsMap; // [RH] # of ticks to complete a turn180 #define TURN180_TICKS ((TICRATE / 4) + 1) @@ -2631,3 +2634,66 @@ void player_t::Serialize (FArchive &arc) } } + +static FPlayerColorSetMap *GetPlayerColors(FName classname, bool create) +{ + FPlayerColorSetMap *map, **value; + + value = PlayerToColorsMap.CheckKey(classname); + if (value == NULL) + { + if (create) + { + map = new FPlayerColorSetMap; + PlayerToColorsMap.Insert(classname, map); + } + else + { + map = NULL; + } + } + else + { + map = *value; + } + return map; +} + +void P_AddPlayerColorSet(FName classname, int setnum, const FPlayerColorSet *colorset) +{ + FPlayerColorSetMap *map = GetPlayerColors(classname, true); + (*map)[setnum] = *colorset; +} + +FPlayerColorSet *P_GetPlayerColorSet(FName classname, int setnum) +{ + FPlayerColorSetMap *map = GetPlayerColors(classname, false); + if (map == NULL) + { + return NULL; + } + return map->CheckKey(setnum); +} + +static int STACK_ARGS intcmp(const void *a, const void *b) +{ + return *(const int *)a - *(const int *)b; +} + +void P_EnumPlayerColorSets(FName classname, TArray *out) +{ + out->Clear(); + FPlayerColorSetMap *map = GetPlayerColors(classname, false); + if (map != NULL) + { + FPlayerColorSetMap::Iterator it(*map); + FPlayerColorSetMap::Pair *pair; + + while (it.NextPair(pair)) + { + out->Push(pair->Key); + } + qsort(&(*out)[0], out->Size(), sizeof(int), intcmp); + } +} + diff --git a/src/r_translate.cpp b/src/r_translate.cpp index 8e74f4443..553d4fcf1 100644 --- a/src/r_translate.cpp +++ b/src/r_translate.cpp @@ -46,6 +46,7 @@ #include "sc_man.h" #include "doomerrors.h" #include "i_system.h" +#include "w_wad.h" #include "gi.h" #include "stats.h" @@ -892,7 +893,8 @@ static void SetRemap(FRemapTable *table, int i, float r, float g, float b) // //---------------------------------------------------------------------------- -static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable) +static void R_CreatePlayerTranslation (float h, float s, float v, const FPlayerColorSet *colorset, + FPlayerSkin *skin, FRemapTable *table, FRemapTable *alttable) { int i; BYTE start = skin->range0start; @@ -936,7 +938,46 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s bases = s; basev = v; - if (gameinfo.gametype & GAME_DoomStrifeChex) + if (colorset != NULL && colorset->Lump >= 0 && Wads.LumpLength(colorset->Lump) < 256) + { // Bad table length. Ignore it. + colorset = NULL; + } + + if (colorset != NULL) + { + // Use the pre-defined range instead of a custom one. + if (colorset->Lump < 0) + { + int first = colorset->FirstColor; + if (start == end) + { + table->Remap[i] = (first + colorset->LastColor) / 2; + } + else + { + int palrange = colorset->LastColor - first; + for (i = start; i <= end; ++i) + { + table->Remap[i] = GPalette.Remap[first + palrange * (i - start) / (end - start)]; + } + } + } + else + { + FMemLump translump = Wads.ReadLump(colorset->Lump); + const BYTE *trans = (const BYTE *)translump.GetMem(); + for (i = start; i <= end; ++i) + { + table->Remap[i] = GPalette.Remap[trans[i]]; + } + } + for (i = start; i <= end; ++i) + { + table->Palette[i] = GPalette.BaseColors[table->Remap[i]]; + table->Palette[i].a = 255; + } + } + else if (gameinfo.gametype & GAME_DoomStrifeChex) { // Build player sprite translation s -= 0.23f; @@ -1014,9 +1055,19 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s SetRemap(table, i, r, g, b); } } - - // Build lifegem translation - if (alttable) + } + if (gameinfo.gametype == GAME_Hexen && alttable != NULL) + { + // Build Hexen's lifegem translation. + + // Is the player's translation range the same as the gem's and we are using a + // predefined translation? If so, then use the same one for the gem. Otherwise, + // build one as per usual. + if (colorset != NULL && start == 164 && end == 185) + { + *alttable = *table; + } + else { for (i = 164; i <= 185; ++i) { @@ -1027,8 +1078,8 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s HSVtoRGB (&r, &g, &b, h, s*bases, v*basev); SetRemap(alttable, i, r, g, b); } - alttable->UpdateNative(); } + alttable->UpdateNative(); } table->UpdateNative(); } @@ -1042,10 +1093,11 @@ static void R_CreatePlayerTranslation (float h, float s, float v, FPlayerSkin *s void R_BuildPlayerTranslation (int player) { float h, s, v; + FPlayerColorSet *colorset; - D_GetPlayerColor (player, &h, &s, &v); + D_GetPlayerColor (player, &h, &s, &v, &colorset); - R_CreatePlayerTranslation (h, s, v, + R_CreatePlayerTranslation (h, s, v, colorset, &skins[players[player].userinfo.skin], translationtables[TRANSLATION_Players][player], translationtables[TRANSLATION_PlayersExtra][player]); @@ -1057,13 +1109,17 @@ void R_BuildPlayerTranslation (int player) // //---------------------------------------------------------------------------- -void R_GetPlayerTranslation (int color, FPlayerSkin *skin, FRemapTable *table) +void R_GetPlayerTranslation (int color, const FPlayerColorSet *colorset, FPlayerSkin *skin, FRemapTable *table) { float h, s, v; + if (colorset != NULL) + { + color = colorset->RepresentativeColor; + } RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, &h, &s, &v); - R_CreatePlayerTranslation (h, s, v, skin, table, NULL); + R_CreatePlayerTranslation (h, s, v, colorset, skin, table, NULL); } diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 884e596e2..5a8bfe0f5 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1860,6 +1860,57 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorrange, I_I, PlayerPawn) info->Class->Meta.SetMetaInt (APMETA_ColorRange, (start & 255) | ((end & 255) << 8)); } +//========================================================================== +// +//========================================================================== +DEFINE_CLASS_PROPERTY_PREFIX(player, colorset, ISIII, PlayerPawn) +{ + PROP_INT_PARM(setnum, 0); + PROP_STRING_PARM(setname, 1); + PROP_INT_PARM(rangestart, 2); + PROP_INT_PARM(rangeend, 3); + PROP_INT_PARM(representative_color, 4); + + FPlayerColorSet color; + color.Name = setname; + color.Lump = -1; + color.FirstColor = rangestart; + color.LastColor = rangeend; + color.RepresentativeColor = representative_color; + + if (setnum < 0) + { + bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n"); + } + else + { + P_AddPlayerColorSet(info->Class->TypeName, setnum, &color); + } +} + +//========================================================================== +// +//========================================================================== +DEFINE_CLASS_PROPERTY_PREFIX(player, colorsetfile, ISSI, PlayerPawn) +{ + PROP_INT_PARM(setnum, 0); + PROP_STRING_PARM(setname, 1); + PROP_STRING_PARM(rangefile, 2); + PROP_INT_PARM(representative_color, 3); + + FPlayerColorSet color; + color.Name = setname; + color.Lump = Wads.CheckNumForName(rangefile); + color.RepresentativeColor = representative_color; + if (setnum < 0) + { + bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n"); + } + else if (color.Lump >= 0) + { + P_AddPlayerColorSet(info->Class->TypeName, setnum, &color); + } +} //========================================================================== // //========================================================================== diff --git a/wadsrc/static/actors/doom/doomplayer.txt b/wadsrc/static/actors/doom/doomplayer.txt index 9138fc649..3f81eaaca 100644 --- a/wadsrc/static/actors/doom/doomplayer.txt +++ b/wadsrc/static/actors/doom/doomplayer.txt @@ -11,7 +11,6 @@ ACTOR DoomPlayer : PlayerPawn Height 56 Mass 100 PainChance 255 - Player.ColorRange 112, 127 Player.DisplayName "Marine" Player.CrouchSprite "PLYC" Player.StartItem "Pistol" @@ -24,6 +23,17 @@ ACTOR DoomPlayer : PlayerPawn Player.WeaponSlot 5, RocketLauncher Player.WeaponSlot 6, PlasmaRifle Player.WeaponSlot 7, BFG9000 + + Player.ColorRange 112, 127 + Player.Colorset 0, "Green", 0x70, 0x7F, 0x72 + Player.Colorset 1, "Gray", 0x60, 0x6F, 0x62 + Player.Colorset 2, "Brown", 0x40, 0x4F, 0x42 + Player.Colorset 3, "Red", 0x20, 0x2F, 0x22 + // Doom Legacy additions + Player.Colorset 4, "Light Gray", 0x58, 0x67, 0x5A + Player.Colorset 5, "Light Brown", 0x38, 0x47, 0x3A + Player.Colorset 6, "Light Red", 0xB0, 0xBF, 0xB2 + Player.Colorset 7, "Light Blue", 0xC0, 0xCF, 0xC2 States { diff --git a/wadsrc/static/actors/heretic/hereticplayer.txt b/wadsrc/static/actors/heretic/hereticplayer.txt index 9e36f8d7f..77ec994d8 100644 --- a/wadsrc/static/actors/heretic/hereticplayer.txt +++ b/wadsrc/static/actors/heretic/hereticplayer.txt @@ -6,7 +6,6 @@ ACTOR HereticPlayer : PlayerPawn Mass 100 Painchance 255 Speed 1 - Player.ColorRange 225, 240 Player.DisplayName "Corvus" Player.StartItem "GoldWand" Player.StartItem "Staff" @@ -18,7 +17,20 @@ ACTOR HereticPlayer : PlayerPawn Player.WeaponSlot 5, SkullRod Player.WeaponSlot 6, PhoenixRod Player.WeaponSlot 7, Mace - + + Player.ColorRange 225, 240 + Player.Colorset 0, "Green", 225, 240, 238 + Player.Colorset 1, "Yellow", 114, 129, 127 + Player.Colorset 2, "Red", 145, 160, 158 + Player.Colorset 3, "Blue", 190, 205, 203 + // Doom Legacy additions + Player.Colorset 4, "Brown", 67, 82, 80 + Player.Colorset 5, "Light Gray", 9, 24, 22 + Player.Colorset 6, "Light Brown", 74, 89, 87 + Player.Colorset 7, "Light Red", 150, 165, 163 + Player.Colorset 8, "Light Blue", 192, 207, 205 + Player.Colorset 9, "Beige", 95, 110, 108 + States { Spawn: diff --git a/wadsrc/static/actors/hexen/clericplayer.txt b/wadsrc/static/actors/hexen/clericplayer.txt index 493faffde..4fe6629e2 100644 --- a/wadsrc/static/actors/hexen/clericplayer.txt +++ b/wadsrc/static/actors/hexen/clericplayer.txt @@ -15,7 +15,6 @@ ACTOR ClericPlayer : PlayerPawn RadiusDamageFactor 0.25 Player.JumpZ 9 Player.Viewheight 48 - Player.ColorRange 146, 163 Player.SpawnClass "Cleric" Player.DisplayName "Cleric" Player.SoundClass "cleric" @@ -29,6 +28,16 @@ ACTOR ClericPlayer : PlayerPawn Player.WeaponSlot 3, CWeapFlame Player.WeaponSlot 4, CWeapWraithverge + Player.ColorRange 146, 163 + Player.Colorset 0, "Blue", 146, 163, 161 + Player.ColorsetFile 1, "Red", "TRANTBL7", 0xB3 + Player.ColorsetFile 2, "Gold", "TRANTBL8", 0x8C + Player.ColorsetFile 3, "Dull Green", "TRANTBL9", 0x41 + Player.ColorsetFile 4, "Green", "TRANTBLA", 0xC9 + Player.ColorsetFile 5, "Gray", "TRANTBLB", 0x30 + Player.ColorsetFile 6, "Brown", "TRANTBLC", 0x72 + Player.ColorsetFile 7, "Purple", "TRANTBLD", 0xEE + States { Spawn: diff --git a/wadsrc/static/actors/hexen/fighterplayer.txt b/wadsrc/static/actors/hexen/fighterplayer.txt index 5c307bd60..277a2986b 100644 --- a/wadsrc/static/actors/hexen/fighterplayer.txt +++ b/wadsrc/static/actors/hexen/fighterplayer.txt @@ -14,7 +14,6 @@ ACTOR FighterPlayer : PlayerPawn RadiusDamageFactor 0.25 Player.JumpZ 9 Player.Viewheight 48 - Player.ColorRange 246, 254 Player.SpawnClass "Fighter" Player.DisplayName "Fighter" Player.SoundClass "fighter" @@ -29,6 +28,16 @@ ACTOR FighterPlayer : PlayerPawn Player.WeaponSlot 3, FWeapHammer Player.WeaponSlot 4, FWeapQuietus + Player.ColorRange 246, 254 + Player.Colorset 0, "Gold", 246, 254, 253 + Player.ColorsetFile 1, "Red", "TRANTBL0", 0xAC + Player.ColorsetFile 2, "Blue", "TRANTBL1", 0x9D + Player.ColorsetFile 3, "Dull Green", "TRANTBL2", 0x3E + Player.ColorsetFile 4, "Green", "TRANTBL3", 0xC8 + Player.ColorsetFile 5, "Gray", "TRANTBL4", 0x2D + Player.ColorsetFile 6, "Brown", "TRANTBL5", 0x6F + Player.ColorsetFile 7, "Purple", "TRANTBL6", 0xEE + States { Spawn: diff --git a/wadsrc/static/actors/hexen/mageplayer.txt b/wadsrc/static/actors/hexen/mageplayer.txt index 2f67d35bf..a34698366 100644 --- a/wadsrc/static/actors/hexen/mageplayer.txt +++ b/wadsrc/static/actors/hexen/mageplayer.txt @@ -15,7 +15,6 @@ ACTOR MagePlayer : PlayerPawn RadiusDamageFactor 0.25 Player.JumpZ 9 Player.Viewheight 48 - Player.ColorRange 146, 163 Player.SpawnClass "Mage" Player.DisplayName "Mage" Player.SoundClass "mage" @@ -31,6 +30,16 @@ ACTOR MagePlayer : PlayerPawn Player.WeaponSlot 3, MWeapLightning Player.WeaponSlot 4, MWeapBloodscourge + Player.ColorRange 146, 163 + Player.Colorset 0, "Blue", 146, 163, 161 + Player.ColorsetFile 1, "Red", "TRANTBL7", 0xB3 + Player.ColorsetFile 2, "Gold", "TRANTBL8", 0x8C + Player.ColorsetFile 3, "Dull Green", "TRANTBL9", 0x41 + Player.ColorsetFile 4, "Green", "TRANTBLA", 0xC9 + Player.ColorsetFile 5, "Gray", "TRANTBLB", 0x30 + Player.ColorsetFile 6, "Brown", "TRANTBLC", 0x72 + Player.ColorsetFile 7, "Purple", "TRANTBLD", 0xEE + States { Spawn: diff --git a/wadsrc/static/actors/strife/strifeplayer.txt b/wadsrc/static/actors/strife/strifeplayer.txt index d42dc1ba4..1dabeff4c 100644 --- a/wadsrc/static/actors/strife/strifeplayer.txt +++ b/wadsrc/static/actors/strife/strifeplayer.txt @@ -9,7 +9,6 @@ ACTOR StrifePlayer : PlayerPawn PainChance 255 Speed 1 MaxStepHeight 16 - Player.ColorRange 128, 143 Player.DisplayName "Rebel" Player.StartItem "PunchDagger" Player.RunHealth 15 @@ -22,6 +21,16 @@ ACTOR StrifePlayer : PlayerPawn Player.WeaponSlot 7, Mauler2, Mauler Player.WeaponSlot 8, Sigil + Player.ColorRange 128, 143 + Player.Colorset 0, "Brown", 0x80, 0x8F, 0x82 + Player.Colorset 1, "Red", 0x40, 0x4F, 0x42 + Player.Colorset 2, "Rust", 0xB0, 0xBF, 0xB2 + Player.Colorset 3, "Gray", 0x10, 0x1F, 0x12 + Player.Colorset 4, "Dark Green", 0x30, 0x3F, 0x32 + Player.Colorset 5, "Gold", 0x50, 0x5F, 0x52 + Player.Colorset 6, "Bright Green", 0x60, 0x6F, 0x62 + Player.Colorset 7, "Blue", 0x90, 0x9F, 0x92 + action native A_ItBurnsItBurns(); action native A_CrispyPlayer(); action native A_HandLower();