| 884 | } |
| 885 | |
| 886 | void CSkins::RandomizeSkin(int Dummy) |
| 887 | { |
| 888 | static const float s_aSchemes[] = {1.0f / 2.0f, 1.0f / 3.0f, 1.0f / -3.0f, 1.0f / 12.0f, 1.0f / -12.0f}; // complementary, triadic, analogous |
| 889 | const bool UseCustomColor = Dummy ? g_Config.m_ClDummyUseCustomColor : g_Config.m_ClPlayerUseCustomColor; |
| 890 | if(UseCustomColor) |
| 891 | { |
| 892 | float GoalSat = random_float(0.3f, 1.0f); |
| 893 | float MaxBodyLht = 1.0f - GoalSat * GoalSat; // max allowed lightness before we start losing saturation |
| 894 | |
| 895 | ColorHSLA Body; |
| 896 | Body.h = random_float(); |
| 897 | Body.l = random_float(0.0f, MaxBodyLht); |
| 898 | Body.s = std::clamp(GoalSat * GoalSat / (1.0f - Body.l), 0.0f, 1.0f); |
| 899 | |
| 900 | ColorHSLA Feet; |
| 901 | Feet.h = std::fmod(Body.h + s_aSchemes[rand() % std::size(s_aSchemes)], 1.0f); |
| 902 | Feet.l = random_float(); |
| 903 | Feet.s = std::clamp(GoalSat * GoalSat / (1.0f - Feet.l), 0.0f, 1.0f); |
| 904 | |
| 905 | unsigned *pColorBody = Dummy ? &g_Config.m_ClDummyColorBody : &g_Config.m_ClPlayerColorBody; |
| 906 | unsigned *pColorFeet = Dummy ? &g_Config.m_ClDummyColorFeet : &g_Config.m_ClPlayerColorFeet; |
| 907 | |
| 908 | *pColorBody = Body.Pack(false); |
| 909 | *pColorFeet = Feet.Pack(false); |
| 910 | } |
| 911 | |
| 912 | std::vector<const CSkinContainer *> vpConsideredSkins; |
| 913 | for(const auto &[_, pSkinContainer] : m_Skins) |
| 914 | { |
| 915 | if(pSkinContainer->m_State == CSkinContainer::EState::ERROR || |
| 916 | pSkinContainer->m_State == CSkinContainer::EState::NOT_FOUND || |
| 917 | pSkinContainer->IsSpecial()) |
| 918 | { |
| 919 | continue; |
| 920 | } |
| 921 | vpConsideredSkins.push_back(pSkinContainer.get()); |
| 922 | } |
| 923 | const char *pRandomSkin; |
| 924 | if(vpConsideredSkins.empty()) |
| 925 | { |
| 926 | pRandomSkin = "default"; |
| 927 | } |
| 928 | else |
| 929 | { |
| 930 | pRandomSkin = vpConsideredSkins[rand() % vpConsideredSkins.size()]->Name(); |
| 931 | } |
| 932 | |
| 933 | char *pSkinName = Dummy ? g_Config.m_ClDummySkin : g_Config.m_ClPlayerSkin; |
| 934 | const size_t SkinNameSize = Dummy ? sizeof(g_Config.m_ClDummySkin) : sizeof(g_Config.m_ClPlayerSkin); |
| 935 | str_copy(pSkinName, pRandomSkin, SkinNameSize); |
| 936 | m_SkinList.ForceRefresh(); |
| 937 | } |
| 938 | |
| 939 | const char *CSkins::SkinPrefix() const |
| 940 | { |
no test coverage detected