1#include <base/color.h>
2#include <base/system.h>
3#include <game/generated/protocol7.h>
4
5#include "teeinfo.h"
6
7struct StdSkin
8{
9 char m_aSkinName[24];
10 // body, marking, decoration, hands, feet, eyes
11 char m_apSkinPartNames[protocol7::NUM_SKINPARTS][24];
12 bool m_aUseCustomColors[protocol7::NUM_SKINPARTS];
13 int m_aSkinPartColors[protocol7::NUM_SKINPARTS];
14};
15
16static StdSkin g_aStdSkins[] = {
17 {.m_aSkinName: "default", .m_apSkinPartNames: {"standard", "", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, false, false, true, true, false}, .m_aSkinPartColors: {1798004, 0, 0, 1799582, 1869630, 0}},
18 {.m_aSkinName: "bluekitty", .m_apSkinPartNames: {"kitty", "whisker", "", "standard", "standard", "negative"}, .m_aUseCustomColors: {true, true, false, true, true, true}, .m_aSkinPartColors: {8681144, -8229413, 0, 7885547, 8868585, 9043712}},
19 {.m_aSkinName: "bluestripe", .m_apSkinPartNames: {"standard", "stripes", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, false, false, true, true, false}, .m_aSkinPartColors: {10187898, 0, 0, 750848, 1944919, 0}},
20 {.m_aSkinName: "brownbear", .m_apSkinPartNames: {"bear", "bear", "hair", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, false, true, true, false}, .m_aSkinPartColors: {1082745, -15634776, 0, 1082745, 1147174, 0}},
21 {.m_aSkinName: "cammo", .m_apSkinPartNames: {"standard", "cammo2", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, false, true, true, false}, .m_aSkinPartColors: {5334342, -11771603, 0, 750848, 1944919, 0}},
22 {.m_aSkinName: "cammostripes", .m_apSkinPartNames: {"standard", "cammostripes", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, false, true, true, false}, .m_aSkinPartColors: {5334342, -14840320, 0, 750848, 1944919, 0}},
23 {.m_aSkinName: "coala", .m_apSkinPartNames: {"koala", "twinbelly", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, false, true, true, false}, .m_aSkinPartColors: {184, -15397662, 0, 184, 9765959, 0}},
24 {.m_aSkinName: "limekitty", .m_apSkinPartNames: {"kitty", "whisker", "", "standard", "standard", "negative"}, .m_aUseCustomColors: {true, true, false, true, true, true}, .m_aSkinPartColors: {4612803, -12229920, 0, 3827951, 3827951, 8256000}},
25 {.m_aSkinName: "pinky", .m_apSkinPartNames: {"standard", "whisker", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, false, true, true, false}, .m_aSkinPartColors: {15911355, -801066, 0, 15043034, 15043034, 0}},
26 {.m_aSkinName: "redbopp", .m_apSkinPartNames: {"standard", "donny", "unibop", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, true, true, true, false}, .m_aSkinPartColors: {16177260, -16590390, 16177260, 16177260, 7624169, 0}},
27 {.m_aSkinName: "redstripe", .m_apSkinPartNames: {"standard", "stripe", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, false, false, true, true, false}, .m_aSkinPartColors: {16307835, 0, 0, 184, 9765959, 0}},
28 {.m_aSkinName: "saddo", .m_apSkinPartNames: {"standard", "saddo", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, false, true, true, false}, .m_aSkinPartColors: {7171455, -9685436, 0, 3640746, 5792119, 0}},
29 {.m_aSkinName: "toptri", .m_apSkinPartNames: {"standard", "toptri", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, false, false, true, true, false}, .m_aSkinPartColors: {6119331, 0, 0, 3640746, 5792119, 0}},
30 {.m_aSkinName: "twinbop", .m_apSkinPartNames: {"standard", "duodonny", "twinbopp", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, true, true, true, false}, .m_aSkinPartColors: {15310519, -1600806, 15310519, 15310519, 37600, 0}},
31 {.m_aSkinName: "twintri", .m_apSkinPartNames: {"standard", "twintri", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, true, false, true, true, false}, .m_aSkinPartColors: {3447932, -14098717, 0, 185, 9634888, 0}},
32 {.m_aSkinName: "warpaint", .m_apSkinPartNames: {"standard", "warpaint", "", "standard", "standard", "standard"}, .m_aUseCustomColors: {true, false, false, true, true, false}, .m_aSkinPartColors: {1944919, 0, 0, 750337, 1944919, 0}}};
33
34CTeeInfo::CTeeInfo(const char *pSkinName, int UseCustomColor, int ColorBody, int ColorFeet)
35{
36 str_copy(dst: m_aSkinName, src: pSkinName, dst_size: sizeof(m_aSkinName));
37 m_UseCustomColor = UseCustomColor;
38 m_ColorBody = ColorBody;
39 m_ColorFeet = ColorFeet;
40}
41
42CTeeInfo::CTeeInfo(const char *apSkinPartNames[protocol7::NUM_SKINPARTS], const int *pUseCustomColors, const int *pSkinPartColors)
43{
44 for(int i = 0; i < protocol7::NUM_SKINPARTS; i++)
45 {
46 str_copy(dst: m_apSkinPartNames[i], src: apSkinPartNames[i], dst_size: sizeof(m_apSkinPartNames[i]));
47 m_aUseCustomColors[i] = pUseCustomColors[i];
48 m_aSkinPartColors[i] = pSkinPartColors[i];
49 }
50}
51
52void CTeeInfo::ToSixup()
53{
54 // reset to default skin
55 for(int p = 0; p < protocol7::NUM_SKINPARTS; p++)
56 {
57 str_copy(dst: m_apSkinPartNames[p], src: g_aStdSkins[0].m_apSkinPartNames[p], dst_size: 24);
58 m_aUseCustomColors[p] = g_aStdSkins[0].m_aUseCustomColors[p];
59 m_aSkinPartColors[p] = g_aStdSkins[0].m_aSkinPartColors[p];
60 }
61
62 // check for std skin
63 for(auto &StdSkin : g_aStdSkins)
64 {
65 if(!str_comp(a: m_aSkinName, b: StdSkin.m_aSkinName))
66 {
67 for(int p = 0; p < protocol7::NUM_SKINPARTS; p++)
68 {
69 str_copy(dst: m_apSkinPartNames[p], src: StdSkin.m_apSkinPartNames[p], dst_size: 24);
70 m_aUseCustomColors[p] = StdSkin.m_aUseCustomColors[p];
71 m_aSkinPartColors[p] = StdSkin.m_aSkinPartColors[p];
72 }
73 break;
74 }
75 }
76
77 if(m_UseCustomColor)
78 {
79 int ColorBody = ColorHSLA(m_ColorBody).UnclampLighting().Pack(Darkest: ms_DarkestLGT7);
80 int ColorFeet = ColorHSLA(m_ColorFeet).UnclampLighting().Pack(Darkest: ms_DarkestLGT7);
81 m_aUseCustomColors[0] = true;
82 m_aUseCustomColors[1] = true;
83 m_aUseCustomColors[2] = true;
84 m_aUseCustomColors[3] = true;
85 m_aUseCustomColors[4] = true;
86 m_aSkinPartColors[0] = ColorBody;
87 m_aSkinPartColors[1] = 0x22FFFFFF;
88 m_aSkinPartColors[2] = ColorBody;
89 m_aSkinPartColors[3] = ColorBody;
90 m_aSkinPartColors[4] = ColorFeet;
91 }
92}
93
94void CTeeInfo::FromSixup()
95{
96 // reset to default skin
97 str_copy(dst: m_aSkinName, src: "default", dst_size: sizeof(m_aSkinName));
98 m_UseCustomColor = false;
99 m_ColorBody = 0;
100 m_ColorFeet = 0;
101
102 // check for std skin
103 for(auto &StdSkin : g_aStdSkins)
104 {
105 bool match = true;
106 for(int p = 0; p < protocol7::NUM_SKINPARTS; p++)
107 {
108 if(str_comp(a: m_apSkinPartNames[p], b: StdSkin.m_apSkinPartNames[p]) || m_aUseCustomColors[p] != StdSkin.m_aUseCustomColors[p] || (m_aUseCustomColors[p] && m_aSkinPartColors[p] != StdSkin.m_aSkinPartColors[p]))
109 {
110 match = false;
111 break;
112 }
113 }
114 if(match)
115 {
116 str_copy(dst: m_aSkinName, src: StdSkin.m_aSkinName, dst_size: sizeof(m_aSkinName));
117 return;
118 }
119 }
120
121 // find closest match
122 int best_skin = 0;
123 int best_matches = -1;
124 for(int s = 0; s < 16; s++)
125 {
126 int matches = 0;
127 for(int p = 0; p < 3; p++)
128 if(str_comp(a: m_apSkinPartNames[p], b: g_aStdSkins[s].m_apSkinPartNames[p]) == 0)
129 matches++;
130
131 if(matches > best_matches)
132 {
133 best_matches = matches;
134 best_skin = s;
135 }
136 }
137
138 str_copy(dst: m_aSkinName, src: g_aStdSkins[best_skin].m_aSkinName, dst_size: sizeof(m_aSkinName));
139 m_UseCustomColor = true;
140 m_ColorBody = ColorHSLA(m_aUseCustomColors[0] ? m_aSkinPartColors[0] : 255).UnclampLighting(Darkest: ms_DarkestLGT7).Pack(Darkest: ColorHSLA::DARKEST_LGT);
141 m_ColorFeet = ColorHSLA(m_aUseCustomColors[4] ? m_aSkinPartColors[4] : 255).UnclampLighting(Darkest: ms_DarkestLGT7).Pack(Darkest: ColorHSLA::DARKEST_LGT);
142}
143