| 1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
| 2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
| 3 | #include "menus.h" |
| 4 | |
| 5 | #include <base/str.h> |
| 6 | |
| 7 | #include <engine/graphics.h> |
| 8 | #include <engine/shared/config.h> |
| 9 | #include <engine/textrender.h> |
| 10 | |
| 11 | #include <generated/client_data.h> |
| 12 | |
| 13 | #include <game/client/animstate.h> |
| 14 | #include <game/client/components/chat.h> |
| 15 | #include <game/client/components/effects.h> |
| 16 | #include <game/client/components/items.h> |
| 17 | #include <game/client/components/mapimages.h> |
| 18 | #include <game/client/components/nameplates.h> |
| 19 | #include <game/client/components/skins.h> |
| 20 | #include <game/client/components/tooltips.h> |
| 21 | #include <game/client/gameclient.h> |
| 22 | #include <game/client/skin.h> |
| 23 | #include <game/client/ui.h> |
| 24 | #include <game/client/ui_listbox.h> |
| 25 | #include <game/client/ui_scrollregion.h> |
| 26 | #include <game/localization.h> |
| 27 | |
| 28 | enum |
| 29 | { |
| 30 | APPEARANCE_TAB_HUD = 0, |
| 31 | APPEARANCE_TAB_CHAT = 1, |
| 32 | APPEARANCE_TAB_NAME_PLATE = 2, |
| 33 | APPEARANCE_TAB_HOOK_COLLISION = 3, |
| 34 | APPEARANCE_TAB_INFO_MESSAGES = 4, |
| 35 | APPEARANCE_TAB_LASER = 5, |
| 36 | NUMBER_OF_APPEARANCE_TABS = 6, |
| 37 | }; |
| 38 | |
| 39 | void CMenus::(CUIRect MainView) |
| 40 | { |
| 41 | char aBuf[128]; |
| 42 | static int s_CurTab = 0; |
| 43 | |
| 44 | CUIRect TabBar, LeftView, RightView, Button; |
| 45 | |
| 46 | MainView.HSplitTop(Cut: 20.0f, pTop: &TabBar, pBottom: &MainView); |
| 47 | const float TabWidth = TabBar.w / (float)NUMBER_OF_APPEARANCE_TABS; |
| 48 | static CButtonContainer s_aPageTabs[NUMBER_OF_APPEARANCE_TABS] = {}; |
| 49 | const char *apTabNames[NUMBER_OF_APPEARANCE_TABS] = { |
| 50 | Localize(pStr: "HUD" ), |
| 51 | Localize(pStr: "Chat" ), |
| 52 | Localize(pStr: "Name Plate" ), |
| 53 | Localize(pStr: "Hook Collisions" ), |
| 54 | Localize(pStr: "Info Messages" ), |
| 55 | Localize(pStr: "Laser" )}; |
| 56 | |
| 57 | for(int Tab = APPEARANCE_TAB_HUD; Tab < NUMBER_OF_APPEARANCE_TABS; ++Tab) |
| 58 | { |
| 59 | TabBar.VSplitLeft(Cut: TabWidth, pLeft: &Button, pRight: &TabBar); |
| 60 | const int Corners = Tab == APPEARANCE_TAB_HUD ? IGraphics::CORNER_L : (Tab == NUMBER_OF_APPEARANCE_TABS - 1 ? IGraphics::CORNER_R : IGraphics::CORNER_NONE); |
| 61 | if(DoButton_MenuTab(pButtonContainer: &s_aPageTabs[Tab], pText: apTabNames[Tab], Checked: s_CurTab == Tab, pRect: &Button, Corners, pAnimator: nullptr, pDefaultColor: nullptr, pActiveColor: nullptr, pHoverColor: nullptr, EdgeRounding: 4.0f)) |
| 62 | { |
| 63 | s_CurTab = Tab; |
| 64 | } |
| 65 | } |
| 66 | |
| 67 | MainView.HSplitTop(Cut: 10.0f, pTop: nullptr, pBottom: &MainView); |
| 68 | |
| 69 | const float LineSize = 20.0f; |
| 70 | const float ColorPickerLineSize = 25.0f; |
| 71 | const float HeadlineFontSize = 20.0f; |
| 72 | const float HeadlineHeight = 30.0f; |
| 73 | const float MarginSmall = 5.0f; |
| 74 | const float MarginBetweenViews = 20.0f; |
| 75 | |
| 76 | const float ColorPickerLabelSize = 13.0f; |
| 77 | const float ColorPickerLineSpacing = 5.0f; |
| 78 | |
| 79 | if(s_CurTab == APPEARANCE_TAB_HUD) |
| 80 | { |
| 81 | MainView.VSplitMid(pLeft: &LeftView, pRight: &RightView, Spacing: MarginBetweenViews); |
| 82 | |
| 83 | // ***** HUD ***** // |
| 84 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "HUD" ), FontSize: HeadlineFontSize, |
| 85 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 86 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 87 | |
| 88 | // Switch of the entire HUD |
| 89 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhud, pText: Localize(pStr: "Show ingame HUD" ), pValue: &g_Config.m_ClShowhud, pRect: &LeftView, VMargin: LineSize); |
| 90 | |
| 91 | // Switches of the various normal HUD elements |
| 92 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudHealthAmmo, pText: Localize(pStr: "Show health, shields and ammo" ), pValue: &g_Config.m_ClShowhudHealthAmmo, pRect: &LeftView, VMargin: LineSize); |
| 93 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudScore, pText: Localize(pStr: "Show score" ), pValue: &g_Config.m_ClShowhudScore, pRect: &LeftView, VMargin: LineSize); |
| 94 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowLocalTimeAlways, pText: Localize(pStr: "Show local time always" ), pValue: &g_Config.m_ClShowLocalTimeAlways, pRect: &LeftView, VMargin: LineSize); |
| 95 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClSpecCursor, pText: Localize(pStr: "Show spectator cursor" ), pValue: &g_Config.m_ClSpecCursor, pRect: &LeftView, VMargin: LineSize); |
| 96 | |
| 97 | // Settings of the HUD element for votes |
| 98 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowVotesAfterVoting, pText: Localize(pStr: "Show votes window after voting" ), pValue: &g_Config.m_ClShowVotesAfterVoting, pRect: &LeftView, VMargin: LineSize); |
| 99 | |
| 100 | // ***** Scoreboard ***** // |
| 101 | LeftView.HSplitTop(Cut: MarginBetweenViews, pTop: nullptr, pBottom: &LeftView); |
| 102 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Scoreboard" ), FontSize: HeadlineFontSize, |
| 103 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 104 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 105 | |
| 106 | ColorRGBA GreenDefault(0.78f, 1.0f, 0.8f, 1.0f); |
| 107 | static CButtonContainer s_AuthedColor, s_SameClanColor; |
| 108 | DoLine_ColorPicker(pResetId: &s_AuthedColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Authed name color in scoreboard" ), pColorValue: &g_Config.m_ClAuthedPlayerColor, DefaultColor: GreenDefault, CheckBoxSpacing: false); |
| 109 | DoLine_ColorPicker(pResetId: &s_SameClanColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Same clan color in scoreboard" ), pColorValue: &g_Config.m_ClSameClanColor, DefaultColor: GreenDefault, CheckBoxSpacing: false); |
| 110 | |
| 111 | // ***** DDRace HUD ***** // |
| 112 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "DDRace HUD" ), FontSize: HeadlineFontSize, |
| 113 | Align: TEXTALIGN_ML, pRect: &RightView, LineSize: HeadlineHeight); |
| 114 | RightView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 115 | |
| 116 | // Switches of various DDRace HUD elements |
| 117 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowIds, pText: Localize(pStr: "Show client IDs (scoreboard, chat, spectator)" ), pValue: &g_Config.m_ClShowIds, pRect: &RightView, VMargin: LineSize); |
| 118 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudDDRace, pText: Localize(pStr: "Show DDRace HUD" ), pValue: &g_Config.m_ClShowhudDDRace, pRect: &RightView, VMargin: LineSize); |
| 119 | if(g_Config.m_ClShowhudDDRace) |
| 120 | { |
| 121 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudJumpsIndicator, pText: Localize(pStr: "Show jumps indicator" ), pValue: &g_Config.m_ClShowhudJumpsIndicator, pRect: &RightView, VMargin: LineSize); |
| 122 | } |
| 123 | else |
| 124 | { |
| 125 | RightView.HSplitTop(Cut: LineSize, pTop: nullptr, pBottom: &RightView); // Create empty space for hidden option |
| 126 | } |
| 127 | |
| 128 | // Eye with a number of spectators |
| 129 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudSpectatorCount, pText: Localize(pStr: "Show number of spectators" ), pValue: &g_Config.m_ClShowhudSpectatorCount, pRect: &RightView, VMargin: LineSize); |
| 130 | |
| 131 | // Switch for dummy actions display |
| 132 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudDummyActions, pText: Localize(pStr: "Show dummy actions" ), pValue: &g_Config.m_ClShowhudDummyActions, pRect: &RightView, VMargin: LineSize); |
| 133 | |
| 134 | // Player movement information display settings |
| 135 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudPlayerPosition, pText: Localize(pStr: "Show player position" ), pValue: &g_Config.m_ClShowhudPlayerPosition, pRect: &RightView, VMargin: LineSize); |
| 136 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudPlayerSpeed, pText: Localize(pStr: "Show player speed" ), pValue: &g_Config.m_ClShowhudPlayerSpeed, pRect: &RightView, VMargin: LineSize); |
| 137 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowhudPlayerAngle, pText: Localize(pStr: "Show player target angle" ), pValue: &g_Config.m_ClShowhudPlayerAngle, pRect: &RightView, VMargin: LineSize); |
| 138 | |
| 139 | // Freeze bar settings |
| 140 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowFreezeBars, pText: Localize(pStr: "Show freeze bars" ), pValue: &g_Config.m_ClShowFreezeBars, pRect: &RightView, VMargin: LineSize); |
| 141 | RightView.HSplitTop(Cut: LineSize * 2.0f, pTop: &Button, pBottom: &RightView); |
| 142 | if(g_Config.m_ClShowFreezeBars) |
| 143 | { |
| 144 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClFreezeBarsAlphaInsideFreeze, pOption: &g_Config.m_ClFreezeBarsAlphaInsideFreeze, pRect: &Button, pStr: Localize(pStr: "Opacity of freeze bars inside freeze" ), Min: 0, Max: 100, pScale: &CUi::ms_LinearScrollbarScale, Flags: CUi::SCROLLBAR_OPTION_MULTILINE, pSuffix: "%" ); |
| 145 | } |
| 146 | } |
| 147 | else if(s_CurTab == APPEARANCE_TAB_CHAT) |
| 148 | { |
| 149 | CChat &Chat = GameClient()->m_Chat; |
| 150 | CUIRect TopView, PreviewView; |
| 151 | MainView.HSplitBottom(Cut: 220.0f, pTop: &TopView, pBottom: &PreviewView); |
| 152 | TopView.HSplitBottom(Cut: MarginBetweenViews, pTop: &TopView, pBottom: nullptr); |
| 153 | TopView.VSplitMid(pLeft: &LeftView, pRight: &RightView, Spacing: MarginBetweenViews); |
| 154 | |
| 155 | // ***** Chat ***** // |
| 156 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Chat" ), FontSize: HeadlineFontSize, |
| 157 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 158 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 159 | |
| 160 | // General chat settings |
| 161 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 162 | if(DoButton_CheckBox(pId: &g_Config.m_ClShowChat, pText: Localize(pStr: "Show chat" ), Checked: g_Config.m_ClShowChat, pRect: &Button)) |
| 163 | { |
| 164 | g_Config.m_ClShowChat = g_Config.m_ClShowChat ? 0 : 1; |
| 165 | } |
| 166 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 167 | if(g_Config.m_ClShowChat) |
| 168 | { |
| 169 | static int s_ShowChat = 0; |
| 170 | if(DoButton_CheckBox(pId: &s_ShowChat, pText: Localize(pStr: "Always show chat" ), Checked: g_Config.m_ClShowChat == 2, pRect: &Button)) |
| 171 | g_Config.m_ClShowChat = g_Config.m_ClShowChat != 2 ? 2 : 1; |
| 172 | } |
| 173 | |
| 174 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClChatTeamColors, pText: Localize(pStr: "Show names in chat in team colors" ), pValue: &g_Config.m_ClChatTeamColors, pRect: &LeftView, VMargin: LineSize); |
| 175 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowChatFriends, pText: Localize(pStr: "Show only chat messages from friends" ), pValue: &g_Config.m_ClShowChatFriends, pRect: &LeftView, VMargin: LineSize); |
| 176 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClShowChatTeamMembersOnly, pText: Localize(pStr: "Show only chat messages from team members" ), pValue: &g_Config.m_ClShowChatTeamMembersOnly, pRect: &LeftView, VMargin: LineSize); |
| 177 | |
| 178 | if(DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClChatOld, pText: Localize(pStr: "Use old chat style" ), pValue: &g_Config.m_ClChatOld, pRect: &LeftView, VMargin: LineSize)) |
| 179 | GameClient()->m_Chat.RebuildChat(); |
| 180 | |
| 181 | // DoButton_CheckBoxAutoVMarginAndSet(&g_Config.m_ClCensorChat, Localize("Censor profanity"), &g_Config.m_ClCensorChat, &LeftView, LineSize); |
| 182 | |
| 183 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 184 | if(Ui()->DoScrollbarOption(pId: &g_Config.m_ClChatFontSize, pOption: &g_Config.m_ClChatFontSize, pRect: &Button, pStr: Localize(pStr: "Chat font size" ), Min: 10, Max: 100)) |
| 185 | { |
| 186 | Chat.EnsureCoherentWidth(); |
| 187 | Chat.RebuildChat(); |
| 188 | } |
| 189 | |
| 190 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 191 | if(Ui()->DoScrollbarOption(pId: &g_Config.m_ClChatWidth, pOption: &g_Config.m_ClChatWidth, pRect: &Button, pStr: Localize(pStr: "Chat width" ), Min: 120, Max: 400)) |
| 192 | { |
| 193 | Chat.EnsureCoherentFontSize(); |
| 194 | Chat.RebuildChat(); |
| 195 | } |
| 196 | |
| 197 | static CButtonContainer s_BackgroundColor; |
| 198 | DoLine_ColorPicker(pResetId: &s_BackgroundColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Chat background color" ), pColorValue: &g_Config.m_ClChatBackgroundColor, DefaultColor: color_cast<ColorRGBA>(hsl: ColorHSLA(DefaultConfig::ClChatBackgroundColor, true)), CheckBoxSpacing: false, pCheckBoxValue: nullptr, Alpha: true); |
| 199 | |
| 200 | // ***** Messages ***** // |
| 201 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Messages" ), FontSize: HeadlineFontSize, |
| 202 | Align: TEXTALIGN_ML, pRect: &RightView, LineSize: HeadlineHeight); |
| 203 | RightView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 204 | |
| 205 | // Message Colors and extra settings |
| 206 | static CButtonContainer s_SystemMessageColor; |
| 207 | DoLine_ColorPicker(pResetId: &s_SystemMessageColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &RightView, pText: Localize(pStr: "System message" ), pColorValue: &g_Config.m_ClMessageSystemColor, DefaultColor: ColorRGBA(1.0f, 1.0f, 0.5f), CheckBoxSpacing: true, pCheckBoxValue: &g_Config.m_ClShowChatSystem); |
| 208 | static CButtonContainer s_HighlightedMessageColor; |
| 209 | DoLine_ColorPicker(pResetId: &s_HighlightedMessageColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &RightView, pText: Localize(pStr: "Highlighted message" ), pColorValue: &g_Config.m_ClMessageHighlightColor, DefaultColor: ColorRGBA(1.0f, 0.5f, 0.5f)); |
| 210 | static CButtonContainer s_TeamMessageColor; |
| 211 | DoLine_ColorPicker(pResetId: &s_TeamMessageColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &RightView, pText: Localize(pStr: "Team message" ), pColorValue: &g_Config.m_ClMessageTeamColor, DefaultColor: ColorRGBA(0.65f, 1.0f, 0.65f)); |
| 212 | static CButtonContainer s_FriendMessageColor; |
| 213 | DoLine_ColorPicker(pResetId: &s_FriendMessageColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &RightView, pText: Localize(pStr: "Friend message" ), pColorValue: &g_Config.m_ClMessageFriendColor, DefaultColor: ColorRGBA(1.0f, 0.137f, 0.137f), CheckBoxSpacing: true, pCheckBoxValue: &g_Config.m_ClMessageFriend); |
| 214 | static CButtonContainer s_NormalMessageColor; |
| 215 | DoLine_ColorPicker(pResetId: &s_NormalMessageColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &RightView, pText: Localize(pStr: "Normal message" ), pColorValue: &g_Config.m_ClMessageColor, DefaultColor: ColorRGBA(1.0f, 1.0f, 1.0f)); |
| 216 | |
| 217 | str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%s (echo)" , Localize(pStr: "Client message" )); |
| 218 | static CButtonContainer s_ClientMessageColor; |
| 219 | DoLine_ColorPicker(pResetId: &s_ClientMessageColor, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &RightView, pText: aBuf, pColorValue: &g_Config.m_ClMessageClientColor, DefaultColor: ColorRGBA(0.5f, 0.78f, 1.0f)); |
| 220 | |
| 221 | // ***** Chat Preview ***** // |
| 222 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Preview" ), FontSize: HeadlineFontSize, |
| 223 | Align: TEXTALIGN_ML, pRect: &PreviewView, LineSize: HeadlineHeight); |
| 224 | PreviewView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &PreviewView); |
| 225 | |
| 226 | // Use the rest of the view for preview |
| 227 | PreviewView.Draw(Color: ColorRGBA(1, 1, 1, 0.1f), Corners: IGraphics::CORNER_ALL, Rounding: 5.0f); |
| 228 | PreviewView.Margin(Cut: MarginSmall, pOtherRect: &PreviewView); |
| 229 | |
| 230 | ColorRGBA SystemColor = color_cast<ColorRGBA, ColorHSLA>(hsl: ColorHSLA(g_Config.m_ClMessageSystemColor)); |
| 231 | ColorRGBA HighlightedColor = color_cast<ColorRGBA, ColorHSLA>(hsl: ColorHSLA(g_Config.m_ClMessageHighlightColor)); |
| 232 | ColorRGBA TeamColor = color_cast<ColorRGBA, ColorHSLA>(hsl: ColorHSLA(g_Config.m_ClMessageTeamColor)); |
| 233 | ColorRGBA FriendColor = color_cast<ColorRGBA, ColorHSLA>(hsl: ColorHSLA(g_Config.m_ClMessageFriendColor)); |
| 234 | ColorRGBA NormalColor = color_cast<ColorRGBA, ColorHSLA>(hsl: ColorHSLA(g_Config.m_ClMessageColor)); |
| 235 | ColorRGBA ClientColor = color_cast<ColorRGBA, ColorHSLA>(hsl: ColorHSLA(g_Config.m_ClMessageClientColor)); |
| 236 | ColorRGBA DefaultNameColor(0.8f, 0.8f, 0.8f, 1.0f); |
| 237 | |
| 238 | const float RealFontSize = Chat.FontSize() * 2; |
| 239 | const float RealMsgPaddingX = (!g_Config.m_ClChatOld ? Chat.MessagePaddingX() : 0) * 2; |
| 240 | const float RealMsgPaddingY = (!g_Config.m_ClChatOld ? Chat.MessagePaddingY() : 0) * 2; |
| 241 | const float RealMsgPaddingTee = (!g_Config.m_ClChatOld ? Chat.MessageTeeSize() + CChat::MESSAGE_TEE_PADDING_RIGHT : 0) * 2; |
| 242 | const float RealOffsetY = RealFontSize + RealMsgPaddingY; |
| 243 | |
| 244 | const float X = RealMsgPaddingX / 2.0f + PreviewView.x; |
| 245 | float Y = PreviewView.y; |
| 246 | float LineWidth = g_Config.m_ClChatWidth * 2 - (RealMsgPaddingX * 1.5f) - RealMsgPaddingTee; |
| 247 | |
| 248 | str_copy(dst&: aBuf, src: Client()->PlayerName()); |
| 249 | |
| 250 | const CAnimState *pIdleState = CAnimState::GetIdle(); |
| 251 | const float RealTeeSize = Chat.MessageTeeSize() * 2; |
| 252 | const float RealTeeSizeHalved = Chat.MessageTeeSize(); |
| 253 | constexpr float TWSkinUnreliableOffset = -0.25f; |
| 254 | const float OffsetTeeY = RealTeeSizeHalved; |
| 255 | const float FullHeightMinusTee = RealOffsetY - RealTeeSize; |
| 256 | |
| 257 | struct SPreviewLine |
| 258 | { |
| 259 | int m_ClientId; |
| 260 | bool m_Team; |
| 261 | char m_aName[64]; |
| 262 | char m_aText[256]; |
| 263 | bool m_Friend; |
| 264 | bool m_Player; |
| 265 | bool m_Client; |
| 266 | bool m_Highlighted; |
| 267 | int m_TimesRepeated; |
| 268 | |
| 269 | CTeeRenderInfo m_RenderInfo; |
| 270 | }; |
| 271 | |
| 272 | static std::vector<SPreviewLine> s_vLines; |
| 273 | |
| 274 | enum ELineFlag |
| 275 | { |
| 276 | FLAG_TEAM = 1 << 0, |
| 277 | FLAG_FRIEND = 1 << 1, |
| 278 | FLAG_HIGHLIGHT = 1 << 2, |
| 279 | FLAG_CLIENT = 1 << 3 |
| 280 | }; |
| 281 | enum |
| 282 | { |
| 283 | PREVIEW_SYS, |
| 284 | PREVIEW_HIGHLIGHT, |
| 285 | PREVIEW_TEAM, |
| 286 | PREVIEW_FRIEND, |
| 287 | PREVIEW_SPAMMER, |
| 288 | PREVIEW_CLIENT |
| 289 | }; |
| 290 | auto &&SetPreviewLine = [](int Index, int ClientId, const char *pName, const char *pText, int Flag, int Repeats) { |
| 291 | SPreviewLine *pLine; |
| 292 | if((int)s_vLines.size() <= Index) |
| 293 | { |
| 294 | s_vLines.emplace_back(); |
| 295 | pLine = &s_vLines.back(); |
| 296 | } |
| 297 | else |
| 298 | { |
| 299 | pLine = &s_vLines[Index]; |
| 300 | } |
| 301 | pLine->m_ClientId = ClientId; |
| 302 | pLine->m_Team = Flag & FLAG_TEAM; |
| 303 | pLine->m_Friend = Flag & FLAG_FRIEND; |
| 304 | pLine->m_Player = ClientId >= 0; |
| 305 | pLine->m_Highlighted = Flag & FLAG_HIGHLIGHT; |
| 306 | pLine->m_Client = Flag & FLAG_CLIENT; |
| 307 | pLine->m_TimesRepeated = Repeats; |
| 308 | str_copy(dst&: pLine->m_aName, src: pName); |
| 309 | str_copy(dst&: pLine->m_aText, src: pText); |
| 310 | }; |
| 311 | auto &&SetLineSkin = [RealTeeSize](int Index, const CSkin *pSkin) { |
| 312 | if(Index >= (int)s_vLines.size()) |
| 313 | return; |
| 314 | s_vLines[Index].m_RenderInfo.m_Size = RealTeeSize; |
| 315 | s_vLines[Index].m_RenderInfo.Apply(pSkin); |
| 316 | }; |
| 317 | |
| 318 | auto &&RenderPreview = [&](int LineIndex, int x, int y, bool Render = true) { |
| 319 | if(LineIndex >= (int)s_vLines.size()) |
| 320 | return vec2(0, 0); |
| 321 | CTextCursor LocalCursor; |
| 322 | LocalCursor.SetPosition(vec2(x, y)); |
| 323 | LocalCursor.m_FontSize = RealFontSize; |
| 324 | LocalCursor.m_Flags = Render ? TEXTFLAG_RENDER : 0; |
| 325 | LocalCursor.m_LineWidth = LineWidth; |
| 326 | const auto &Line = s_vLines[LineIndex]; |
| 327 | |
| 328 | char aClientId[16] = "" ; |
| 329 | if(g_Config.m_ClShowIds && Line.m_ClientId >= 0 && Line.m_aName[0] != '\0') |
| 330 | { |
| 331 | GameClient()->FormatClientId(ClientId: Line.m_ClientId, aClientId, Format: EClientIdFormat::INDENT_FORCE); |
| 332 | } |
| 333 | |
| 334 | char aCount[12]; |
| 335 | if(Line.m_ClientId < 0) |
| 336 | str_format(buffer: aCount, buffer_size: sizeof(aCount), format: "[%d] " , Line.m_TimesRepeated + 1); |
| 337 | else |
| 338 | str_format(buffer: aCount, buffer_size: sizeof(aCount), format: " [%d]" , Line.m_TimesRepeated + 1); |
| 339 | |
| 340 | if(Line.m_Player) |
| 341 | { |
| 342 | LocalCursor.m_X += RealMsgPaddingTee; |
| 343 | |
| 344 | if(Line.m_Friend && g_Config.m_ClMessageFriend) |
| 345 | { |
| 346 | if(Render) |
| 347 | TextRender()->TextColor(Color: FriendColor); |
| 348 | TextRender()->TextEx(pCursor: &LocalCursor, pText: "♥ " , Length: -1); |
| 349 | } |
| 350 | } |
| 351 | |
| 352 | ColorRGBA NameColor; |
| 353 | if(Line.m_Team) |
| 354 | NameColor = CalculateNameColor(TextColorHSL: color_cast<ColorHSLA>(rgb: TeamColor)); |
| 355 | else if(Line.m_Player) |
| 356 | NameColor = DefaultNameColor; |
| 357 | else if(Line.m_Client) |
| 358 | NameColor = ClientColor; |
| 359 | else |
| 360 | NameColor = SystemColor; |
| 361 | |
| 362 | if(Render) |
| 363 | TextRender()->TextColor(Color: NameColor); |
| 364 | |
| 365 | TextRender()->TextEx(pCursor: &LocalCursor, pText: aClientId); |
| 366 | TextRender()->TextEx(pCursor: &LocalCursor, pText: Line.m_aName); |
| 367 | |
| 368 | if(Line.m_TimesRepeated > 0) |
| 369 | { |
| 370 | if(Render) |
| 371 | TextRender()->TextColor(r: 1.0f, g: 1.0f, b: 1.0f, a: 0.3f); |
| 372 | TextRender()->TextEx(pCursor: &LocalCursor, pText: aCount, Length: -1); |
| 373 | } |
| 374 | |
| 375 | if(Line.m_ClientId >= 0 && Line.m_aName[0] != '\0') |
| 376 | { |
| 377 | if(Render) |
| 378 | TextRender()->TextColor(Color: NameColor); |
| 379 | TextRender()->TextEx(pCursor: &LocalCursor, pText: ": " , Length: -1); |
| 380 | } |
| 381 | |
| 382 | CTextCursor AppendCursor = LocalCursor; |
| 383 | AppendCursor.m_LongestLineWidth = 0.0f; |
| 384 | if(!g_Config.m_ClChatOld) |
| 385 | { |
| 386 | AppendCursor.m_StartX = LocalCursor.m_X; |
| 387 | AppendCursor.m_LineWidth -= LocalCursor.m_LongestLineWidth; |
| 388 | } |
| 389 | |
| 390 | if(Render) |
| 391 | { |
| 392 | if(Line.m_Highlighted) |
| 393 | TextRender()->TextColor(Color: HighlightedColor); |
| 394 | else if(Line.m_Team) |
| 395 | TextRender()->TextColor(Color: TeamColor); |
| 396 | else if(Line.m_Player) |
| 397 | TextRender()->TextColor(Color: NormalColor); |
| 398 | } |
| 399 | |
| 400 | TextRender()->TextEx(pCursor: &AppendCursor, pText: Line.m_aText, Length: -1); |
| 401 | if(Render) |
| 402 | TextRender()->TextColor(Color: TextRender()->DefaultTextColor()); |
| 403 | |
| 404 | return vec2{LocalCursor.m_LongestLineWidth + AppendCursor.m_LongestLineWidth, AppendCursor.Height() + RealMsgPaddingY}; |
| 405 | }; |
| 406 | |
| 407 | // Set preview lines |
| 408 | { |
| 409 | char aLineBuilder[128]; |
| 410 | |
| 411 | str_format(buffer: aLineBuilder, buffer_size: sizeof(aLineBuilder), format: "'%s' entered and joined the game" , aBuf); |
| 412 | SetPreviewLine(PREVIEW_SYS, -1, "*** " , aLineBuilder, 0, 0); |
| 413 | |
| 414 | str_format(buffer: aLineBuilder, buffer_size: sizeof(aLineBuilder), format: "Hey, how are you %s?" , aBuf); |
| 415 | SetPreviewLine(PREVIEW_HIGHLIGHT, 7, "Random Tee" , aLineBuilder, FLAG_HIGHLIGHT, 0); |
| 416 | |
| 417 | SetPreviewLine(PREVIEW_TEAM, 11, "Your Teammate" , "Let's speedrun this!" , FLAG_TEAM, 0); |
| 418 | SetPreviewLine(PREVIEW_FRIEND, 8, "Friend" , "Hello there" , FLAG_FRIEND, 0); |
| 419 | SetPreviewLine(PREVIEW_SPAMMER, 9, "Spammer" , "Hey fools, I'm spamming here!" , 0, 5); |
| 420 | SetPreviewLine(PREVIEW_CLIENT, -1, "— " , "Echo command executed" , FLAG_CLIENT, 0); |
| 421 | } |
| 422 | |
| 423 | SetLineSkin(1, GameClient()->m_Skins.Find(pName: "pinky" )); |
| 424 | SetLineSkin(2, GameClient()->m_Skins.Find(pName: "default" )); |
| 425 | SetLineSkin(3, GameClient()->m_Skins.Find(pName: "cammostripes" )); |
| 426 | SetLineSkin(4, GameClient()->m_Skins.Find(pName: "beast" )); |
| 427 | |
| 428 | // Backgrounds first |
| 429 | if(!g_Config.m_ClChatOld) |
| 430 | { |
| 431 | Graphics()->TextureClear(); |
| 432 | Graphics()->QuadsBegin(); |
| 433 | Graphics()->SetColor(color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClChatBackgroundColor, true))); |
| 434 | |
| 435 | float TempY = Y; |
| 436 | const float RealBackgroundRounding = Chat.MessageRounding() * 2.0f; |
| 437 | |
| 438 | auto &&RenderMessageBackground = [&](int LineIndex) { |
| 439 | auto Size = RenderPreview(LineIndex, 0, 0, false); |
| 440 | Graphics()->DrawRectExt(x: X - RealMsgPaddingX / 2.0f, y: TempY - RealMsgPaddingY / 2.0f, w: Size.x + RealMsgPaddingX * 1.5f, h: Size.y, r: RealBackgroundRounding, Corners: IGraphics::CORNER_ALL); |
| 441 | return Size.y; |
| 442 | }; |
| 443 | |
| 444 | if(g_Config.m_ClShowChatSystem) |
| 445 | { |
| 446 | TempY += RenderMessageBackground(PREVIEW_SYS); |
| 447 | } |
| 448 | |
| 449 | if(!g_Config.m_ClShowChatFriends) |
| 450 | { |
| 451 | if(!g_Config.m_ClShowChatTeamMembersOnly) |
| 452 | TempY += RenderMessageBackground(PREVIEW_HIGHLIGHT); |
| 453 | TempY += RenderMessageBackground(PREVIEW_TEAM); |
| 454 | } |
| 455 | |
| 456 | if(!g_Config.m_ClShowChatTeamMembersOnly) |
| 457 | TempY += RenderMessageBackground(PREVIEW_FRIEND); |
| 458 | |
| 459 | if(!g_Config.m_ClShowChatFriends && !g_Config.m_ClShowChatTeamMembersOnly) |
| 460 | { |
| 461 | TempY += RenderMessageBackground(PREVIEW_SPAMMER); |
| 462 | } |
| 463 | |
| 464 | TempY += RenderMessageBackground(PREVIEW_CLIENT); |
| 465 | |
| 466 | Graphics()->QuadsEnd(); |
| 467 | } |
| 468 | |
| 469 | // System |
| 470 | if(g_Config.m_ClShowChatSystem) |
| 471 | { |
| 472 | Y += RenderPreview(PREVIEW_SYS, X, Y).y; |
| 473 | } |
| 474 | |
| 475 | if(!g_Config.m_ClShowChatFriends) |
| 476 | { |
| 477 | // Highlighted |
| 478 | if(!g_Config.m_ClChatOld && !g_Config.m_ClShowChatTeamMembersOnly) |
| 479 | RenderTools()->RenderTee(pAnim: pIdleState, pInfo: &s_vLines[PREVIEW_HIGHLIGHT].m_RenderInfo, Emote: EMOTE_NORMAL, Dir: vec2(1, 0.1f), Pos: vec2(X + RealTeeSizeHalved, Y + OffsetTeeY + FullHeightMinusTee / 2.0f + TWSkinUnreliableOffset)); |
| 480 | if(!g_Config.m_ClShowChatTeamMembersOnly) |
| 481 | Y += RenderPreview(PREVIEW_HIGHLIGHT, X, Y).y; |
| 482 | |
| 483 | // Team |
| 484 | if(!g_Config.m_ClChatOld) |
| 485 | RenderTools()->RenderTee(pAnim: pIdleState, pInfo: &s_vLines[PREVIEW_TEAM].m_RenderInfo, Emote: EMOTE_NORMAL, Dir: vec2(1, 0.1f), Pos: vec2(X + RealTeeSizeHalved, Y + OffsetTeeY + FullHeightMinusTee / 2.0f + TWSkinUnreliableOffset)); |
| 486 | Y += RenderPreview(PREVIEW_TEAM, X, Y).y; |
| 487 | } |
| 488 | |
| 489 | // Friend |
| 490 | if(!g_Config.m_ClChatOld && !g_Config.m_ClShowChatTeamMembersOnly) |
| 491 | RenderTools()->RenderTee(pAnim: pIdleState, pInfo: &s_vLines[PREVIEW_FRIEND].m_RenderInfo, Emote: EMOTE_NORMAL, Dir: vec2(1, 0.1f), Pos: vec2(X + RealTeeSizeHalved, Y + OffsetTeeY + FullHeightMinusTee / 2.0f + TWSkinUnreliableOffset)); |
| 492 | if(!g_Config.m_ClShowChatTeamMembersOnly) |
| 493 | Y += RenderPreview(PREVIEW_FRIEND, X, Y).y; |
| 494 | |
| 495 | // Normal |
| 496 | if(!g_Config.m_ClShowChatFriends && !g_Config.m_ClShowChatTeamMembersOnly) |
| 497 | { |
| 498 | if(!g_Config.m_ClChatOld) |
| 499 | RenderTools()->RenderTee(pAnim: pIdleState, pInfo: &s_vLines[PREVIEW_SPAMMER].m_RenderInfo, Emote: EMOTE_NORMAL, Dir: vec2(1, 0.1f), Pos: vec2(X + RealTeeSizeHalved, Y + OffsetTeeY + FullHeightMinusTee / 2.0f + TWSkinUnreliableOffset)); |
| 500 | Y += RenderPreview(PREVIEW_SPAMMER, X, Y).y; |
| 501 | } |
| 502 | // Client |
| 503 | RenderPreview(PREVIEW_CLIENT, X, Y); |
| 504 | |
| 505 | TextRender()->TextColor(Color: TextRender()->DefaultTextColor()); |
| 506 | } |
| 507 | else if(s_CurTab == APPEARANCE_TAB_NAME_PLATE) |
| 508 | { |
| 509 | MainView.VSplitMid(pLeft: &LeftView, pRight: &RightView, Spacing: MarginBetweenViews); |
| 510 | |
| 511 | // ***** Name Plate ***** // |
| 512 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Name Plate" ), FontSize: HeadlineFontSize, |
| 513 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 514 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 515 | |
| 516 | // General name plate settings |
| 517 | { |
| 518 | int Pressed = (g_Config.m_ClNamePlates ? 2 : 0) + (g_Config.m_ClNamePlatesOwn ? 1 : 0); |
| 519 | if(DoLine_RadioMenu(View&: LeftView, pLabel: Localize(pStr: "Show name plates" ), |
| 520 | vButtonContainers&: m_vButtonContainersNamePlateShow, |
| 521 | vLabels: {Localize(pStr: "None" , pContext: "Show name plates" ), Localize(pStr: "Own" , pContext: "Show name plates" ), Localize(pStr: "Others" , pContext: "Show name plates" ), Localize(pStr: "All" , pContext: "Show name plates" )}, |
| 522 | vValues: {0, 1, 2, 3}, |
| 523 | Value&: Pressed)) |
| 524 | { |
| 525 | g_Config.m_ClNamePlates = Pressed & 2 ? 1 : 0; |
| 526 | g_Config.m_ClNamePlatesOwn = Pressed & 1 ? 1 : 0; |
| 527 | } |
| 528 | } |
| 529 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 530 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClNamePlatesSize, pOption: &g_Config.m_ClNamePlatesSize, pRect: &Button, pStr: Localize(pStr: "Name plates size" ), Min: -50, Max: 100); |
| 531 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 532 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClNamePlatesOffset, pOption: &g_Config.m_ClNamePlatesOffset, pRect: &Button, pStr: Localize(pStr: "Name plates offset" ), Min: 10, Max: 50); |
| 533 | |
| 534 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClNamePlatesClan, pText: Localize(pStr: "Show clan above name plates" ), pValue: &g_Config.m_ClNamePlatesClan, pRect: &LeftView, VMargin: LineSize); |
| 535 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 536 | if(g_Config.m_ClNamePlatesClan) |
| 537 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClNamePlatesClanSize, pOption: &g_Config.m_ClNamePlatesClanSize, pRect: &Button, pStr: Localize(pStr: "Clan plates size" ), Min: -50, Max: 100); |
| 538 | |
| 539 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClNamePlatesTeamcolors, pText: Localize(pStr: "Use team colors for name plates" ), pValue: &g_Config.m_ClNamePlatesTeamcolors, pRect: &LeftView, VMargin: LineSize); |
| 540 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClNamePlatesFriendMark, pText: Localize(pStr: "Show friend icon in name plates" ), pValue: &g_Config.m_ClNamePlatesFriendMark, pRect: &LeftView, VMargin: LineSize); |
| 541 | |
| 542 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClNamePlatesIds, pText: Localize(pStr: "Show client IDs in name plates" ), pValue: &g_Config.m_ClNamePlatesIds, pRect: &LeftView, VMargin: LineSize); |
| 543 | if(g_Config.m_ClNamePlatesIds > 0) |
| 544 | DoButton_CheckBoxAutoVMarginAndSet(pId: &g_Config.m_ClNamePlatesIdsSeparateLine, pText: Localize(pStr: "Show client IDs on a separate line" ), pValue: &g_Config.m_ClNamePlatesIdsSeparateLine, pRect: &LeftView, VMargin: LineSize); |
| 545 | else |
| 546 | LeftView.HSplitTop(Cut: LineSize, pTop: nullptr, pBottom: &LeftView); |
| 547 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 548 | if(g_Config.m_ClNamePlatesIds > 0 && g_Config.m_ClNamePlatesIdsSeparateLine > 0) |
| 549 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClNamePlatesIdsSize, pOption: &g_Config.m_ClNamePlatesIdsSize, pRect: &Button, pStr: Localize(pStr: "Client IDs size" ), Min: -50, Max: 100); |
| 550 | |
| 551 | // ***** Hook Strength ***** // |
| 552 | LeftView.HSplitTop(Cut: MarginBetweenViews, pTop: nullptr, pBottom: &LeftView); |
| 553 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Hook Strength" ), FontSize: HeadlineFontSize, |
| 554 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 555 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 556 | |
| 557 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 558 | if(DoButton_CheckBox(pId: &g_Config.m_ClNamePlatesStrong, pText: Localize(pStr: "Show hook strength icon indicator" ), Checked: g_Config.m_ClNamePlatesStrong, pRect: &Button)) |
| 559 | { |
| 560 | g_Config.m_ClNamePlatesStrong = g_Config.m_ClNamePlatesStrong ? 0 : 1; |
| 561 | } |
| 562 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 563 | if(g_Config.m_ClNamePlatesStrong) |
| 564 | { |
| 565 | static int s_NamePlatesStrong = 0; |
| 566 | if(DoButton_CheckBox(pId: &s_NamePlatesStrong, pText: Localize(pStr: "Show hook strength number indicator" ), Checked: g_Config.m_ClNamePlatesStrong == 2, pRect: &Button)) |
| 567 | g_Config.m_ClNamePlatesStrong = g_Config.m_ClNamePlatesStrong != 2 ? 2 : 1; |
| 568 | } |
| 569 | |
| 570 | LeftView.HSplitTop(Cut: LineSize * 2.0f, pTop: &Button, pBottom: &LeftView); |
| 571 | if(g_Config.m_ClNamePlatesStrong) |
| 572 | { |
| 573 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClNamePlatesStrongSize, pOption: &g_Config.m_ClNamePlatesStrongSize, pRect: &Button, pStr: Localize(pStr: "Size of hook strength icon and number indicator" ), Min: -50, Max: 100, pScale: &CUi::ms_LinearScrollbarScale, Flags: CUi::SCROLLBAR_OPTION_MULTILINE); |
| 574 | } |
| 575 | |
| 576 | // ***** Key Presses ***** // |
| 577 | LeftView.HSplitTop(Cut: MarginBetweenViews, pTop: nullptr, pBottom: &LeftView); |
| 578 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Key Presses" ), FontSize: HeadlineFontSize, |
| 579 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 580 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 581 | |
| 582 | DoLine_RadioMenu(View&: LeftView, pLabel: Localize(pStr: "Show players' key presses" ), |
| 583 | vButtonContainers&: m_vButtonContainersNamePlateKeyPresses, |
| 584 | vLabels: {Localize(pStr: "None" , pContext: "Show players' key presses" ), Localize(pStr: "Own" , pContext: "Show players' key presses" ), Localize(pStr: "Others" , pContext: "Show players' key presses" ), Localize(pStr: "All" , pContext: "Show players' key presses" )}, |
| 585 | vValues: {0, 3, 1, 2}, |
| 586 | Value&: g_Config.m_ClShowDirection); |
| 587 | |
| 588 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 589 | if(g_Config.m_ClShowDirection > 0) |
| 590 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClDirectionSize, pOption: &g_Config.m_ClDirectionSize, pRect: &Button, pStr: Localize(pStr: "Size of key press icons" ), Min: -50, Max: 100); |
| 591 | |
| 592 | // ***** Name Plate Preview ***** // |
| 593 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Preview" ), FontSize: HeadlineFontSize, |
| 594 | Align: TEXTALIGN_ML, pRect: &RightView, LineSize: HeadlineHeight); |
| 595 | RightView.HSplitTop(Cut: 2.0f * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 596 | |
| 597 | // ***** Name Plate Dummy Preview ***** // |
| 598 | RightView.HSplitBottom(Cut: LineSize, pTop: &RightView, pBottom: &Button); |
| 599 | if(DoButton_CheckBox(pId: &m_DummyNamePlatePreview, pText: g_Config.m_ClDummy ? Localize(pStr: "Preview player's name plate" ) : Localize(pStr: "Preview dummy's name plate" ), Checked: m_DummyNamePlatePreview, pRect: &Button)) |
| 600 | m_DummyNamePlatePreview = !m_DummyNamePlatePreview; |
| 601 | |
| 602 | int Dummy = g_Config.m_ClDummy != (m_DummyNamePlatePreview ? 1 : 0); |
| 603 | |
| 604 | const vec2 Position = RightView.Center(); |
| 605 | |
| 606 | GameClient()->m_NamePlates.RenderNamePlatePreview(Position, Dummy); |
| 607 | } |
| 608 | else if(s_CurTab == APPEARANCE_TAB_HOOK_COLLISION) |
| 609 | { |
| 610 | MainView.VSplitMid(pLeft: &LeftView, pRight: &RightView, Spacing: MarginBetweenViews); |
| 611 | |
| 612 | // ***** Hookline ***** // |
| 613 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Hook collision line" ), FontSize: HeadlineFontSize, |
| 614 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 615 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 616 | |
| 617 | // General hookline settings |
| 618 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 619 | if(DoButton_CheckBox(pId: &g_Config.m_ClShowHookCollOwn, pText: Localize(pStr: "Show own player's hook collision line" ), Checked: g_Config.m_ClShowHookCollOwn, pRect: &Button)) |
| 620 | { |
| 621 | g_Config.m_ClShowHookCollOwn = g_Config.m_ClShowHookCollOwn ? 0 : 1; |
| 622 | } |
| 623 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 624 | if(g_Config.m_ClShowHookCollOwn) |
| 625 | { |
| 626 | static int s_ShowHookCollOwn = 0; |
| 627 | if(DoButton_CheckBox(pId: &s_ShowHookCollOwn, pText: Localize(pStr: "Always show own player's hook collision line" ), Checked: g_Config.m_ClShowHookCollOwn == 2, pRect: &Button)) |
| 628 | g_Config.m_ClShowHookCollOwn = g_Config.m_ClShowHookCollOwn != 2 ? 2 : 1; |
| 629 | } |
| 630 | |
| 631 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 632 | if(DoButton_CheckBox(pId: &g_Config.m_ClShowHookCollOther, pText: Localize(pStr: "Show other players' hook collision lines" ), Checked: g_Config.m_ClShowHookCollOther, pRect: &Button)) |
| 633 | { |
| 634 | g_Config.m_ClShowHookCollOther = g_Config.m_ClShowHookCollOther >= 1 ? 0 : 1; |
| 635 | } |
| 636 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 637 | if(g_Config.m_ClShowHookCollOther) |
| 638 | { |
| 639 | static int s_ShowHookCollOther = 0; |
| 640 | if(DoButton_CheckBox(pId: &s_ShowHookCollOther, pText: Localize(pStr: "Always show other players' hook collision lines" ), Checked: g_Config.m_ClShowHookCollOther == 2, pRect: &Button)) |
| 641 | g_Config.m_ClShowHookCollOther = g_Config.m_ClShowHookCollOther != 2 ? 2 : 1; |
| 642 | } |
| 643 | |
| 644 | LeftView.HSplitTop(Cut: LineSize * 2.0f, pTop: &Button, pBottom: &LeftView); |
| 645 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClHookCollSize, pOption: &g_Config.m_ClHookCollSize, pRect: &Button, pStr: Localize(pStr: "Width of your own hook collision line" ), Min: 0, Max: 20, pScale: &CUi::ms_LinearScrollbarScale, Flags: CUi::SCROLLBAR_OPTION_MULTILINE); |
| 646 | |
| 647 | LeftView.HSplitTop(Cut: LineSize * 2.0f, pTop: &Button, pBottom: &LeftView); |
| 648 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClHookCollSizeOther, pOption: &g_Config.m_ClHookCollSizeOther, pRect: &Button, pStr: Localize(pStr: "Width of others' hook collision line" ), Min: 0, Max: 20, pScale: &CUi::ms_LinearScrollbarScale, Flags: CUi::SCROLLBAR_OPTION_MULTILINE); |
| 649 | |
| 650 | LeftView.HSplitTop(Cut: LineSize * 2.0f, pTop: &Button, pBottom: &LeftView); |
| 651 | Ui()->DoScrollbarOption(pId: &g_Config.m_ClHookCollAlpha, pOption: &g_Config.m_ClHookCollAlpha, pRect: &Button, pStr: Localize(pStr: "Hook collision line opacity" ), Min: 0, Max: 100, pScale: &CUi::ms_LinearScrollbarScale, Flags: CUi::SCROLLBAR_OPTION_MULTILINE, pSuffix: "%" ); |
| 652 | |
| 653 | static CButtonContainer s_HookCollNoCollResetId, s_HookCollHookableCollResetId, s_HookCollTeeCollResetId, s_HookCollTipColorResetId; |
| 654 | static int s_HookCollToolTip; |
| 655 | |
| 656 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Colors of the hook collision line:" ), FontSize: 13.0f, |
| 657 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 658 | |
| 659 | Ui()->DoButtonLogic(pId: &s_HookCollToolTip, Checked: 0, pRect: &LeftView, Flags: BUTTONFLAG_NONE); // Just for the tooltip, result ignored |
| 660 | GameClient()->m_Tooltips.DoToolTip(pId: &s_HookCollToolTip, pNearRect: &LeftView, pText: Localize(pStr: "Your movements are not taken into account when calculating the line colors" )); |
| 661 | DoLine_ColorPicker(pResetId: &s_HookCollNoCollResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "When nothing is hookable" , pContext: "Hook collision line color" ), pColorValue: &g_Config.m_ClHookCollColorNoColl, DefaultColor: ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f), CheckBoxSpacing: false); |
| 662 | DoLine_ColorPicker(pResetId: &s_HookCollHookableCollResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "When something is hookable" , pContext: "Hook collision line color" ), pColorValue: &g_Config.m_ClHookCollColorHookableColl, DefaultColor: ColorRGBA(130.0f / 255.0f, 232.0f / 255.0f, 160.0f / 255.0f, 1.0f), CheckBoxSpacing: false); |
| 663 | DoLine_ColorPicker(pResetId: &s_HookCollTeeCollResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "When a Tee is hookable" , pContext: "Hook collision line color" ), pColorValue: &g_Config.m_ClHookCollColorTeeColl, DefaultColor: ColorRGBA(1.0f, 1.0f, 0.0f, 1.0f), CheckBoxSpacing: false); |
| 664 | DoLine_ColorPicker(pResetId: &s_HookCollTipColorResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Hook collision line tip" , pContext: "Hook collision line color" ), pColorValue: &g_Config.m_ClHookCollTipColor, DefaultColor: ColorRGBA(1.0f, 1.0f, 0.0f, 0.5f), CheckBoxSpacing: false, pCheckBoxValue: nullptr, Alpha: true); |
| 665 | |
| 666 | // ***** Hook collisions preview ***** // |
| 667 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Preview" ), FontSize: HeadlineFontSize, |
| 668 | Align: TEXTALIGN_ML, pRect: &RightView, LineSize: HeadlineHeight); |
| 669 | RightView.HSplitTop(Cut: 2 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 670 | |
| 671 | auto DoHookCollision = [this](const vec2 &Pos, const float &Length, const int &Size, const ColorRGBA &Color, const ColorRGBA &TipColor, const bool &Invert) { |
| 672 | ColorRGBA ColorModified = Color; |
| 673 | ColorRGBA TipColorModified = TipColor; |
| 674 | if(Invert) |
| 675 | ColorModified = color_invert(col: ColorModified); |
| 676 | ColorModified = ColorModified.WithAlpha(alpha: (float)g_Config.m_ClHookCollAlpha / 100); |
| 677 | TipColorModified = TipColor.WithMultipliedAlpha(alpha: (float)g_Config.m_ClHookCollAlpha / 100); |
| 678 | Graphics()->TextureClear(); |
| 679 | if(Size > 0) |
| 680 | { |
| 681 | Graphics()->QuadsBegin(); |
| 682 | Graphics()->SetColor(ColorModified); |
| 683 | float LineWidth = 0.5f + (float)(Size - 1) * 0.25f; |
| 684 | IGraphics::CQuadItem QuadItem(Pos.x, Pos.y - LineWidth, Length, LineWidth * 2.f); |
| 685 | Graphics()->QuadsDrawTL(pArray: &QuadItem, Num: 1); |
| 686 | if(TipColor.a > 0.0f) |
| 687 | { |
| 688 | Graphics()->SetColor(TipColorModified); |
| 689 | IGraphics::CQuadItem TipQuadItem(Pos.x + Length, Pos.y - LineWidth, 15.f, LineWidth * 2.f); |
| 690 | Graphics()->QuadsDrawTL(pArray: &TipQuadItem, Num: 1); |
| 691 | } |
| 692 | Graphics()->QuadsEnd(); |
| 693 | } |
| 694 | else |
| 695 | { |
| 696 | Graphics()->LinesBegin(); |
| 697 | Graphics()->SetColor(ColorModified); |
| 698 | IGraphics::CLineItem LineItem(Pos.x, Pos.y, Pos.x + Length, Pos.y); |
| 699 | Graphics()->LinesDraw(pArray: &LineItem, Num: 1); |
| 700 | if(TipColor.a > 0.0f) |
| 701 | { |
| 702 | Graphics()->SetColor(TipColorModified); |
| 703 | IGraphics::CLineItem TipLineItem(Pos.x + Length, Pos.y, Pos.x + Length + 15.f, Pos.y); |
| 704 | Graphics()->LinesDraw(pArray: &TipLineItem, Num: 1); |
| 705 | } |
| 706 | Graphics()->LinesEnd(); |
| 707 | } |
| 708 | }; |
| 709 | |
| 710 | CTeeRenderInfo OwnSkinInfo; |
| 711 | OwnSkinInfo.Apply(pSkin: GameClient()->m_Skins.Find(pName: g_Config.m_ClPlayerSkin)); |
| 712 | OwnSkinInfo.ApplyColors(CustomColoredSkin: g_Config.m_ClPlayerUseCustomColor, ColorBody: g_Config.m_ClPlayerColorBody, ColorFeet: g_Config.m_ClPlayerColorFeet); |
| 713 | OwnSkinInfo.m_Size = 50.0f; |
| 714 | |
| 715 | CTeeRenderInfo DummySkinInfo; |
| 716 | DummySkinInfo.Apply(pSkin: GameClient()->m_Skins.Find(pName: g_Config.m_ClDummySkin)); |
| 717 | DummySkinInfo.ApplyColors(CustomColoredSkin: g_Config.m_ClDummyUseCustomColor, ColorBody: g_Config.m_ClDummyColorBody, ColorFeet: g_Config.m_ClDummyColorFeet); |
| 718 | DummySkinInfo.m_Size = 50.0f; |
| 719 | |
| 720 | vec2 TeeRenderPos, DummyRenderPos; |
| 721 | |
| 722 | const float LineLength = 150.f; |
| 723 | const float LeftMargin = 30.f; |
| 724 | |
| 725 | const int TileScale = 32.0f; |
| 726 | |
| 727 | // Toggled via checkbox later, inverts some previews |
| 728 | static bool s_HookCollPressed = false; |
| 729 | |
| 730 | CUIRect PreviewColl; |
| 731 | |
| 732 | // ***** Unhookable Tile Preview ***** |
| 733 | CUIRect PreviewNoColl; |
| 734 | RightView.HSplitTop(Cut: 50.0f, pTop: &PreviewNoColl, pBottom: &RightView); |
| 735 | RightView.HSplitTop(Cut: 4 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 736 | TeeRenderPos = vec2(PreviewNoColl.x + LeftMargin, PreviewNoColl.y + PreviewNoColl.h / 2.0f); |
| 737 | DoHookCollision(TeeRenderPos, PreviewNoColl.w - LineLength, g_Config.m_ClHookCollSize, color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClHookCollColorNoColl)), ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f), s_HookCollPressed); |
| 738 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &OwnSkinInfo, Emote: 0, Dir: vec2(1.0f, 0.0f), Pos: TeeRenderPos); |
| 739 | |
| 740 | CUIRect NoHookTileRect; |
| 741 | PreviewNoColl.VSplitRight(Cut: LineLength, pLeft: &PreviewNoColl, pRight: &NoHookTileRect); |
| 742 | NoHookTileRect.VSplitLeft(Cut: 50.0f, pLeft: &NoHookTileRect, pRight: nullptr); |
| 743 | NoHookTileRect.Margin(Cut: 10.0f, pOtherRect: &NoHookTileRect); |
| 744 | |
| 745 | // Render unhookable tile |
| 746 | Graphics()->TextureClear(); |
| 747 | Graphics()->TextureSet(Texture: GameClient()->m_MapImages.GetEntities(EntityLayerType: MAP_IMAGE_ENTITY_LAYER_TYPE_ALL_EXCEPT_SWITCH)); |
| 748 | Graphics()->SetColor(r: 1.0f, g: 1.0f, b: 1.0f, a: 1.0f); |
| 749 | RenderMap()->RenderTile(x: NoHookTileRect.x, y: NoHookTileRect.y, Index: TILE_NOHOOK, Scale: TileScale, Color: ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f)); |
| 750 | |
| 751 | // ***** Hookable Tile Preview ***** |
| 752 | RightView.HSplitTop(Cut: 50.0f, pTop: &PreviewColl, pBottom: &RightView); |
| 753 | RightView.HSplitTop(Cut: 4 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 754 | TeeRenderPos = vec2(PreviewColl.x + LeftMargin, PreviewColl.y + PreviewColl.h / 2.0f); |
| 755 | DoHookCollision(TeeRenderPos, PreviewColl.w - LineLength, g_Config.m_ClHookCollSize, color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClHookCollColorHookableColl)), ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f), s_HookCollPressed); |
| 756 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &OwnSkinInfo, Emote: 0, Dir: vec2(1.0f, 0.0f), Pos: TeeRenderPos); |
| 757 | |
| 758 | CUIRect HookTileRect; |
| 759 | PreviewColl.VSplitRight(Cut: LineLength, pLeft: &PreviewColl, pRight: &HookTileRect); |
| 760 | HookTileRect.VSplitLeft(Cut: 50.0f, pLeft: &HookTileRect, pRight: nullptr); |
| 761 | HookTileRect.Margin(Cut: 10.0f, pOtherRect: &HookTileRect); |
| 762 | |
| 763 | // Render hookable tile |
| 764 | Graphics()->TextureClear(); |
| 765 | Graphics()->TextureSet(Texture: GameClient()->m_MapImages.GetEntities(EntityLayerType: MAP_IMAGE_ENTITY_LAYER_TYPE_ALL_EXCEPT_SWITCH)); |
| 766 | Graphics()->SetColor(r: 1.0f, g: 1.0f, b: 1.0f, a: 1.0f); |
| 767 | RenderMap()->RenderTile(x: HookTileRect.x, y: HookTileRect.y, Index: TILE_SOLID, Scale: TileScale, Color: ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f)); |
| 768 | |
| 769 | // ***** Hook Dummy Preview ***** |
| 770 | RightView.HSplitTop(Cut: 50.0f, pTop: &PreviewColl, pBottom: &RightView); |
| 771 | RightView.HSplitTop(Cut: 4 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 772 | TeeRenderPos = vec2(PreviewColl.x + LeftMargin, PreviewColl.y + PreviewColl.h / 2.0f); |
| 773 | DummyRenderPos = vec2(PreviewColl.x + PreviewColl.w - LineLength - 5.f + LeftMargin, PreviewColl.y + PreviewColl.h / 2.0f); |
| 774 | DoHookCollision(TeeRenderPos, PreviewColl.w - LineLength - 15.f, g_Config.m_ClHookCollSize, color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClHookCollColorTeeColl)), ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f), s_HookCollPressed); |
| 775 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &DummySkinInfo, Emote: 0, Dir: vec2(1.0f, 0.0f), Pos: DummyRenderPos); |
| 776 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &OwnSkinInfo, Emote: 0, Dir: vec2(1.0f, 0.0f), Pos: TeeRenderPos); |
| 777 | |
| 778 | // ***** Hook Dummy Reverse Preview ***** |
| 779 | RightView.HSplitTop(Cut: 50.0f, pTop: &PreviewColl, pBottom: &RightView); |
| 780 | RightView.HSplitTop(Cut: 4 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 781 | TeeRenderPos = vec2(PreviewColl.x + LeftMargin, PreviewColl.y + PreviewColl.h / 2.0f); |
| 782 | DummyRenderPos = vec2(PreviewColl.x + PreviewColl.w - LineLength - 5.f + LeftMargin, PreviewColl.y + PreviewColl.h / 2.0f); |
| 783 | DoHookCollision(TeeRenderPos, PreviewColl.w - LineLength - 15.f, g_Config.m_ClHookCollSizeOther, color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClHookCollColorTeeColl)), ColorRGBA(0.0f, 0.0f, 0.0f, 0.0f), false); |
| 784 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &OwnSkinInfo, Emote: 0, Dir: vec2(1.0f, 0.0f), Pos: DummyRenderPos); |
| 785 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &DummySkinInfo, Emote: 0, Dir: vec2(1.0f, 0.0f), Pos: TeeRenderPos); |
| 786 | |
| 787 | // ***** Hook Line Tip Preview ***** |
| 788 | RightView.HSplitTop(Cut: 50.0f, pTop: &PreviewColl, pBottom: &RightView); |
| 789 | RightView.HSplitTop(Cut: 4 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 790 | TeeRenderPos = vec2(PreviewColl.x + LeftMargin, PreviewColl.y + PreviewColl.h / 2.0f); |
| 791 | DoHookCollision(TeeRenderPos, PreviewColl.w - LineLength - 15.f, g_Config.m_ClHookCollSize, color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClHookCollColorNoColl)), color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClHookCollTipColor, true)), s_HookCollPressed); |
| 792 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &OwnSkinInfo, Emote: 0, Dir: vec2(1.0f, 0.0f), Pos: TeeRenderPos); |
| 793 | |
| 794 | // ***** Preview +hookcoll pressed toggle ***** |
| 795 | RightView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &RightView); |
| 796 | if(DoButton_CheckBox(pId: &s_HookCollPressed, pText: Localize(pStr: "Preview 'Hook collisions' being pressed" ), Checked: s_HookCollPressed, pRect: &Button)) |
| 797 | s_HookCollPressed = !s_HookCollPressed; |
| 798 | } |
| 799 | else if(s_CurTab == APPEARANCE_TAB_INFO_MESSAGES) |
| 800 | { |
| 801 | MainView.VSplitMid(pLeft: &LeftView, pRight: &RightView, Spacing: MarginBetweenViews); |
| 802 | |
| 803 | // ***** Info Messages ***** // |
| 804 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Info Messages" ), FontSize: HeadlineFontSize, |
| 805 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 806 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 807 | |
| 808 | // General info messages settings |
| 809 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 810 | if(DoButton_CheckBox(pId: &g_Config.m_ClShowKillMessages, pText: Localize(pStr: "Show kill messages" ), Checked: g_Config.m_ClShowKillMessages, pRect: &Button)) |
| 811 | { |
| 812 | g_Config.m_ClShowKillMessages ^= 1; |
| 813 | } |
| 814 | |
| 815 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 816 | if(DoButton_CheckBox(pId: &g_Config.m_ClShowFinishMessages, pText: Localize(pStr: "Show finish messages" ), Checked: g_Config.m_ClShowFinishMessages, pRect: &Button)) |
| 817 | { |
| 818 | g_Config.m_ClShowFinishMessages ^= 1; |
| 819 | } |
| 820 | |
| 821 | static CButtonContainer s_KillMessageNormalColorId, s_KillMessageHighlightColorId; |
| 822 | DoLine_ColorPicker(pResetId: &s_KillMessageNormalColorId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Normal Color" ), pColorValue: &g_Config.m_ClKillMessageNormalColor, DefaultColor: ColorRGBA(1.0f, 1.0f, 1.0f), CheckBoxSpacing: false); |
| 823 | DoLine_ColorPicker(pResetId: &s_KillMessageHighlightColorId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Highlight Color" ), pColorValue: &g_Config.m_ClKillMessageHighlightColor, DefaultColor: ColorRGBA(1.0f, 1.0f, 1.0f), CheckBoxSpacing: false); |
| 824 | } |
| 825 | else if(s_CurTab == APPEARANCE_TAB_LASER) |
| 826 | { |
| 827 | MainView.VSplitMid(pLeft: &LeftView, pRight: &RightView, Spacing: MarginBetweenViews); |
| 828 | |
| 829 | // ***** Weapons ***** // |
| 830 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Weapons" ), FontSize: HeadlineFontSize, |
| 831 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 832 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 833 | |
| 834 | // General weapon laser settings |
| 835 | static CButtonContainer s_LaserRifleOutResetId, s_LaserRifleInResetId, s_LaserShotgunOutResetId, s_LaserShotgunInResetId; |
| 836 | |
| 837 | ColorHSLA LaserRifleOutlineColor = DoLine_ColorPicker(pResetId: &s_LaserRifleOutResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Rifle Laser Outline Color" ), pColorValue: &g_Config.m_ClLaserRifleOutlineColor, DefaultColor: ColorRGBA(0.074402f, 0.074402f, 0.247166f, 1.0f), CheckBoxSpacing: false); |
| 838 | ColorHSLA LaserRifleInnerColor = DoLine_ColorPicker(pResetId: &s_LaserRifleInResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Rifle Laser Inner Color" ), pColorValue: &g_Config.m_ClLaserRifleInnerColor, DefaultColor: ColorRGBA(0.498039f, 0.498039f, 1.0f, 1.0f), CheckBoxSpacing: false); |
| 839 | ColorHSLA LaserShotgunOutlineColor = DoLine_ColorPicker(pResetId: &s_LaserShotgunOutResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Shotgun Laser Outline Color" ), pColorValue: &g_Config.m_ClLaserShotgunOutlineColor, DefaultColor: ColorRGBA(0.125490f, 0.098039f, 0.043137f, 1.0f), CheckBoxSpacing: false); |
| 840 | ColorHSLA LaserShotgunInnerColor = DoLine_ColorPicker(pResetId: &s_LaserShotgunInResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Shotgun Laser Inner Color" ), pColorValue: &g_Config.m_ClLaserShotgunInnerColor, DefaultColor: ColorRGBA(0.570588f, 0.417647f, 0.252941f, 1.0f), CheckBoxSpacing: false); |
| 841 | |
| 842 | // ***** Entities ***** // |
| 843 | LeftView.HSplitTop(Cut: 10.0f, pTop: nullptr, pBottom: &LeftView); |
| 844 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Entities" ), FontSize: HeadlineFontSize, |
| 845 | Align: TEXTALIGN_ML, pRect: &LeftView, LineSize: HeadlineHeight); |
| 846 | LeftView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 847 | |
| 848 | // General entity laser settings |
| 849 | static CButtonContainer s_LaserDoorOutResetId, s_LaserDoorInResetId, s_LaserFreezeOutResetId, s_LaserFreezeInResetId, s_LaserDraggerOutResetId, s_LaserDraggerInResetId; |
| 850 | |
| 851 | ColorHSLA LaserDoorOutlineColor = DoLine_ColorPicker(pResetId: &s_LaserDoorOutResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Door Laser Outline Color" ), pColorValue: &g_Config.m_ClLaserDoorOutlineColor, DefaultColor: ColorRGBA(0.0f, 0.131372f, 0.096078f, 1.0f), CheckBoxSpacing: false); |
| 852 | ColorHSLA LaserDoorInnerColor = DoLine_ColorPicker(pResetId: &s_LaserDoorInResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Door Laser Inner Color" ), pColorValue: &g_Config.m_ClLaserDoorInnerColor, DefaultColor: ColorRGBA(0.262745f, 0.760784f, 0.639215f, 1.0f), CheckBoxSpacing: false); |
| 853 | ColorHSLA LaserFreezeOutlineColor = DoLine_ColorPicker(pResetId: &s_LaserFreezeOutResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Freeze Laser Outline Color" ), pColorValue: &g_Config.m_ClLaserFreezeOutlineColor, DefaultColor: ColorRGBA(0.131372f, 0.123529f, 0.182352f, 1.0f), CheckBoxSpacing: false); |
| 854 | ColorHSLA LaserFreezeInnerColor = DoLine_ColorPicker(pResetId: &s_LaserFreezeInResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Freeze Laser Inner Color" ), pColorValue: &g_Config.m_ClLaserFreezeInnerColor, DefaultColor: ColorRGBA(0.482352f, 0.443137f, 0.564705f, 1.0f), CheckBoxSpacing: false); |
| 855 | ColorHSLA LaserDraggerOutlineColor = DoLine_ColorPicker(pResetId: &s_LaserDraggerOutResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Dragger Outline Color" ), pColorValue: &g_Config.m_ClLaserDraggerOutlineColor, DefaultColor: ColorRGBA(0.1640625f, 0.015625f, 0.015625f, 1.0f), CheckBoxSpacing: false); |
| 856 | ColorHSLA LaserDraggerInnerColor = DoLine_ColorPicker(pResetId: &s_LaserDraggerInResetId, LineSize: ColorPickerLineSize, LabelSize: ColorPickerLabelSize, BottomMargin: ColorPickerLineSpacing, pMainRect: &LeftView, pText: Localize(pStr: "Dragger Inner Color" ), pColorValue: &g_Config.m_ClLaserDraggerInnerColor, DefaultColor: ColorRGBA(.8666666f, .3725490f, .3725490f, 1.0f), CheckBoxSpacing: false); |
| 857 | |
| 858 | static CButtonContainer s_AllToRifleResetId, s_AllToDefaultResetId; |
| 859 | |
| 860 | LeftView.HSplitTop(Cut: 4 * MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 861 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 862 | if(DoButton_Menu(pButtonContainer: &s_AllToRifleResetId, pText: Localize(pStr: "Set all to Rifle" ), Checked: 0, pRect: &Button)) |
| 863 | { |
| 864 | g_Config.m_ClLaserShotgunOutlineColor = g_Config.m_ClLaserRifleOutlineColor; |
| 865 | g_Config.m_ClLaserShotgunInnerColor = g_Config.m_ClLaserRifleInnerColor; |
| 866 | g_Config.m_ClLaserDoorOutlineColor = g_Config.m_ClLaserRifleOutlineColor; |
| 867 | g_Config.m_ClLaserDoorInnerColor = g_Config.m_ClLaserRifleInnerColor; |
| 868 | g_Config.m_ClLaserFreezeOutlineColor = g_Config.m_ClLaserRifleOutlineColor; |
| 869 | g_Config.m_ClLaserFreezeInnerColor = g_Config.m_ClLaserRifleInnerColor; |
| 870 | g_Config.m_ClLaserDraggerOutlineColor = g_Config.m_ClLaserRifleOutlineColor; |
| 871 | g_Config.m_ClLaserDraggerInnerColor = g_Config.m_ClLaserRifleInnerColor; |
| 872 | } |
| 873 | |
| 874 | // values taken from the CL commands |
| 875 | LeftView.HSplitTop(Cut: 2 * MarginSmall, pTop: nullptr, pBottom: &LeftView); |
| 876 | LeftView.HSplitTop(Cut: LineSize, pTop: &Button, pBottom: &LeftView); |
| 877 | if(DoButton_Menu(pButtonContainer: &s_AllToDefaultResetId, pText: Localize(pStr: "Reset to defaults" ), Checked: 0, pRect: &Button)) |
| 878 | { |
| 879 | g_Config.m_ClLaserRifleOutlineColor = 11176233; |
| 880 | g_Config.m_ClLaserRifleInnerColor = 11206591; |
| 881 | g_Config.m_ClLaserShotgunOutlineColor = 1866773; |
| 882 | g_Config.m_ClLaserShotgunInnerColor = 1467241; |
| 883 | g_Config.m_ClLaserDoorOutlineColor = 7667473; |
| 884 | g_Config.m_ClLaserDoorInnerColor = 7701379; |
| 885 | g_Config.m_ClLaserFreezeOutlineColor = 11613223; |
| 886 | g_Config.m_ClLaserFreezeInnerColor = 12001153; |
| 887 | g_Config.m_ClLaserDraggerOutlineColor = 57618; |
| 888 | g_Config.m_ClLaserDraggerInnerColor = 42398; |
| 889 | } |
| 890 | |
| 891 | // ***** Laser Preview ***** // |
| 892 | Ui()->DoLabel_AutoLineSize(pText: Localize(pStr: "Preview" ), FontSize: HeadlineFontSize, |
| 893 | Align: TEXTALIGN_ML, pRect: &RightView, LineSize: HeadlineHeight); |
| 894 | RightView.HSplitTop(Cut: MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 895 | |
| 896 | const float LaserPreviewHeight = 60.0f; |
| 897 | CUIRect LaserPreview; |
| 898 | RightView.HSplitTop(Cut: LaserPreviewHeight, pTop: &LaserPreview, pBottom: &RightView); |
| 899 | RightView.HSplitTop(Cut: 2 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 900 | DoLaserPreview(pRect: &LaserPreview, OutlineColor: LaserRifleOutlineColor, InnerColor: LaserRifleInnerColor, LaserType: LASERTYPE_RIFLE); |
| 901 | |
| 902 | RightView.HSplitTop(Cut: LaserPreviewHeight, pTop: &LaserPreview, pBottom: &RightView); |
| 903 | RightView.HSplitTop(Cut: 2 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 904 | DoLaserPreview(pRect: &LaserPreview, OutlineColor: LaserShotgunOutlineColor, InnerColor: LaserShotgunInnerColor, LaserType: LASERTYPE_SHOTGUN); |
| 905 | |
| 906 | RightView.HSplitTop(Cut: LaserPreviewHeight, pTop: &LaserPreview, pBottom: &RightView); |
| 907 | RightView.HSplitTop(Cut: 2 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 908 | DoLaserPreview(pRect: &LaserPreview, OutlineColor: LaserDoorOutlineColor, InnerColor: LaserDoorInnerColor, LaserType: LASERTYPE_DOOR); |
| 909 | |
| 910 | RightView.HSplitTop(Cut: LaserPreviewHeight, pTop: &LaserPreview, pBottom: &RightView); |
| 911 | RightView.HSplitTop(Cut: 2 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 912 | DoLaserPreview(pRect: &LaserPreview, OutlineColor: LaserFreezeOutlineColor, InnerColor: LaserFreezeInnerColor, LaserType: LASERTYPE_FREEZE); |
| 913 | |
| 914 | RightView.HSplitTop(Cut: LaserPreviewHeight, pTop: &LaserPreview, pBottom: &RightView); |
| 915 | RightView.HSplitTop(Cut: 2 * MarginSmall, pTop: nullptr, pBottom: &RightView); |
| 916 | DoLaserPreview(pRect: &LaserPreview, OutlineColor: LaserDraggerOutlineColor, InnerColor: LaserDraggerInnerColor, LaserType: LASERTYPE_DRAGGER); |
| 917 | } |
| 918 | } |
| 919 | |
| 920 | void CMenus::(const CUIRect *pRect, const ColorHSLA LaserOutlineColor, const ColorHSLA LaserInnerColor, const int LaserType) |
| 921 | { |
| 922 | CUIRect Section = *pRect; |
| 923 | vec2 From = vec2(Section.x + 30.0f, Section.y + Section.h / 2.0f); |
| 924 | vec2 Pos = vec2(Section.x + Section.w - 20.0f, Section.y + Section.h / 2.0f); |
| 925 | |
| 926 | const ColorRGBA OuterColor = color_cast<ColorRGBA>(hsl: ColorHSLA(LaserOutlineColor)); |
| 927 | const ColorRGBA InnerColor = color_cast<ColorRGBA>(hsl: ColorHSLA(LaserInnerColor)); |
| 928 | const float TicksHead = Client()->GlobalTime() * Client()->GameTickSpeed(); |
| 929 | |
| 930 | // TicksBody = 4.0 for less laser width for weapon alignment |
| 931 | GameClient()->m_Items.RenderLaser(From, Pos, OuterColor, InnerColor, TicksBody: 4.0f, TicksHead, Type: LaserType); |
| 932 | |
| 933 | switch(LaserType) |
| 934 | { |
| 935 | case LASERTYPE_RIFLE: |
| 936 | Graphics()->TextureSet(Texture: GameClient()->m_GameSkin.m_SpriteWeaponLaser); |
| 937 | Graphics()->SelectSprite(Id: SPRITE_WEAPON_LASER_BODY); |
| 938 | Graphics()->QuadsBegin(); |
| 939 | Graphics()->QuadsSetSubset(TopLeftU: 0, TopLeftV: 0, BottomRightU: 1, BottomRightV: 1); |
| 940 | Graphics()->DrawSprite(x: Section.x + 30.0f, y: Section.y + Section.h / 2.0f, Size: 60.0f); |
| 941 | Graphics()->QuadsEnd(); |
| 942 | break; |
| 943 | case LASERTYPE_SHOTGUN: |
| 944 | Graphics()->TextureSet(Texture: GameClient()->m_GameSkin.m_SpriteWeaponShotgun); |
| 945 | Graphics()->SelectSprite(Id: SPRITE_WEAPON_SHOTGUN_BODY); |
| 946 | Graphics()->QuadsBegin(); |
| 947 | Graphics()->QuadsSetSubset(TopLeftU: 0, TopLeftV: 0, BottomRightU: 1, BottomRightV: 1); |
| 948 | Graphics()->DrawSprite(x: Section.x + 30.0f, y: Section.y + Section.h / 2.0f, Size: 60.0f); |
| 949 | Graphics()->QuadsEnd(); |
| 950 | break; |
| 951 | case LASERTYPE_DRAGGER: |
| 952 | { |
| 953 | CTeeRenderInfo TeeRenderInfo; |
| 954 | TeeRenderInfo.Apply(pSkin: GameClient()->m_Skins.Find(pName: g_Config.m_ClPlayerSkin)); |
| 955 | TeeRenderInfo.ApplyColors(CustomColoredSkin: g_Config.m_ClPlayerUseCustomColor, ColorBody: g_Config.m_ClPlayerColorBody, ColorFeet: g_Config.m_ClPlayerColorFeet); |
| 956 | TeeRenderInfo.m_Size = 64.0f; |
| 957 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &TeeRenderInfo, Emote: EMOTE_NORMAL, Dir: vec2(-1, 0), Pos); |
| 958 | break; |
| 959 | } |
| 960 | case LASERTYPE_FREEZE: |
| 961 | { |
| 962 | CTeeRenderInfo TeeRenderInfo; |
| 963 | if(g_Config.m_ClShowNinja) |
| 964 | TeeRenderInfo.Apply(pSkin: GameClient()->m_Skins.Find(pName: "x_ninja" )); |
| 965 | else |
| 966 | TeeRenderInfo.Apply(pSkin: GameClient()->m_Skins.Find(pName: g_Config.m_ClPlayerSkin)); |
| 967 | TeeRenderInfo.m_TeeRenderFlags = TEE_EFFECT_FROZEN; |
| 968 | TeeRenderInfo.m_Size = 64.0f; |
| 969 | TeeRenderInfo.m_ColorBody = ColorRGBA(1, 1, 1); |
| 970 | TeeRenderInfo.m_ColorFeet = ColorRGBA(1, 1, 1); |
| 971 | RenderTools()->RenderTee(pAnim: CAnimState::GetIdle(), pInfo: &TeeRenderInfo, Emote: EMOTE_PAIN, Dir: vec2(1, 0), Pos: From); |
| 972 | GameClient()->m_Effects.FreezingFlakes(Pos: From, Size: vec2(32, 32), Alpha: 1.0f); |
| 973 | break; |
| 974 | } |
| 975 | default: |
| 976 | GameClient()->m_Items.RenderLaser(From, Pos: From, OuterColor, InnerColor, TicksBody: 4.0f, TicksHead, Type: LaserType); |
| 977 | } |
| 978 | } |
| 979 | |