diff --git a/config/FutilityChat.ini b/config/FutilityChat.ini new file mode 100644 index 0000000..4c26d6e --- /dev/null +++ b/config/FutilityChat.ini @@ -0,0 +1,31 @@ +[default FutilityChat] +; This feature allows to configure color of text chat messages. +autoEnable=true +; How to color text chat messages? +; 1. `CCS_DoNothing` - do not change color in any way; +; 2. `CCS_TeamColorForced` - force players' team colors for +; their messages; +; 3. `CCS_ConfigColorForced` - force `configuredColor` value for +; players' messages; +; 4. `CCS_TeamColorCustom` - use players' team colors for +; their messages by default, but allow to change color with formatted +; tags (e.g. "Stop right there, {$crimson criminal} scum!"); +; 5. `CCS_ConfigColorCustom` - use `configuredColor` value for +; messages by default, but allow to change color with formatted +; tags (e.g. "Stop right there, {$crimson criminal} scum!"); +; Default is `CCS_DoNothing`, corresponding to vanilla behaviour. +colorSetting=CCS_DoNothing +; Color that will be used if either of `CCS_ConfigColorForced` or +; `CCS_ConfigColorCustom` options were used in `colorSetting`. +; Default value is white: (R=255,G=255,B=255,A=255), +; has no vanilla equivalent. +configuredColor=(R=255,G=255,B=255,A=255) +; Allows to modify team color's value for the chat messages +; (if either of `CCS_TeamColorForced` or `CCS_TeamColorCustom` options +; were used) to be lighter or darker. +; This value is clamped between -1 and 1. +; * `0` means using the same color; +; * range (0; 1) - gives you lighter colors (`1` being white); +; * range (-1; 0) - gives you darker colors (`-1` being black); +; Default value is `0.6`, has no vanilla equivalent. +teamColorModifier=0.6 \ No newline at end of file diff --git a/sources/Features/FutileChat/FutilityChat.uc b/sources/Features/FutileChat/FutilityChat.uc new file mode 100644 index 0000000..1d64110 --- /dev/null +++ b/sources/Features/FutileChat/FutilityChat.uc @@ -0,0 +1,92 @@ +/** + * Config object for `FutilityChat_Feature`. + * Copyright 2022 Anton Tarasenko + *------------------------------------------------------------------------------ + * This file is part of Acedia. + * + * Acedia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + * + * Acedia is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Acedia. If not, see . + */ +class FutilityChat extends FeatureConfig + perobjectconfig + config(FutilityChat); + +enum ChatColorSetting +{ + CCS_DoNothing, + CCS_TeamColorForced, + CCS_ConfigColorForced, + CCS_TeamColorCustom, + CCS_ConfigColorCustom +}; + +var public config ChatColorSetting colorSetting; +var public config Color configuredColor; +var public config float teamColorModifier; + +protected function AssociativeArray ToData() +{ + local AssociativeArray data; + data = __().collections.EmptyAssociativeArray(); + data.SetItem( P("colorSetting"), + _.text.FromString(string(colorSetting)), true); + data.SetItem(P("configuredColor"), _.color.ToText(configuredColor), true); + data.SetFloat(P("teamColorModifier"), teamColorModifier, true); + return data; +} + +protected function FromData(AssociativeArray source) +{ + if (source == none) { + return; + } + colorSetting = ColorSettingFromText(source.GetText(P("colorSetting"))); + _.color.Parse(source.GetText(P("configuredColor")), configuredColor); + teamColorModifier = source.GetFloat(P("teamColorModifier"), 0.5); +} + +private function ChatColorSetting ColorSettingFromText( + Text permissions) +{ + if (permissions == none) { + return CCS_DoNothing; + } + if (permissions.EndsWith(P("TeamColorForced"), SCASE_INSENSITIVE)) { + return CCS_TeamColorForced; + } + if (permissions.EndsWith(P("ConfigColorForced"), SCASE_INSENSITIVE)) { + return CCS_ConfigColorForced; + } + if (permissions.EndsWith(P("TeamColorCustom"), SCASE_INSENSITIVE)) { + return CCS_TeamColorCustom; + } + if (permissions.EndsWith(P("ConfigColorCustom"), SCASE_INSENSITIVE)) { + return CCS_ConfigColorCustom; + } + return CCS_DoNothing; +} + +protected function DefaultIt() +{; + colorSetting = CCS_DoNothing; + configuredColor = _.color.RGB(255, 255, 255); + teamColorModifier = 0.6; +} + +defaultproperties +{ + configName = "FutilityChat" + colorSetting = CCS_DoNothing + configuredColor = (R=255,G=255,B=255,A=255) + teamColorModifier = 0.6 +} \ No newline at end of file diff --git a/sources/Features/FutileChat/FutilityChat_Feature.uc b/sources/Features/FutileChat/FutilityChat_Feature.uc new file mode 100644 index 0000000..738feb2 --- /dev/null +++ b/sources/Features/FutileChat/FutilityChat_Feature.uc @@ -0,0 +1,166 @@ +/** + * This feature allows to configure color of text chat messages. + * Copyright 2022 Anton Tarasenko + *------------------------------------------------------------------------------ + * This file is part of Acedia. + * + * Acedia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License, or + * (at your option) any later version. + * + * Acedia is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Acedia. If not, see . + */ +class FutilityChat_Feature extends Feature + dependson(FutilityChat); + +// How to color text chat messages? +// 1. `CCS_DoNothing` - do not change color in any way; +// 2. `CCS_TeamColorForced` - force players' team colors for +// their messages; +// 3. `CCS_ConfigColorForced` - force `configuredColor` value for +// players' messages; +// 4. `CCS_TeamColorCustom` - use players' team colors for +// their messages by default, but allow to change color with formatted +// tags (e.g. "Stop right there, {$crimson criminal} scum!"); +// 5. `CCS_ConfigColorCustom` - use `configuredColor` value for +// messages by default, but allow to change color with formatted +// tags (e.g. "Stop right there, {$crimson criminal} scum!"); +// Default is `CCS_DoNothing`, corresponding to vanilla behaviour. +var private /*config*/ FutilityChat.ChatColorSetting colorSetting; +// Color that will be used if either of `CCS_ConfigColorForced` or +// `CCS_ConfigColorCustom` options were used in `colorSetting`. +// Default value is white: (R=255,G=255,B=255,A=255), +// has no vanilla equivalent. +var private /*config*/ Color configuredColor; +// Allows to modify team color's value for the chat messages +// (if either of `CCS_TeamColorForced` or `CCS_TeamColorCustom` options +// were used) to be lighter or darker. +// This value is clamped between -1 and 1. +// * `0` means using the same color; +// * range (0; 1) - gives you lighter colors (`1` being white); +// * range (-1; 0) - gives you darker colors (`-1` being black); +// Default value is `0.6`, has no vanilla equivalent. +var private /*config*/ float teamColorModifier; + +// Keep track of whether we connected to necessary signals, so that we can +// connect to them or disconnect from them once setting get updated +var private bool connectedToSignal; + +protected function OnDisabled() +{ + if (connectedToSignal) + { + connectedToSignal = false; + _.chat.OnMessage(self).Disconnect(); + } +} + +protected function SwapConfig(FeatureConfig config) +{ + local bool configRequiresSignal; + local FutilityChat newConfig; + newConfig = FutilityChat(config); + if (newConfig == none) { + return; + } + colorSetting = newConfig.colorSetting; + configuredColor = newConfig.configuredColor; + teamColorModifier = newConfig.teamColorModifier; + configRequiresSignal = (colorSetting != CCS_DoNothing); + // Enable or disable censoring if `IsAnyCensoringEnabled()`'s response + // has changed. + if (!connectedToSignal && configRequiresSignal) + { + connectedToSignal = true; + _.chat.OnMessage(self).connect = ReformatChatMessage; + } + if (connectedToSignal && !configRequiresSignal) + { + connectedToSignal = false; + _.chat.OnMessage(self).Disconnect(); + } +} + +private function bool ReformatChatMessage( + EPlayer sender, + MutableText message, + bool teamMessage) +{ + local int i; + local MutableText messageCopy; + local Text.Character nextCharacter; + local Text.Formatting defaultFormatting; + if (sender == none) return true; + if (message == none) return true; + if (colorSetting == CCS_DoNothing) return true; + + defaultFormatting.isColored = true; + if ( colorSetting == CCS_TeamColorForced + || colorSetting == CCS_TeamColorCustom) + { + defaultFormatting.color = ModColor(sender.GetTeamColor()); + } + else { + defaultFormatting.color = configuredColor; + } + if (message.StartsWith(P("|"))) { + messageCopy = message.MutableCopy(1); + } + else if ( colorSetting == CCS_TeamColorForced + || colorSetting == CCS_ConfigColorForced) + { + messageCopy = message.MutableCopy(); + } + else + { + messageCopy = _.text.Empty(); + messageCopy.AppendFormatted(message); + } + message.Clear(); + for (i = 0; i < messageCopy.GetLength(); i += 1) + { + nextCharacter = messageCopy.GetCharacter(i); + if (!nextCharacter.formatting.isColored) { + nextCharacter.formatting = defaultFormatting; + } + message.AppendCharacter(nextCharacter); + } + _.memory.Free(messageCopy); + return true; +} + +private function Color ModColor(Color inputColor) +{ + local Color mixColor; + local Color outputColor; + local float clampedModifier; + if (Abs(teamColorModifier) < 0.001) { + return inputColor; + } + clampedModifier = FClamp(teamColorModifier, -1.0, 1.0); + if (clampedModifier > 0) { + mixColor = _.color.White; + } + else + { + mixColor = _.color.Black; + clampedModifier *= -1.0; + } + outputColor.R = Lerp(clampedModifier, inputColor.R, mixColor.R); + outputColor.G = Lerp(clampedModifier, inputColor.G, mixColor.G); + outputColor.B = Lerp(clampedModifier, inputColor.B, mixColor.B); + outputColor.A = inputColor.A; + return outputColor; +} + +defaultproperties +{ + configClass = class'FutilityChat' +} \ No newline at end of file diff --git a/sources/Manifest.uc b/sources/Manifest.uc index e95f9d9..0f174cd 100644 --- a/sources/Manifest.uc +++ b/sources/Manifest.uc @@ -1,6 +1,6 @@ /** * Manifest is meant to describe contents of the Acedia's package. - * Copyright 2021 Anton Tarasenko + * Copyright 2021 - 2022 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * @@ -24,4 +24,5 @@ defaultproperties { features(0) = class'Futility_Feature' features(1) = class'FutilityNicknames_Feature' + features(2) = class'FutilityChat_Feature' } \ No newline at end of file