diff --git a/config/FutilityChat.ini b/config/FutilityChat.ini index 4c26d6e..0321975 100644 --- a/config/FutilityChat.ini +++ b/config/FutilityChat.ini @@ -1,31 +1,34 @@ [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. +;= 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. +;= 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. +;= 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/config/FutilityNicknames.ini b/config/FutilityNicknames.ini index f3cf732..fb43d73 100644 --- a/config/FutilityNicknames.ini +++ b/config/FutilityNicknames.ini @@ -1,64 +1,67 @@ [default FutilityNicknames] -; This feature allows to configure nickname limitations for the server. -; It allows you to customize vanilla limitations for nickname length and -; color with those of your own design. Enabling this feature overwrites -; default behaviour. +;= This feature allows to configure nickname limitations for the server. +;= It allows you to customize vanilla limitations for nickname length and +;= color with those of your own design. Enabling this feature overwrites +;= default behaviour. autoEnable=true -; How to treat whitespace characters inside players' nicknames. -; * `NSA_DoNothing` - does nothing, leaving whitespaces as they are; -; * `NSA_Trim` - removes leading and trailing whitespaces for nicknames; -; * `NSA_Simplify` - removes leading and trailing whitespaces -; for nicknames, also reducing a sequence of whitespaces inside -; nickname to a single space, e.g. "my nick" becomes "my nick". -; Default is `NSA_DoNothing`, same as on vanilla. +;= How to treat whitespace characters inside players' nicknames. +;= +;= * `NSA_DoNothing` - does nothing, leaving whitespaces as they are;= +;= * `NSA_Trim` - removes leading and trailing whitespaces for nicknames;= +;= * `NSA_Simplify` - removes leading and trailing whitespaces +;= for nicknames, also reducing a sequence of whitespaces inside +;= nickname to a single space, e.g. "my nick" becomes "my nick". +;= +;= Default is `NSA_DoNothing`, same as on vanilla. spacesAction=NSA_DoNothing -; How to treat colored nicknames. -; * `NCP_ForbidColor` - completely strips down any color from nicknames; -; * `NCP_ForceTeamColor` - forces all nicknames to have player's current -; team's color; -; * `NCP_ForceSingleColor` - allows nickname to be painted with a single -; color (sets nickname's color to that of the first character); -; * `NCP_AllowAnyColor` - allows nickname to be colored in any way player -; wants. -; Default is `NCP_ForbidColor`, same as on vanilla. +;= How to treat colored nicknames. +;= * `NCP_ForbidColor` - completely strips down any color from nicknames;= +;= * `NCP_ForceTeamColor` - forces all nicknames to have player's current +;= team's color;= +;= * `NCP_ForceSingleColor` - allows nickname to be painted with a single +;= color (sets nickname's color to that of the first character);= +;= * `NCP_AllowAnyColor` - allows nickname to be colored in any way player +;= wants. +;= Default is `NCP_ForbidColor`, same as on vanilla. colorPermissions=NCP_ForbidColor -; Set this to `true` if you wish to replace all whitespace characters with -; underscores and `false` to leave them as is. -; Default is `true`, same as on vanilla. However there is one difference: -; Futility replaces all whitespace characters (including tabulations, -; non-breaking spaces, etc.) instead of only ' '. +;= Set this to `true` if you wish to replace all whitespace characters with +;= underscores and `false` to leave them as is. +;= Default is `true`, same as on vanilla. However there is one difference: +;= Futility replaces all whitespace characters (including tabulations, +;= non-breaking spaces, etc.) instead of only ' '. replaceSpacesWithUnderscores=true -; Set this to `true` to remove single 'quotation marks' and `false` to -; leave them. Default is `false`, same as on vanilla. +;= Set this to `true` to remove single 'quotation marks' and `false` to +;= leave them. Default is `false`, same as on vanilla. removeSingleQuotationMarks=false -; Set this to `true` to remove dobule 'quotation marks' and `false` to -; leave them. Default is `true`, same as on vanilla. +;= Set this to `true` to remove dobule 'quotation marks' and `false` to +;= leave them. Default is `true`, same as on vanilla. removeDoubleQuotationMarks=true -; Max allowed nickname length. Negative values disable any length limits. -; -; NOTE #1: `0` resets all nicknames to be empty and, -; if `correctEmptyNicknames` is set to `true`, they will be replaced with -; one of the fallback nicknames -; (see `correctEmptyNicknames` and `fallbackNickname`). -; NOTE #2: Because of how color swapping in vanilla Killing Floor works, -; every color swap makes text count as being about 4 characters longer. -; So if one uses too many colors in the nickname, for drawing functions -; it will appear to be longer than it actually is and it *will* mess up -; UI. Unless you are using custom HUD it is recommended to keep this value -; at default `20` and forbid colored nicknames -; (by setting `colorPermissions=NCP_ForbidColor`). Or to allow only one -; color (by setting `colorPermissions=NCP_ForceSingleColor` or -; `colorPermissions=NCP_ForceTeamColor`) and reducing `maxNicknameLength` -; to `16` (20 characters - 4 for color swap). -; If you want to increase the limit above that, you can also do your -; own research by testing nicknames of various length on -; screen resolutions you care about. +;= Max allowed nickname length. Negative values disable any length limits. +;= +;= NOTE #1: `0` resets all nicknames to be empty and, +;= if `correctEmptyNicknames` is set to `true`, they will be replaced with +;= one of the fallback nicknames +;= (see `correctEmptyNicknames` and `fallbackNickname`). +;= +;= NOTE #2: Because of how color swapping in vanilla Killing Floor works, +;= every color swap makes text count as being about 4 characters longer. +;= So if one uses too many colors in the nickname, for drawing functions +;= it will appear to be longer than it actually is and it *will* mess up +;= UI. Unless you are using custom HUD it is recommended to keep this value +;= at default `20` and forbid colored nicknames +;= (by setting `colorPermissions=NCP_ForbidColor`). Or to allow only one +;= color (by setting `colorPermissions=NCP_ForceSingleColor` or +;= `colorPermissions=NCP_ForceTeamColor`) and reducing `maxNicknameLength` +;= to `16` (20 characters - 4 for color swap). +;= If you want to increase the limit above that, you can also do your +;= own research by testing nicknames of various length on +;= screen resolutions you care about. maxNicknameLength=20 -; Should we replace empty player nicknames with a random fallback nickname -; (defined in `fallbackNickname` array)? +;= Should we replace empty player nicknames with a random fallback nickname +;= (defined in `fallbackNickname` array)? correctEmptyNicknames=true -; Array of fallback nicknames that will be used to replace any empty nicknames -; if `correctEmptyNicknames` is set to `true`. +;= Array of fallback nicknames that will be used to replace any empty nicknames +;= if `correctEmptyNicknames` is set to `true`. fallbackNickname="Fresh Meat" fallbackNickname="Rotten Meat" fallbackNickname="Troll Meat" @@ -70,20 +73,21 @@ fallbackNickname="Boar Meat" fallbackNickname="Walrus Meat" fallbackNickname="Bug Meat" fallbackNickname="Horse Meat" -; Guaranteed order of applying changes (only chosen ones) is as following: -; 1. Trim/simplify spaces; -; 2. Remove single and double quotation marks; -; 3. Enforce max limit of nickname's length; -; 4. Replace empty nickname with fallback nickname (no further changes -; will be applied to fallback nickname in that case); -; 5. Enforce color limitation; -; 6. Replace remaining whitespaces with underscores. -; -; NOTE #1: as follows from the instruction described above, no changes will -; ever be applied to fallback nicknames (unless player's nickname -; coincides with one by pure accident). -; NOTE #2: whitespaces inside steam nicknames are converted into underscores -; before they are passed into the game and this is a change Futility -; cannot currently abort. -; Therefore all changes relevant to whitespaces inside nicknames will only -; be applied to in-game changes. \ No newline at end of file +;= Guaranteed order of applying changes (only chosen ones) is as following: +;= 1. Trim/simplify spaces;= +;= 2. Remove single and double quotation marks;= +;= 3. Enforce max limit of nickname's length;= +;= 4. Replace empty nickname with fallback nickname (no further changes +;= will be applied to fallback nickname in that case);= +;= 5. Enforce color limitation;= +;= 6. Replace remaining whitespaces with underscores. +;= +;= NOTE #1: as follows from the instruction described above, no changes will +;= ever be applied to fallback nicknames (unless player's nickname +;= coincides with one by pure accident). +;= +;= NOTE #2: whitespaces inside steam nicknames are converted into underscores +;= before they are passed into the game and this is a change Futility +;= cannot currently abort. +;= Therefore all changes relevant to whitespaces inside nicknames will only +;= be applied to in-game changes. \ No newline at end of file diff --git a/sources/Commands/ACommandFeature.uc b/sources/Commands/ACommandFeature.uc index fcae759..044f3ef 100644 --- a/sources/Commands/ACommandFeature.uc +++ b/sources/Commands/ACommandFeature.uc @@ -20,28 +20,25 @@ class ACommandFeature extends Command dependson(PendingConfigsTool); -var private class selectedFeatureClass; -var private Text selectedConfigName; +var private class selectedFeatureClass; +var private Text selectedFeatureName; +var private Text selectedConfigName; -var private PendingConfigsTool pendingConfigs; -var private ACommandFeature_Announcer announcer; +var private PendingConfigsTool pendingConfigs; +var private ACommandFeature_Announcer announcer; -protected function Constructor() -{ - pendingConfigs = - PendingConfigsTool(_.memory.Allocate(class'PendingConfigsTool')); +protected function Constructor() { + pendingConfigs = PendingConfigsTool(_.memory.Allocate(class'PendingConfigsTool')); super.Constructor(); } -protected function Finalizer() -{ +protected function Finalizer() { _.memory.Free(announcer); _.memory.Free(pendingConfigs); super.Finalizer(); } -protected function BuildData(CommandDataBuilder builder) -{ +protected function BuildData(CommandDataBuilder builder) { builder.Group(P("admin")); builder.Summary(P("Managing features.")); builder.Describe(P("Command for managing features and their configs.")); @@ -108,126 +105,109 @@ protected function Executed( local bool saveFlag, allFlag; announcer.Setup(none, instigator, othersConsole); - saveFlag = arguments.options.HasKey(P("save")); - allFlag = arguments.options.HasKey(P("all")); + saveFlag = arguments.options.HasKey(P("save")); + allFlag = arguments.options.HasKey(P("all")); SelectFeatureAndConfig(arguments); if (arguments.subCommandName.IsEmpty()) { ShowAllFeatures(); - } - else if (arguments.subCommandName.Compare(P("enable"))) { + } else if (arguments.subCommandName.Compare(P("enable"))) { EnableFeature(); - } - else if (arguments.subCommandName.Compare(P("disable"))) { + } else if (arguments.subCommandName.Compare(P("disable"))) { DisableFeature(); - } - else if (arguments.subCommandName.Compare(P("showconf"))) { + } else if (arguments.subCommandName.Compare(P("showconf"))) { ShowSelectedConfigs(allFlag); - } - else if (arguments.subCommandName.Compare(P("editconf"))) - { + } else if (arguments.subCommandName.Compare(P("editconf"))) { EditFeatureConfig( arguments.parameters.GetText(P("variable_path")), arguments.parameters.GetItem(P("value")), saveFlag); - } - else if (arguments.subCommandName.Compare(P("saveconf"))) { + } else if (arguments.subCommandName.Compare(P("saveconf"))) { SaveFeatureConfig(); - } - else if (arguments.subCommandName.Compare(P("newconf"))) { + } else if (arguments.subCommandName.Compare(P("newconf"))) { NewFeatureConfig(); - } - else if (arguments.subCommandName.Compare(P("removeconf"))) { + } else if (arguments.subCommandName.Compare(P("removeconf"))) { RemoveFeatureConfig(); - } - else if (arguments.subCommandName.Compare(P("autoconf"))) { + } else if (arguments.subCommandName.Compare(P("autoconf"))) { SetAutoFeatureConfig(); } - _.memory.Free(selectedConfigName); + _.memory.Free2(selectedConfigName, selectedFeatureName); selectedConfigName = none; + selectedFeatureName = none; } -protected function SelectFeatureAndConfig(CallData arguments) -{ +protected function SelectFeatureAndConfig(CallData arguments) { local Text featureClassName, userGivenConfigName; - featureClassName = arguments.parameters.GetText(P("feature")); + selectedFeatureName = arguments.parameters.GetTextBy(P("/feature/alias")); + featureClassName = arguments.parameters.GetTextBy(P("/feature/value")); selectedFeatureClass = LoadFeatureClass(featureClassName); if (selectedFeatureClass == none && !arguments.subCommandName.IsEmpty()) { + _.memory.Free(selectedFeatureName); + selectedFeatureName = none; return; } _.memory.Free(featureClassName); userGivenConfigName = arguments.parameters.GetText(P("config")); - if (userGivenConfigName != none) - { + if (userGivenConfigName != none) { selectedConfigName = userGivenConfigName.LowerCopy(); userGivenConfigName.FreeSelf(); } pendingConfigs.SelectConfig(selectedFeatureClass, selectedConfigName); } -protected function EnableFeature() -{ - local bool wasEnabled; - local Text oldConfig, newConfig; - local Feature instance; +protected function EnableFeature() { + local bool wasEnabled; + local Text oldConfig, newConfig; + local Feature instance; - wasEnabled = selectedFeatureClass.static.IsEnabled(); - oldConfig = selectedFeatureClass.static.GetCurrentConfig(); - newConfig = PickConfigBasedOnParameter(); + wasEnabled = selectedFeatureClass.static.IsEnabled(); + oldConfig = selectedFeatureClass.static.GetCurrentConfig(); + newConfig = PickConfigBasedOnParameter(); // Already enabled with the same config! - if (oldConfig != none && oldConfig.Compare(newConfig, SCASE_INSENSITIVE)) - { - announcer.AnnounceFailedAlreadyEnabled(selectedFeatureClass, newConfig); + if (oldConfig != none && oldConfig.Compare(newConfig, SCASE_INSENSITIVE)) { + announcer.AnnounceFailedAlreadyEnabled(selectedFeatureName, newConfig); _.memory.Free(newConfig); _.memory.Free(oldConfig); return; } // Try enabling and report the result instance = selectedFeatureClass.static.EnableMe(newConfig); - if (instance == none) - { + if (instance == none) { announcer.AnnounceFailedCannotEnableFeature( - selectedFeatureClass, + selectedFeatureName, newConfig); - } - else if (wasEnabled) - { + } else if (wasEnabled) { announcer.AnnounceSwappedConfig( - selectedFeatureClass, + selectedFeatureName, oldConfig, newConfig); - } - else { - announcer.AnnounceEnabledFeature(selectedFeatureClass, newConfig); + } else { + announcer.AnnounceEnabledFeature(selectedFeatureName, newConfig); } _.memory.Free(newConfig); _.memory.Free(oldConfig); } -protected function DisableFeature() -{ - if (!selectedFeatureClass.static.IsEnabled()) - { - announcer.AnnounceFailedAlreadyDisabled(selectedFeatureClass); +protected function DisableFeature() { + if (!selectedFeatureClass.static.IsEnabled()) { + announcer.AnnounceFailedAlreadyDisabled(selectedFeatureName); return; } selectedFeatureClass.static.DisableMe(); // It is possible that this command itself is destroyed after above command // so do the check just in case if (IsAllocated()) { - announcer.AnnounceDisabledFeature(selectedFeatureClass); + announcer.AnnounceDisabledFeature(selectedFeatureName); } } -protected function ShowSelectedConfigs(bool showAllFeatures) -{ - local int i; - local array availableConfigs; - local MutableText configList; - local class configClass; +protected function ShowSelectedConfigs(bool showAllFeatures) { + local int i; + local array availableConfigs; + local MutableText configList; + local class configClass; - if (showAllFeatures) - { + if (showAllFeatures) { configClass = selectedFeatureClass.default.configClass; if (configClass != none) { availableConfigs = configClass.static.AvailableConfigs(); @@ -238,8 +218,7 @@ protected function ShowSelectedConfigs(bool showAllFeatures) _.memory.FreeMany(availableConfigs); return; } - if (selectedConfigName != none) - { + if (selectedConfigName != none) { ShowFeatureConfig(selectedConfigName); return; } @@ -251,35 +230,32 @@ protected function ShowSelectedConfigs(bool showAllFeatures) _.memory.Free(configList); } -protected function ShowFeatureConfig(BaseText configName) -{ - local MutableText dataAsJSON; - local HashTable currentData, pendingData; +protected function ShowFeatureConfig(BaseText configName) { + local MutableText dataAsJSON; + local HashTable currentData, pendingData; if (configName == none) { return; } currentData = GetCurrentConfigData(configName); - if (currentData == none) - { + if (currentData == none) { announcer.AnnounceFailedNoDataForConfig( - selectedFeatureClass, + selectedFeatureName, configName); return; } // Display current data dataAsJSON = _.json.PrettyPrint(currentData); - announcer.AnnounceCurrentConfig(selectedFeatureClass, configName); + announcer.AnnounceCurrentConfig(selectedFeatureName, configName); callerConsole.Flush().WriteLine(dataAsJSON); _.memory.Free(dataAsJSON); // Display pending data pendingConfigs.SelectConfig(selectedFeatureClass, configName); pendingData = pendingConfigs.GetPendingConfigData(); - if (pendingData != none) - { + if (pendingData != none) { dataAsJSON = _.json.PrettyPrint(pendingData); announcer.AnnouncePendingConfig( - selectedFeatureClass, + selectedFeatureName, configName); callerConsole.Flush().WriteLine(dataAsJSON); _.memory.Free(dataAsJSON); @@ -288,20 +264,17 @@ protected function ShowFeatureConfig(BaseText configName) _.memory.Free(currentData); } -protected function Text PickConfigBasedOnParameter() -{ - local Text resolvedConfig; - local class configClass; +protected function Text PickConfigBasedOnParameter() { + local Text resolvedConfig; + local class configClass; configClass = selectedFeatureClass.default.configClass; - if (configClass == none) - { - announcer.AnnounceFailedNoConfigClass(selectedFeatureClass); + if (configClass == none) { + announcer.AnnounceFailedNoConfigClass(selectedFeatureName); return none; } // If config was specified - simply check that it exists - if (selectedConfigName != none) - { + if (selectedConfigName != none) { if (configClass.static.Exists(selectedConfigName)) { return selectedConfigName.Copy(); } @@ -311,13 +284,12 @@ protected function Text PickConfigBasedOnParameter() // If it wasn't specified - try auto config instead resolvedConfig = configClass.static.GetAutoEnabledConfig(); if (resolvedConfig == none) { - announcer.AnnounceFailedNoConfigProvided(selectedFeatureClass); + announcer.AnnounceFailedNoConfigProvided(selectedFeatureName); } return resolvedConfig; } -protected function class LoadFeatureClass(BaseText featureClassName) -{ +protected function class LoadFeatureClass(BaseText featureClassName) { local class featureClass; if (featureClassName == none) { @@ -330,10 +302,10 @@ protected function class LoadFeatureClass(BaseText featureClassName) return featureClass; } -protected function ShowAllFeatures() -{ - local int i; - local array< class > availableFeatures; +protected function ShowAllFeatures() { + local int i; + local array< class > availableFeatures; + availableFeatures = _.environment.GetAvailableFeatures(); for (i = 0; i < availableFeatures.length; i ++) { ShowFeature(availableFeatures[i]); @@ -366,45 +338,47 @@ protected function ShowFeature(class featureClass) _.memory.Free(configList); } -protected function MutableText PrintConfigList(class featureClass) -{ - local int i; - local Text autoConfig; - local ListBuilder configList; - local MutableText result, nextConfig; - local array availableConfigs; - local class configClass; +protected function MutableText PrintConfigList(class featureClass) { + local int i; + local Text autoConfig, enabledConfig; + local ListBuilder configList; + local MutableText result, nextConfig; + local array availableConfigs; + local class configClass; if (featureClass == none) return none; configClass = featureClass.default.configClass; if (configClass == none) return none; - availableConfigs = configClass.static.AvailableConfigs(); - autoConfig = configClass.static.GetAutoEnabledConfig(); - configList = ListBuilder(_.memory.Allocate(class'ListBuilder')); - for (i = 0; i < availableConfigs.length; i += 1) - { + availableConfigs = configClass.static.AvailableConfigs(); + enabledConfig = featureClass.static.GetCurrentConfig(); + autoConfig = configClass.static.GetAutoEnabledConfig(); + configList = ListBuilder(_.memory.Allocate(class'ListBuilder')); + for (i = 0; i < availableConfigs.length; i += 1) { nextConfig = availableConfigs[i].MutableCopy(); + if (enabledConfig != none && enabledConfig.Compare(nextConfig, SCASE_INSENSITIVE)) { + nextConfig.ChangeDefaultColor(_.color.TextPositive); + } if (pendingConfigs.HasPendingConfigFor(featureClass, nextConfig)) { nextConfig.Append(F("{$TextEmphasis *}")); } configList.Item(nextConfig); _.memory.Free(nextConfig); - if ( autoConfig != none - && autoConfig.Compare(availableConfigs[i], SCASE_INSENSITIVE)) - { - configList.Comment(F("{$TextPositive auto enabled}")); + if (autoConfig != none && autoConfig.Compare(availableConfigs[i], SCASE_INSENSITIVE)) { + if (autoConfig.Compare(enabledConfig, SCASE_INSENSITIVE)) { + configList.Comment(F("{$TextPositive auto enabled}")); + } else { + configList.Comment(F("{$TextNegative auto enabled}")); + } } } result = configList.GetMutable(); - _.memory.Free(configList); - _.memory.Free(autoConfig); + _.memory.Free3(configList, autoConfig, enabledConfig); _.memory.FreeMany(availableConfigs); return result; } -protected function MutableText PrettyPrintValueAt(BaseText pathToValue) -{ +protected function MutableText PrettyPrintValueAt(BaseText pathToValue) { local MutableText printedValue; local AcediaObject value; local HashTable relevantData; @@ -416,8 +390,7 @@ protected function MutableText PrettyPrintValueAt(BaseText pathToValue) if (relevantData != none) { value = relevantData.GetItemBy(pathToValue); } - if (value != none) - { + if (value != none) { printedValue = _.json.PrettyPrint(value); _.memory.Free(value); } @@ -425,11 +398,7 @@ protected function MutableText PrettyPrintValueAt(BaseText pathToValue) return printedValue; } -protected function EditFeatureConfig( - BaseText pathToValue, - AcediaObject newValue, - bool saveConfig) -{ +protected function EditFeatureConfig(BaseText pathToValue, AcediaObject newValue, bool saveConfig) { local MutableText printedOldValue; local MutableText printedNewValue; local PendingConfigsTool.PendingConfigToolResult error; @@ -447,26 +416,20 @@ protected function EditFeatureConfig( } else if (error == PCTE_ExpectedObject) { announcer.AnnounceFailedExpectedObject(); - } - else if (error == PCTE_BadPointer) - { + } else if (error == PCTE_BadPointer) { announcer.AnnounceFailedBadPointer( - selectedFeatureClass, + selectedFeatureName, selectedConfigName, pathToValue); - } - else if (printedOldValue == none) - { + } else if (printedOldValue == none) { announcer.AnnounceConfigNewValue( - selectedFeatureClass, + selectedFeatureName, selectedConfigName, pathToValue, printedNewValue); - } - else - { + } else { announcer.AnnounceConfigEdited( - selectedFeatureClass, + selectedFeatureName, selectedConfigName, pathToValue, printedOldValue, @@ -481,21 +444,18 @@ protected function EditFeatureConfig( _.memory.Free(newValue); } -protected function SaveFeatureConfig() -{ - local BaseText enabledConfigName; - local HashTable pendingData; - local class configClass; +protected function SaveFeatureConfig() { + local BaseText enabledConfigName; + local HashTable pendingData; + local class configClass; configClass = selectedFeatureClass.default.configClass; - if (configClass == none) - { - announcer.AnnounceFailedNoConfigClass(selectedFeatureClass); + if (configClass == none) { + announcer.AnnounceFailedNoConfigClass(selectedFeatureName); return; } pendingData = pendingConfigs.GetPendingConfigData(); - if (pendingData == none) - { + if (pendingData == none) { announcer.AnnounceFailedPendingConfigMissing(selectedConfigName); return; } @@ -504,13 +464,11 @@ protected function SaveFeatureConfig() configClass.static.SaveData(selectedConfigName, pendingData); // Re-apply config if it is active? enabledConfigName = selectedFeatureClass.static.GetCurrentConfig(); - if (selectedConfigName.Compare(enabledConfigName, SCASE_INSENSITIVE)) - { + if (selectedConfigName.Compare(enabledConfigName, SCASE_INSENSITIVE)) { selectedFeatureClass.static.EnableMe(selectedConfigName); - announcer.AnnouncePublicPendingConfigSaved(selectedFeatureClass); - } - else { - announcer.AnnouncePrivatePendingConfigSaved(selectedFeatureClass); + announcer.AnnouncePublicPendingConfigSaved(selectedFeatureName); + } else { + announcer.AnnouncePrivatePendingConfigSaved(selectedFeatureName, selectedConfigName); } _.memory.Free(enabledConfigName); pendingData.FreeSelf(); @@ -518,125 +476,101 @@ protected function SaveFeatureConfig() return; } -protected function NewFeatureConfig() -{ - local BaseText enabledConfigName; - local class configClass; +protected function NewFeatureConfig() { + local BaseText enabledConfigName; + local class configClass; configClass = selectedFeatureClass.default.configClass; - if (configClass == none) - { - announcer.AnnounceFailedNoConfigClass(selectedFeatureClass); + if (configClass == none) { + announcer.AnnounceFailedNoConfigClass(selectedFeatureName); return; } - if (configClass.static.Exists(selectedConfigName)) - { - announcer.AnnounceFailedConfigAlreadyExists( - selectedFeatureClass, - selectedConfigName); + if (configClass.static.Exists(selectedConfigName)) { + announcer.AnnounceFailedConfigAlreadyExists(selectedFeatureName, selectedConfigName); return; } - if (!configClass.static.NewConfig(selectedConfigName)) - { + if (!configClass.static.NewConfig(selectedConfigName)) { announcer.AnnounceFailedBadConfigName(selectedConfigName); return; } enabledConfigName = selectedFeatureClass.static.GetCurrentConfig(); - if (selectedConfigName.Compare(enabledConfigName, SCASE_INSENSITIVE)) - { + if (selectedConfigName.Compare(enabledConfigName, SCASE_INSENSITIVE)) { selectedFeatureClass.static.EnableMe(selectedConfigName); - announcer.AnnouncePublicPendingConfigSaved(selectedFeatureClass); + announcer.AnnouncePublicPendingConfigSaved(selectedFeatureName); } _.memory.Free(enabledConfigName); - announcer.AnnounceConfigCreated(selectedFeatureClass, selectedConfigName); + announcer.AnnounceConfigCreated(selectedFeatureName, selectedConfigName); } -protected function RemoveFeatureConfig() -{ +protected function RemoveFeatureConfig() { local class configClass; configClass = selectedFeatureClass.default.configClass; - if (configClass == none) - { - announcer.AnnounceFailedNoConfigClass(selectedFeatureClass); + if (configClass == none) { + announcer.AnnounceFailedNoConfigClass(selectedFeatureName); return; } - if (!configClass.static.Exists(selectedConfigName)) - { + if (!configClass.static.Exists(selectedConfigName)) { announcer.AnnounceFailedConfigDoesNotExist( - selectedFeatureClass, + selectedFeatureName, selectedConfigName); return; } pendingConfigs.RemoveConfig(); configClass.static.DeleteConfig(selectedConfigName); - announcer.AnnounceConfigRemoved(selectedFeatureClass, selectedConfigName); + announcer.AnnounceConfigRemoved(selectedFeatureName, selectedConfigName); } -protected function SetAutoFeatureConfig() -{ - local Text currentAutoEnabledConfig; - local class configClass; +protected function SetAutoFeatureConfig() { + local Text currentAutoEnabledConfig; + local class configClass; configClass = selectedFeatureClass.default.configClass; - if (configClass == none) - { - announcer.AnnounceFailedNoConfigClass(selectedFeatureClass); + if (configClass == none) { + announcer.AnnounceFailedNoConfigClass(selectedFeatureName); return; } - if ( selectedConfigName != none - && !configClass.static.Exists(selectedConfigName)) - { - announcer.AnnounceFailedConfigDoesNotExist( - selectedFeatureClass, - selectedConfigName); + if (selectedConfigName != none && !configClass.static.Exists(selectedConfigName)) { + announcer.AnnounceFailedConfigDoesNotExist(selectedFeatureName, selectedConfigName); return; } currentAutoEnabledConfig = configClass.static.GetAutoEnabledConfig(); if (selectedConfigName == none && currentAutoEnabledConfig == none) { - announcer.AnnounceFailedAlreadyNoAutoEnabled(selectedFeatureClass); + announcer.AnnounceFailedAlreadyNoAutoEnabled(selectedFeatureName); } else if (selectedConfigName != none && - selectedConfigName.Compare(currentAutoEnabledConfig, SCASE_INSENSITIVE)) - { + selectedConfigName.Compare(currentAutoEnabledConfig, SCASE_INSENSITIVE)) { announcer.AnnounceFailedAlreadySameAutoEnabled( - selectedFeatureClass, + selectedFeatureName, selectedConfigName); - } - else - { + } else { configClass.static.SetAutoEnabledConfig(selectedConfigName); - if (selectedConfigName != none) - { + if (selectedConfigName != none) { announcer.AnnounceAutoEnabledConfig( - selectedFeatureClass, + selectedFeatureName, selectedConfigName); - } - else { - announcer.AnnounceRemovedAutoEnabledConfig(selectedFeatureClass); + } else { + announcer.AnnounceRemovedAutoEnabledConfig(selectedFeatureName); } } _.memory.Free(currentAutoEnabledConfig); } -private function HashTable GetCurrentConfigData(BaseText configName) -{ +private function HashTable GetCurrentConfigData(BaseText configName) { local class configClass; if (configName == none) { return none; } configClass = selectedFeatureClass.default.configClass; - if (configClass == none) - { - announcer.AnnounceFailedNoConfigClass(selectedFeatureClass); + if (configClass == none) { + announcer.AnnounceFailedNoConfigClass(selectedFeatureName); return none; } return configClass.static.LoadData(configName); } -private function HashTable GetCurrentSelectedConfigData() -{ +private function HashTable GetCurrentSelectedConfigData() { return GetCurrentConfigData(selectedConfigName); } diff --git a/sources/Commands/ACommandFeature_Announcer.uc b/sources/Commands/ACommandFeature_Announcer.uc index 599b5e7..0fbec66 100644 --- a/sources/Commands/ACommandFeature_Announcer.uc +++ b/sources/Commands/ACommandFeature_Announcer.uc @@ -75,8 +75,8 @@ protected function Finalizer() } public final function AnnounceEnabledFeature( - class featureClass, - BaseText configName) + BaseText featureName, + BaseText configName) { local int i; local array templates; @@ -93,12 +93,12 @@ public final function AnnounceEnabledFeature( } templates = MakeArray(enabledFeature); for (i = 0; i < templates.length; i += 1) { - templates[i].Reset().ArgClass(featureClass).Arg(configName); + templates[i].Reset().Arg(featureName).Arg(configName); } MakeAnnouncement(enabledFeature); } -public final function AnnounceDisabledFeature(class featureClass) +public final function AnnounceDisabledFeature(BaseText featureName) { local int i; local array templates; @@ -114,15 +114,15 @@ public final function AnnounceDisabledFeature(class featureClass) } templates = MakeArray(disabledFeature); for (i = 0; i < templates.length; i += 1) { - templates[i].Reset().ArgClass(featureClass); + templates[i].Reset().Arg(featureName); } MakeAnnouncement(disabledFeature); } public final function AnnounceSwappedConfig( - class featureClass, - BaseText oldConfig, - BaseText newConfig) + BaseText featureName, + BaseText oldConfig, + BaseText newConfig) { local int i; local array templates; @@ -142,7 +142,7 @@ public final function AnnounceSwappedConfig( { templates[i] .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(oldConfig) .Arg(newConfig); } @@ -150,7 +150,7 @@ public final function AnnounceSwappedConfig( } public final function AnnouncePublicPendingConfigSaved( - class featureClass) + BaseText featureName) { local int i; local array templates; @@ -167,30 +167,30 @@ public final function AnnouncePublicPendingConfigSaved( } templates = MakeArray(pendingConfigSavedPublic); for (i = 0; i < templates.length; i += 1) { - templates[i].Reset().ArgClass(featureClass); + templates[i].Reset().Arg(featureName); } MakeAnnouncement(pendingConfigSavedPublic); } -public final function AnnouncePrivatePendingConfigSaved( - class featureClass) +public final function AnnouncePrivatePendingConfigSaved(BaseText featureName, BaseText configName) { if (!pendingConfigSavedPrivate.initialized) { pendingConfigSavedPrivate.initialized = true; pendingConfigSavedPrivate.toSelfReport = _.text.MakeTemplate_S( - "Active config for feature {$TextEmphasis `%1`} was" + "Config \"%2\" for feature {$TextEmphasis `%1`} was" @ "{$TextNeutral modified}"); } pendingConfigSavedPrivate.toSelfReport .Reset() - .ArgClass(featureClass); + .Arg(featureName) + .Arg(configName); MakeAnnouncement(pendingConfigSavedPrivate); } public final function AnnounceCurrentConfig( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!showCurrentConfig.initialized) { @@ -200,14 +200,14 @@ public final function AnnounceCurrentConfig( } showCurrentConfig.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(showCurrentConfig); } public final function AnnouncePendingConfig( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!showPendingConfig.initialized) { @@ -217,14 +217,14 @@ public final function AnnouncePendingConfig( } showPendingConfig.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(showPendingConfig); } public final function AnnounceConfigCreated( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!configCreated.initialized) { @@ -235,14 +235,14 @@ public final function AnnounceConfigCreated( } configCreated.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(configCreated); } public final function AnnounceConfigRemoved( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!configRemoved.initialized) { @@ -253,17 +253,17 @@ public final function AnnounceConfigRemoved( } configRemoved.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(configRemoved); } public final function AnnounceConfigEdited( - class featureClass, - BaseText config, - BaseText pathToValue, - BaseText oldValue, - BaseText newValue) + BaseText featureName, + BaseText config, + BaseText pathToValue, + BaseText oldValue, + BaseText newValue) { if (!configEdited.initialized) { @@ -275,7 +275,7 @@ public final function AnnounceConfigEdited( } configEdited.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config) .Arg(pathToValue) .Arg(oldValue) @@ -284,10 +284,10 @@ public final function AnnounceConfigEdited( } public final function AnnounceConfigNewValue( - class featureClass, - BaseText config, - BaseText pathToValue, - BaseText newValue) + BaseText featureName, + BaseText config, + BaseText pathToValue, + BaseText newValue) { if (!configEditedNew.initialized) { @@ -298,7 +298,7 @@ public final function AnnounceConfigNewValue( } configEditedNew.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config) .Arg(pathToValue) .Arg(newValue); @@ -306,8 +306,8 @@ public final function AnnounceConfigNewValue( } public final function AnnounceAutoEnabledConfig( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!autoEnabled.initialized) { @@ -318,13 +318,13 @@ public final function AnnounceAutoEnabledConfig( } autoEnabled.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(autoEnabled); } public final function AnnounceRemovedAutoEnabledConfig( - class featureClass) + BaseText featureName) { if (!removedAutoEnabled.initialized) { @@ -335,12 +335,12 @@ public final function AnnounceRemovedAutoEnabledConfig( } removedAutoEnabled.toSelfReport .Reset() - .ArgClass(featureClass); + .Arg(featureName); MakeAnnouncement(removedAutoEnabled); } public final function AnnounceFailedAlreadyNoAutoEnabled( - class featureClass) + BaseText featureName) { if (!failedAlreadyNoAutoEnabled.initialized) { @@ -352,13 +352,13 @@ public final function AnnounceFailedAlreadyNoAutoEnabled( } failedAlreadyNoAutoEnabled.toSelfReport .Reset() - .ArgClass(featureClass); + .Arg(featureName); MakeAnnouncement(failedAlreadyNoAutoEnabled); } public final function AnnounceFailedAlreadySameAutoEnabled( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!failedAlreadySameAutoEnabled.initialized) { @@ -370,14 +370,14 @@ public final function AnnounceFailedAlreadySameAutoEnabled( } failedAlreadySameAutoEnabled.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(failedAlreadySameAutoEnabled); } public final function AnnounceFailedConfigAlreadyExists( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!failedConfigAlreadyExists.initialized) { @@ -388,14 +388,14 @@ public final function AnnounceFailedConfigAlreadyExists( } failedConfigAlreadyExists.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(failedConfigAlreadyExists); } - - public final function AnnounceFailedConfigDoesNotExist( - class featureClass, - BaseText config) + +public final function AnnounceFailedConfigDoesNotExist( + BaseText featureName, + BaseText config) { if (!failedConfigDoesNotExists.initialized) { @@ -406,7 +406,7 @@ public final function AnnounceFailedConfigAlreadyExists( } failedConfigDoesNotExists.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(failedConfigDoesNotExists); } @@ -424,7 +424,7 @@ public final function AnnounceFailedToLoadFeatureClass(BaseText failedClassName) } public final function AnnounceFailedNoConfigProvided( - class featureClass) + BaseText featureName) { if (!failedNoConfigProvided.initialized) { @@ -433,7 +433,7 @@ public final function AnnounceFailedNoConfigProvided( "{$TextFailure No config specified} and {$TextFailure no" @ "auto-enabled config} exists for feature {$TextEmphasis `%1`}"); } - failedNoConfigProvided.toSelfReport.Reset().ArgClass(featureClass); + failedNoConfigProvided.toSelfReport.Reset().Arg(featureName); MakeAnnouncement(failedNoConfigProvided); } @@ -463,8 +463,8 @@ public final function AnnounceFailedPendingConfigMissing(BaseText config) } public final function AnnounceFailedCannotEnableFeature( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!failedCannotEnableFeature.initialized) { @@ -475,13 +475,13 @@ public final function AnnounceFailedCannotEnableFeature( } failedCannotEnableFeature.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(failedCannotEnableFeature); } public final function AnnounceFailedNoConfigClass( - class featureClass) + BaseText featureName) { if (!failedNoConfigClass.initialized) { @@ -491,7 +491,7 @@ public final function AnnounceFailedNoConfigClass( @ "class! This is most likely caused by its faulty" @ "implementation"); } - failedNoConfigClass.toSelfReport.Reset().ArgClass(featureClass); + failedNoConfigClass.toSelfReport.Reset().Arg(featureName); MakeAnnouncement(failedNoConfigClass); } @@ -508,7 +508,7 @@ public final function AnnounceFailedBadConfigName(BaseText configName) } public final function AnnounceFailedAlreadyDisabled( - class featureClass) + BaseText featureName) { if (!failedAlreadyDisabled.initialized) { @@ -517,13 +517,13 @@ public final function AnnounceFailedAlreadyDisabled( "{$TextFailure Cannot disable} feature {$TextEmphasis `%1`}: it is" @ "already {$TextNegative disabled}"); } - failedAlreadyDisabled.toSelfReport.Reset().ArgClass(featureClass); + failedAlreadyDisabled.toSelfReport.Reset().Arg(featureName); MakeAnnouncement(failedAlreadyDisabled); } public final function AnnounceFailedAlreadyEnabled( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!failedAlreadyEnabled.initialized) { @@ -534,14 +534,14 @@ public final function AnnounceFailedAlreadyEnabled( } failedAlreadyEnabled.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(failedAlreadyEnabled); } public final function AnnounceFailedNoDataForConfig( - class featureClass, - BaseText config) + BaseText featureName, + BaseText config) { if (!failedNoDataForConfig.initialized) { @@ -552,7 +552,7 @@ public final function AnnounceFailedNoDataForConfig( } failedNoDataForConfig.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config); MakeAnnouncement(failedNoDataForConfig); } @@ -570,9 +570,9 @@ public final function AnnounceFailedExpectedObject() } public final function AnnounceFailedBadPointer( - class featureClass, - BaseText config, - BaseText pointer) + BaseText featureName, + BaseText config, + BaseText pointer) { if (!failedBadPointer.initialized) { @@ -583,7 +583,7 @@ public final function AnnounceFailedBadPointer( } failedBadPointer.toSelfReport .Reset() - .ArgClass(featureClass) + .Arg(featureName) .Arg(config) .Arg(pointer); MakeAnnouncement(failedBadPointer); diff --git a/sources/Commands/ACommandSpawn.uc b/sources/Commands/ACommandSpawn.uc index 938bcd7..7cca785 100644 --- a/sources/Commands/ACommandSpawn.uc +++ b/sources/Commands/ACommandSpawn.uc @@ -47,57 +47,59 @@ protected function BuildData(CommandDataBuilder builder) } protected function Executed( - CallData arguments, - EPlayer instigator, + CallData arguments, + EPlayer instigator, CommandPermissions permissions ) { - local Text template; - local Vector spawnLocation; + local HashTable value; + local Vector spawnLocation; announcer.Setup(none, instigator, othersConsole); - template = arguments.parameters.GetText(P("template")); + value = arguments.parameters.GetHashTable(P("template")); if (arguments.subCommandName.IsEmpty()) { - SpawnInInstigatorSight(instigator, template); - } - else if (arguments.subCommandName.Compare(P("at"), SCASE_INSENSITIVE)) - { + SpawnInInstigatorSight(instigator, value); + } else if (arguments.subCommandName.Compare(P("at"), SCASE_INSENSITIVE)) { spawnLocation.x = arguments.parameters.GetFloat(P("x")); spawnLocation.y = arguments.parameters.GetFloat(P("y")); spawnLocation.z = arguments.parameters.GetFloat(P("z")); - SpawnAt(instigator, template, spawnLocation); + SpawnAt(instigator, value, spawnLocation); } - _.memory.Free(template); + _.memory.Free(value); } private final function SpawnAt( - EPlayer instigator, - BaseText template, - Vector spawnLocation) -{ + EPlayer instigator, + HashTable value, + Vector spawnLocation +) { + local Text humanReadable, template; local EPlaceable result; + humanReadable = value.GetText(P("alias")); + template = value.GetText(P("value")); result = _server.kf.world.Spawn(template, spawnLocation); if (result != none) { - announcer.AnnounceSpawned(template); - } - else { - announcer.AnnounceSpawningFailed(template); + announcer.AnnounceSpawned(humanReadable); + } else { + announcer.AnnounceSpawningFailed(humanReadable); } - _.memory.Free(result); + _.memory.Free2(humanReadable, result); } private final function SpawnInInstigatorSight( - EPlayer instigator, - BaseText template) -{ - local EPlaceable result; - local Vector spawnLocation; - local TracingIterator iter; + EPlayer instigator, + HashTable value +) { + local EPlaceable result; + local Vector spawnLocation; + local TracingIterator iter; + local Text humanReadable, template; + humanReadable = value.GetText(P("alias")); + template = value.GetText(P("value")); iter = _server.kf.world.TracePlayerSight(instigator); iter.LeaveOnlyVisible(); - if (iter.HasFinished()) - { + if (iter.HasFinished()) { announcer.AnnounceFailedTrace(); return; } @@ -105,20 +107,16 @@ private final function SpawnInInstigatorSight( result = _server.kf.world.Spawn(template, spawnLocation); // Shift position back a little and try again; // this should fix a ton of spawning failures - if (result == none) - { - spawnLocation = spawnLocation + - Normal(iter.GetTracingStart() - spawnLocation) * 100; + if (result == none) { + spawnLocation = spawnLocation + Normal(iter.GetTracingStart() - spawnLocation) * 100; result = _server.kf.world.Spawn(template, spawnLocation); } if (result != none) { - announcer.AnnounceSpawned(template); - } - else { - announcer.AnnounceSpawningFailed(template); + announcer.AnnounceSpawned(humanReadable); + } else { + announcer.AnnounceSpawningFailed(humanReadable); } - _.memory.Free(result); - _.memory.Free(iter); + _.memory.Free4(result, iter, humanReadable, result); } defaultproperties { diff --git a/sources/Features/FutileChat/FutilityChat.uc b/sources/Features/FutileChat/FutilityChat.uc index a35e7bf..005f751 100644 --- a/sources/Features/FutileChat/FutilityChat.uc +++ b/sources/Features/FutileChat/FutilityChat.uc @@ -1,6 +1,6 @@ /** - * Config object for `FutilityChat_Feature`. - * Copyright 2022 Anton Tarasenko + * Config class for storing map lists. + * Copyright 2022-2023 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * @@ -21,8 +21,7 @@ class FutilityChat extends FeatureConfig perobjectconfig config(FutilityChat); -enum ChatColorSetting -{ +enum ChatColorSetting { CCS_DoNothing, CCS_TeamColorForced, CCS_ConfigColorForced, @@ -30,16 +29,45 @@ enum ChatColorSetting CCS_ConfigColorCustom }; -var public config ChatColorSetting colorSetting; -var public config Color configuredColor; -var public config float teamColorModifier; +/// 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 public config 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 public 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 public config float teamColorModifier; -protected function HashTable ToData() -{ +protected function HashTable ToData() { local HashTable data; - local Text colorAsText; + local Text colorAsText; + data = __().collections.EmptyHashTable(); - data.SetString(P("colorSetting"), string(colorSetting)); + data.SetString(P("colorSetting"), StringFromColorSetting(colorSetting)); colorAsText = _.color.ToText(configuredColor); data.SetItem(P("configuredColor"), colorAsText); _.memory.Free(colorAsText); @@ -47,24 +75,21 @@ protected function HashTable ToData() return data; } -protected function FromData(HashTable source) -{ +protected function FromData(HashTable source) { local Text storedText; - if (source == none) { - return; + + if (source != none) { + storedText = source.GetText(P("colorSetting")); + colorSetting = ColorSettingFromText(storedText); + _.memory.Free(storedText); + storedText = source.GetText(P("configuredColor")); + _.color.Parse(storedText, configuredColor); + _.memory.Free(storedText); + teamColorModifier = source.GetFloat(P("teamColorModifier"), 0.5); } - storedText = source.GetText(P("colorSetting")); - colorSetting = ColorSettingFromText(storedText); - _.memory.Free(storedText); - storedText = source.GetText(P("configuredColor")); - _.color.Parse(storedText, configuredColor); - _.memory.Free(storedText); - teamColorModifier = source.GetFloat(P("teamColorModifier"), 0.5); } -private function ChatColorSetting ColorSettingFromText( - BaseText permissions) -{ +private function ChatColorSetting ColorSettingFromText(BaseText permissions) { if (permissions == none) { return CCS_DoNothing; } @@ -83,17 +108,34 @@ private function ChatColorSetting ColorSettingFromText( return CCS_DoNothing; } -protected function DefaultIt() -{ - colorSetting = CCS_DoNothing; - configuredColor = _.color.RGB(255, 255, 255); - teamColorModifier = 0.6; +private function string StringFromColorSetting(ChatColorSetting permissions) { + if (permissions == CCS_DoNothing) { + return "DoNothing"; + } + if (permissions == CCS_TeamColorForced) { + return "TeamColorForced"; + } + if (permissions == CCS_ConfigColorForced) { + return "ConfigColorForced"; + } + if (permissions == CCS_TeamColorCustom) { + return "TeamColorCustom"; + } + if (permissions == CCS_ConfigColorCustom) { + return "ConfigColorCustom"; + } + return "DoNothing"; +} + +protected function DefaultIt() { + colorSetting = CCS_DoNothing; + configuredColor = _.color.RGB(255, 255, 255); + teamColorModifier = 0.6; } -defaultproperties -{ +defaultproperties { configName = "FutilityChat" - colorSetting = CCS_DoNothing - configuredColor = (R=255,G=255,B=255,A=255) - teamColorModifier = 0.6 + 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 index f4a7b3f..a3bd663 100644 --- a/sources/Features/FutileChat/FutilityChat_Feature.uc +++ b/sources/Features/FutileChat/FutilityChat_Feature.uc @@ -1,6 +1,6 @@ /** - * This feature allows to configure color of text chat messages. - * Copyright 2022 Anton Tarasenko + * Config class for storing map lists. + * Copyright 2022-2023 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * @@ -20,123 +20,82 @@ 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; +var private /*config*/ FutilityChat.ChatColorSetting colorSetting; +var private /*config*/ Color configuredColor; +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 +/// 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; +protected function OnEnabled() { + if (colorSetting != CCS_DoNothing) { + _.chat.OnMessage(self).connect = ReformatChatMessage; + } +} + +protected function OnDisabled() { + if (colorSetting != CCS_DoNothing) { _.chat.OnMessage(self).Disconnect(); } } protected function SwapConfig(FeatureConfig config) { - local bool configRequiresSignal; - local FutilityChat newConfig; + 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(); - } + colorSetting = newConfig.colorSetting; + configuredColor = newConfig.configuredColor; + teamColorModifier = newConfig.teamColorModifier; + configRequiresSignal = (colorSetting != CCS_DoNothing); } private function bool ReformatChatMessage( - EPlayer sender, + EPlayer sender, MutableText message, - bool teamMessage) -{ - local Text messageCopy; - local BaseText.Formatting defaultFormatting; + bool teamMessage +) { + local Text messageCopy; + local BaseText.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) - { + if (colorSetting == CCS_TeamColorForced || colorSetting == CCS_TeamColorCustom) { defaultFormatting.color = ModColor(sender.GetTeamColor()); - } - else { + } else { defaultFormatting.color = configuredColor; } if (message.StartsWith(P("|"))) { message.Remove(0, 1); - } - else if ( colorSetting != CCS_TeamColorForced - && colorSetting != CCS_ConfigColorForced) - { + } else if (colorSetting != CCS_TeamColorForced && colorSetting != CCS_ConfigColorForced) { messageCopy = message.Copy(); - class'FormattingStringParser'.static - .ParseFormatted(messageCopy, message.Clear()); + class'FormattingStringParser'.static.ParseFormatted(messageCopy, message.Clear()); _.memory.Free(messageCopy); } message.ChangeDefaultFormatting(defaultFormatting); return true; } -private function Color ModColor(Color inputColor) -{ +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 - { + } else { mixColor = _.color.Black; clampedModifier *= -1.0; } @@ -147,7 +106,6 @@ private function Color ModColor(Color inputColor) return outputColor; } -defaultproperties -{ +defaultproperties { configClass = class'FutilityChat' } \ No newline at end of file diff --git a/sources/Features/FutileNickames/FutilityNicknames.uc b/sources/Features/FutileNickames/FutilityNicknames.uc index cb982b9..346b79a 100644 --- a/sources/Features/FutileNickames/FutilityNicknames.uc +++ b/sources/Features/FutileNickames/FutilityNicknames.uc @@ -1,6 +1,6 @@ /** - * Config object for `FutileNickames_Feature`. - * Copyright 2022 Anton Tarasenko + * Config class for storing map lists. + * Copyright 2022-2023 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * @@ -21,62 +21,108 @@ class FutilityNicknames extends FeatureConfig perobjectconfig config(FutilityNicknames); -enum NicknameSpacesAction -{ +enum NicknameSpacesAction { NSA_DoNothing, NSA_Trim, NSA_Simplify }; -enum NicknameColorPermissions -{ +enum NicknameColorPermissions { NCP_ForbidColor, NCP_ForceTeamColor, NCP_ForceSingleColor, NCP_AllowAnyColor }; -var public config NicknameSpacesAction spacesAction; -var public config NicknameColorPermissions colorPermissions; -var public config bool replaceSpacesWithUnderscores; -var public config bool removeSingleQuotationMarks; -var public config bool removeDoubleQuotationMarks; -var public config bool correctEmptyNicknames; -var public config int maxNicknameLength; -var public config array fallbackNickname; +/// How to treat whitespace characters inside players' nicknames: +/// +/// * `NSA_DoNothing` - does nothing, leaving whitespaces as they are; +/// * `NSA_Trim` - removes leading and trailing whitespaces for nicknames; +/// * `NSA_Simplify` - removes leading and trailing whitespaces +/// for nicknames, also reducing a sequence of whitespaces inside +/// nickname to a single space, e.g. "my nick" becomes "my nick". +/// +/// Default is `NSA_DoNothing`, same as on vanilla. +var public config NicknameSpacesAction spacesAction; +/// How to treat colored nicknames: +/// +/// * `NCP_ForbidColor` - completely strips down any color from nicknames; +/// * `NCP_ForceTeamColor` - forces all nicknames to have player's current +/// team's color; +/// * `NCP_ForceSingleColor` - allows nickname to be painted with a single +/// color (sets nickname's color to that of the first character); +/// * `NCP_AllowAnyColor` - allows nickname to be colored in any way player +/// wants. +/// Default is `NCP_ForbidColor`, same as on vanilla. +var public config NicknameColorPermissions colorPermissions; +/// Set this to `true` if you wish to replace all whitespace characters with +/// underscores and `false` to leave them as is. +/// Default is `true`, same as on vanilla. However there is one difference: +/// Futility replaces all whitespace characters (including tabulations, +/// non-breaking spaces, etc.) instead of only ' '. +var public config bool replaceSpacesWithUnderscores; +/// Set this to `true` to remove single 'quotation marks' and `false` to +/// leave them. Default is `false`, same as on vanilla. +var public config bool removeSingleQuotationMarks; +/// Set this to `true` to remove dobule 'quotation marks' and `false` to +/// leave them. Default is `true`, same as on vanilla. +var public config bool removeDoubleQuotationMarks; +/// Should we replace empty player nicknames with a random fallback nickname +/// (defined in `fallbackNickname` array)? +var public config bool correctEmptyNicknames; +/// Max allowed nickname length. Negative values disable any length limits. +/// +/// NOTE #1: `0` resets all nicknames to be empty and, +/// if `correctEmptyNicknames` is set to `true`, they will be replaced with +/// one of the fallback nicknames (see `correctEmptyNicknames` and +/// `fallbackNickname`). +/// +/// NOTE #2: Because of how color swapping in vanilla Killing Floor works, +/// every color swap makes text count as being about 4 characters longer. +/// So if one uses too many colors in the nickname, for drawing functions +/// it will appear to be longer than it actually is and it *will* mess up +/// UI. Unless you are using custom HUD it is recommended to keep this value +/// at default `20` and forbid colored nicknames (by setting +/// `colorPermissions=NCP_ForbidColor`). Or to allow only one color (by setting +/// `colorPermissions=NCP_ForceSingleColor` or +/// `colorPermissions=NCP_ForceTeamColor`) and reducing `maxNicknameLength` to +/// `16` (20 characters - 4 for color swap). +/// If you want to increase the limit above that, you can also do your own +/// research by testing nicknames of various length on screen resolutions you +/// care about. +var public config int maxNicknameLength; +/// Array of fallback nicknames that will be used to replace any empty nicknames +/// if `correctEmptyNicknames` is set to `true`. +var public config array fallbackNickname; -protected function HashTable ToData() -{ - local int i; +protected function HashTable ToData() { + local int i; local ArrayList fallbackNicknamesData; local HashTable data; + data = __().collections.EmptyHashTable(); data.SetString(P("spacesAction"), string(spacesAction)); data.SetString(P("colorPermissions"), string(colorPermissions)); - data.SetBool( P("replaceSpacesWithUnderscores"), - replaceSpacesWithUnderscores); - data.SetBool( P("removeSingleQuotationMarks"), - removeSingleQuotationMarks); - data.SetBool( P("removeDoubleQuotationMarks"), - removeDoubleQuotationMarks); + data.SetBool(P("replaceSpacesWithUnderscores"), replaceSpacesWithUnderscores); + data.SetBool(P("removeSingleQuotationMarks"), removeSingleQuotationMarks); + data.SetBool(P("removeDoubleQuotationMarks"), removeDoubleQuotationMarks); data.SetBool(P("correctEmptyNicknames"), correctEmptyNicknames); data.SetInt(P("maxNicknameLength"), maxNicknameLength); fallbackNicknamesData = __().collections.EmptyArrayList(); - for (i = 0; i < fallbackNickname.length; i += 1) - { - fallbackNicknamesData.AddItem( - __().text.FromFormattedString(fallbackNickname[i])); + + for (i = 0; i < fallbackNickname.length; i += 1) { + fallbackNicknamesData.AddItem(__().text.FromFormattedString(fallbackNickname[i])); } data.SetItem(P("fallbackNickname"), fallbackNicknamesData); _.memory.Free(fallbackNicknamesData); return data; } -protected function FromData(HashTable source) -{ - local int i; - local Text nextNickName, storedText; +protected function FromData(HashTable source) { + local int i; + local Text nextNickName, storedText; local ArrayList fallbackNicknamesData; + if (source == none) { return; } @@ -86,25 +132,20 @@ protected function FromData(HashTable source) storedText = source.GetText(P("colorPermissions")); colorPermissions = ColorPermissionsFromText(storedText); _.memory.Free(storedText); - replaceSpacesWithUnderscores = - source.GetBool(P("replaceSpacesWithUnderscores"), true); - removeSingleQuotationMarks = - source.GetBool(P("removeSingleQuotationMarks"), true); - removeDoubleQuotationMarks = - source.GetBool(P("removeDoubleQuotationMarks"), true); + replaceSpacesWithUnderscores = source.GetBool(P("replaceSpacesWithUnderscores"), true); + removeSingleQuotationMarks = source.GetBool(P("removeSingleQuotationMarks"), true); + removeDoubleQuotationMarks = source.GetBool(P("removeDoubleQuotationMarks"), true); correctEmptyNicknames = source.GetBool(P("correctEmptyNicknames"), true); maxNicknameLength = source.GetInt(P("correctEmptyNicknames"), 20); fallbackNicknamesData = source.GetArrayList(P("fallbackNickname")); if (fallbackNickname.length > 0) { fallbackNickname.length = 0; } - for (i = 0; i < fallbackNicknamesData.GetLength(); i += 1) - { + for (i = 0; i < fallbackNicknamesData.GetLength(); i += 1) { nextNickName = fallbackNicknamesData.GetText(i); if (nextNickName != none) { fallbackNickname[i] = nextNickName.ToFormattedString(); - } - else { + } else { fallbackNickname[i] = ""; } _.memory.Free(nextNickName); @@ -112,8 +153,7 @@ protected function FromData(HashTable source) _.memory.Free(fallbackNicknamesData); } -private function NicknameSpacesAction SpaceActionFromText(BaseText action) -{ +private function NicknameSpacesAction SpaceActionFromText(BaseText action) { if (action == none) { return NSA_DoNothing; } @@ -129,9 +169,7 @@ private function NicknameSpacesAction SpaceActionFromText(BaseText action) return NSA_DoNothing; } -private function NicknameColorPermissions ColorPermissionsFromText( - BaseText permissions) -{ +private function NicknameColorPermissions ColorPermissionsFromText(BaseText permissions) { if (permissions == none) { return NCP_ForbidColor; } @@ -150,15 +188,14 @@ private function NicknameColorPermissions ColorPermissionsFromText( return NCP_ForbidColor; } -protected function DefaultIt() -{ - spacesAction = NSA_DoNothing; - colorPermissions = NCP_ForbidColor; - replaceSpacesWithUnderscores = true; - removeSingleQuotationMarks = false; - removeDoubleQuotationMarks = true; - correctEmptyNicknames = true; - maxNicknameLength = 20; +protected function DefaultIt() { + spacesAction = NSA_DoNothing; + colorPermissions = NCP_ForbidColor; + replaceSpacesWithUnderscores = true; + removeSingleQuotationMarks = false; + removeDoubleQuotationMarks = true; + correctEmptyNicknames = true; + maxNicknameLength = 20; if (fallbackNickname.length > 0) { fallbackNickname.length = 0; } @@ -174,16 +211,15 @@ protected function DefaultIt() fallbackNickname[9] = "Bug Meat"; } -defaultproperties -{ +defaultproperties { configName = "FutilityNicknames" - spacesAction = NSA_DoNothing - colorPermissions = NCP_ForbidColor - replaceSpacesWithUnderscores = true - removeSingleQuotationMarks = false - removeDoubleQuotationMarks = true - correctEmptyNicknames = true - maxNicknameLength = 20 + spacesAction = NSA_DoNothing + colorPermissions = NCP_ForbidColor + replaceSpacesWithUnderscores = true + removeSingleQuotationMarks = false + removeDoubleQuotationMarks = true + correctEmptyNicknames = true + maxNicknameLength = 20 fallbackNickname(0) = "Fresh Meat" fallbackNickname(1) = "Rotten Meat" fallbackNickname(2) = "Troll Meat" diff --git a/sources/Features/FutileNickames/FutilityNicknames_Feature.uc b/sources/Features/FutileNickames/FutilityNicknames_Feature.uc index 93bed10..2e2f021 100644 --- a/sources/Features/FutileNickames/FutilityNicknames_Feature.uc +++ b/sources/Features/FutileNickames/FutilityNicknames_Feature.uc @@ -1,9 +1,6 @@ /** - * This feature allows to configure nickname limitations for the server. - * It allows you to customize vanilla limitations for nickname length and - * color with those of your own design. Enabling this feature overwrites - * default behaviour. - * Copyright 2022 Anton Tarasenko + * Config class for storing map lists. + * Copyright 2022-2023 Anton Tarasenko *------------------------------------------------------------------------------ * This file is part of Acedia. * @@ -23,224 +20,133 @@ class FutilityNicknames_Feature extends Feature dependson(FutilityNicknames); -/** - * This feature's functionality is rather simple, but we will still break up - * what its various components are. - * - * Fallback nicknames are picked at random from - * the `fallbackNicknames` array. This is done by copying that array into - * `unusedNicknames` and then picking and removing its random elements each - * time we need a fallback. Once `unusedNicknames` is empty - it is copied from - * `fallbackNicknames` once again, letting already used nicknames to be reused. - * `unusedNicknames` contains same references as `fallbackNicknames`, - * so they need to be separately deallocated and should also be forgotten once - * `fallbackNicknames` are deallocated`. - * This is implemented inside `PickNextFallback()` method. - * - * Nickname changes are applied inside `CensorNickname()` method that uses - * several auxiliary methods to perform different stages of "censoring". - * Censoring is performed: - * 1. On any player's name change - * (using `OnPlayerNameChanging()` signal, connected to - * `HandleNicknameChange()`); - * 2. When new player logins (using `OnNewPlayer()` signal, - * conneted to `CensorOriginalNickname()`) to enforce our own - * handling of player's original nickname; - * 3. When censoring is re-activated. - * In case all censoring options of this feature are disabled - * (checked by `IsAnyCensoringEnabled()`) - we do not attempt to - * catch any events or do anything at all. - * If settings change mid-execution, this feature might need to - * enable or disable censoring on-the-fly. To accomplish that we - * remember current status inside `censoringNicknames` boolean - * variable and enable/disable events if required by settings. - * So whenever we re-activate censoring we also need to update - * ("censor") current players' nicknames - a third occasion to - * call `CensorNickname()`, implemented inside - * `CensorCurrentPlayersNicknames()`. - */ +//! This feature's functionality is rather simple, but we will still break up +//! what its various components are. +//! +//! Fallback nicknames are picked at random from +//! the `fallbackNicknames` array. This is done by copying that array into +//! `unusedNicknames` and then picking and removing its random elements each +//! time we need a fallback. Once `unusedNicknames` is empty - it is copied from +//! `fallbackNicknames` once again, letting already used nicknames to be reused. +//! `unusedNicknames` contains same references as `fallbackNicknames`, +//! so they need to be separately deallocated and should also be forgotten once +//! `fallbackNicknames` are deallocated`. +//! This is implemented inside `PickNextFallback()` method. +//! +//! Nickname changes are applied inside `CensorNickname()` method that uses +//! several auxiliary methods to perform different stages of "censoring". +//! Censoring is performed: +//! 1. On any player's name change +//! (using `OnPlayerNameChanging()` signal, connected to +//! `HandleNicknameChange()`); +//! 2. When new player logins (using `OnNewPlayer()` signal, +//! conneted to `CensorOriginalNickname()`) to enforce our own +//! handling of player's original nickname. -// How to treat whitespace characters inside players' nicknames. -// * `NSA_DoNothing` - does nothing, leaving whitespaces as they are; -// * `NSA_Trim` - removes leading and trailing whitespaces for nicknames; -// * `NSA_Simplify` - removes leading and trailing whitespaces -// for nicknames, also reducing a sequence of whitespaces inside -// nickname to a single space, e.g. "my nick" becomes "my nick". -// Default is `NSA_DoNothing`, same as on vanilla. var private /*config*/ FutilityNicknames.NicknameSpacesAction spacesAction; - -// How to treat colored nicknames. -// * `NCP_ForbidColor` - completely strips down any color from nicknames; -// * `NCP_ForceTeamColor` - forces all nicknames to have player's current -// team's color; -// * `NCP_ForceSingleColor` - allows nickname to be painted with a single -// color (sets nickname's color to that of the first character); -// * `NCP_AllowAnyColor` - allows nickname to be colored in any way player -// wants. -// Default is `NCP_ForbidColor`, same as on vanilla. var private /*config*/ FutilityNicknames.NicknameColorPermissions colorPermissions; +var private /*config*/ bool replaceSpacesWithUnderscores; +var private /*config*/ bool removeSingleQuotationMarks; +var private /*config*/ bool removeDoubleQuotationMarks; +var private /*config*/ int maxNicknameLength; +var private /*config*/ bool correctEmptyNicknames; +var private /*config*/ array fallbackNickname; -// Set this to `true` if you wish to replace all whitespace characters with -// underscores and `false` to leave them as is. -// Default is `true`, same as on vanilla. However there is one difference: -// Futility replaces all whitespace characters (including tabulations, -// non-breaking spaces, etc.) instead of only ' '. -var private /*config*/ bool replaceSpacesWithUnderscores; -// Set this to `true` to remove single 'quotation marks' and `false` to -// leave them. Default is `false`, same as on vanilla. -var private /*config*/ bool removeSingleQuotationMarks; -// Set this to `true` to remove dobule 'quotation marks' and `false` to -// leave them. Default is `true`, same as on vanilla. -var private /*config*/ bool removeDoubleQuotationMarks; - -// Max allowed nickname length. Negative values disable any length limits. -// -// NOTE #1: `0` resets all nicknames to be empty and, -// if `correctEmptyNicknames` is set to `true`, they will be replaced with -// one of the fallback nicknames -// (see `correctEmptyNicknames` and `fallbackNickname`). -// NOTE #2: Because of how color swapping in vanilla Killing Floor works, -// every color swap makes text count as being about 4 characters longer. -// So if one uses too many colors in the nickname, for drawing functions -// it will appear to be longer than it actually is and it *will* mess up -// UI. Unless you are using custom HUD it is recommended to keep this value -// at default `20` and forbid colored nicknames -// (by setting `colorPermissions=NCP_ForbidColor`). Or to allow only one -// color (by setting `colorPermissions=NCP_ForceSingleColor` or -// `colorPermissions=NCP_ForceTeamColor`) and reducing `maxNicknameLength` -// to `16` (20 characters - 4 for color swap). -// If you want to increase the limit above that, you can also do your -// own research by testing nicknames of various length on -// screen resolutions you care about. -var private /*config*/ int maxNicknameLength; +/// Guaranteed order of applying changes (only chosen ones) is as following: +/// +/// 1. Trim/simplify spaces; +/// 2. Remove single and double quotation marks; +/// 3. Enforce max limit of nickname's length; +/// 4. Replace empty nickname with fallback nickname (no further changes +/// will be applied to fallback nickname in that case); +/// 5. Enforce color limitation; +/// 6. Replace remaining whitespaces with underscores. +/// +/// NOTE #1: as follows from the instruction described above, no changes will +/// ever be applied to fallback nicknames (unless player's nickname coincides +/// with one by pure accident). +/// +/// NOTE #2: whitespaces inside steam nicknames are converted into underscores +/// before they are passed into the game and this is a change Futility +/// cannot currently abort. Therefore all changes relevant to whitespaces inside +/// nicknames will only be applied to in-game changes. -// Should we replace empty player nicknames with a random fallback nickname -// (defined in `fallbackNickname` array)? -var private /*config*/ bool correctEmptyNicknames; -// Array of fallback nicknames that will be used to replace any empty nicknames -// if `correctEmptyNicknames` is set to `true`. -var private /*config*/ array fallbackNickname; - -// Guaranteed order of applying changes (only chosen ones) is as following: -// 1. Trim/simplify spaces; -// 2. Remove single and double quotation marks; -// 3. Enforce max limit of nickname's length; -// 4. Replace empty nickname with fallback nickname (no further changes -// will be applied to fallback nickname in that case); -// 5. Enforce color limitation; -// 6. Replace remaining whitespaces with underscores. -// -// NOTE #1: as follows from the instruction described above, no changes will -// ever be applied to fallback nicknames (unless player's nickname -// coincides with one by pure accident). -// NOTE #2: whitespaces inside steam nicknames are converted into underscores -// before they are passed into the game and this is a change Futility -// cannot currently abort. -// Therefore all changes relevant to whitespaces inside nicknames will only -// be applied to in-game changes. - -// Nicknames from `fallbackNickname` that can still be picked in -// the current rotation. +/// Nicknames from `fallbackNickname` that can still be picked in the current +/// rotation. var private array unusedNicknames; -// Are we currently censoring nicknames? -// Set to `false` if none of the feature's options require -// any action (censoring) and, therefore, we do not listen to any signals. -var private bool censoringNicknames; var private const int CODEPOINT_UNDERSCORE; -protected function OnDisabled() -{ - _.memory.FreeMany(fallbackNickname); - // Free this `Text` data - it will be refilled with `SwapConfig()` - // if this feature is ever reenabled - if (fallbackNickname.length > 0) - { - _.memory.FreeMany(fallbackNickname); - fallbackNickname.length = 0; - unusedNicknames.length = 0; +protected function OnEnabled() { + if (IsAnyCensoringEnabled()) { + // Do this before adding event handler to avoid censoring nicknames + // second time (censoring nickname will trigger `OnPlayerNameChanging()` + // signal) + CensorCurrentPlayersNicknames(); + _.players.OnPlayerNameChanging(self).connect = HandleNicknameChange; + _.players.OnNewPlayer(self).connect = CensorOriginalNickname; } - if (censoringNicknames) - { - censoringNicknames = false; +} + +protected function OnDisabled() { + _.memory.FreeMany(fallbackNickname); + _.memory.FreeMany(unusedNicknames); + fallbackNickname.length = 0; + unusedNicknames.length = 0; + if (IsAnyCensoringEnabled()) { _.players.OnPlayerNameChanging(self).Disconnect(); _.players.OnNewPlayer(self).Disconnect(); } } -protected function SwapConfig(FeatureConfig config) -{ - local bool configRequiresCensoring; +protected function SwapConfig(FeatureConfig config) { local FutilityNicknames newConfig; + newConfig = FutilityNicknames(config); if (newConfig == none) { return; } - replaceSpacesWithUnderscores = newConfig.replaceSpacesWithUnderscores; - removeSingleQuotationMarks = newConfig.removeSingleQuotationMarks; - removeDoubleQuotationMarks = newConfig.removeDoubleQuotationMarks; - correctEmptyNicknames = newConfig.correctEmptyNicknames; - spacesAction = newConfig.spacesAction; - colorPermissions = newConfig.colorPermissions; - maxNicknameLength = newConfig.maxNicknameLength; - configRequiresCensoring = IsAnyCensoringEnabled(); - // Enable or disable censoring if `IsAnyCensoringEnabled()`'s response - // has changed. - if (!censoringNicknames && configRequiresCensoring) - { - censoringNicknames = true; - // Do this before adding event handler to - // avoid censoring nicknames second time - CensorCurrentPlayersNicknames(); - _.players.OnPlayerNameChanging(self).connect = HandleNicknameChange; - _.players.OnNewPlayer(self).connect = CensorOriginalNickname; - } - if (censoringNicknames && !configRequiresCensoring) - { - censoringNicknames = false; - _.players.OnPlayerNameChanging(self).Disconnect(); - _.players.OnNewPlayer(self).Disconnect(); - } + replaceSpacesWithUnderscores = newConfig.replaceSpacesWithUnderscores; + removeSingleQuotationMarks = newConfig.removeSingleQuotationMarks; + removeDoubleQuotationMarks = newConfig.removeDoubleQuotationMarks; + correctEmptyNicknames = newConfig.correctEmptyNicknames; + spacesAction = newConfig.spacesAction; + colorPermissions = newConfig.colorPermissions; + maxNicknameLength = newConfig.maxNicknameLength; SwapFallbackNicknames(newConfig); } -private function Text PickNextFallback() -{ - local int pickedIndex; - local Text result; - if (fallbackNickname.length <= 0) - { - // Just in case this feature is really misconfigured +private function SwapFallbackNicknames(FutilityNicknames newConfig) { + local int i; + + _.memory.FreeMany(fallbackNickname); + fallbackNickname.length = 0; + for (i = 0; i < newConfig.fallbackNickname.length; i += 1) { + fallbackNickname[i] = _.text.FromFormattedString(newConfig.fallbackNickname[i]); + } + unusedNicknames = fallbackNickname; +} + +private function Text PickNextFallback() { + local int pickedIndex; + local Text result; + + if (fallbackNickname.length <= 0) { + // Just in case this feature is really misconfigured return P("Fresh Meat").Copy(); } if (unusedNicknames.length <= 0) { unusedNicknames = fallbackNickname; } - // Pick one nickname at random. - // `pickedIndex` will belong to [0; unusedNicknames.length - 1] segment. + // Pick one nickname at random. + // `pickedIndex` will belong to [0; unusedNicknames.length - 1] segment. pickedIndex = Rand(unusedNicknames.length); result = unusedNicknames[pickedIndex].Copy(); unusedNicknames.Remove(pickedIndex, 1); return result; } -protected function SwapFallbackNicknames(FutilityNicknames newConfig) -{ - local int i; - _.memory.FreeMany(fallbackNickname); - if (fallbackNickname.length > 0) { - fallbackNickname.length = 0; - } - for (i = 0; i < newConfig.fallbackNickname.length; i += 1) - { - fallbackNickname[i] = - _.text.FromFormattedString(newConfig.fallbackNickname[i]); - } - unusedNicknames = fallbackNickname; -} - -private function bool IsAnyCensoringEnabled() -{ +private function bool IsAnyCensoringEnabled() { return ( replaceSpacesWithUnderscores || removeSingleQuotationMarks || removeDoubleQuotationMarks @@ -250,40 +156,38 @@ private function bool IsAnyCensoringEnabled() || spacesAction != NSA_DoNothing); } -// For nickname changes mid-game. +// For nickname changes mid-game. private function HandleNicknameChange( - EPlayer affectedPlayer, - BaseText oldName, - MutableText newName) -{ + EPlayer affectedPlayer, + BaseText oldName, + MutableText newName +) { CensorNickname(newName, affectedPlayer); } -// For handling of player's original nicknames. -private function CensorOriginalNickname(EPlayer affectedPlayer) -{ +// For handling of player's original nicknames. +private function CensorOriginalNickname(EPlayer affectedPlayer) { local Text originalNickname; if (affectedPlayer == none) { return; } originalNickname = affectedPlayer.GetOriginalName(); - // This will automatically trigger `OnPlayerNameChanging()` signal and - // our `HandleNicknameChange()` handler. + // This will automatically trigger `OnPlayerNameChanging()` signal and + // our `HandleNicknameChange()` handler. affectedPlayer.SetName(originalNickname); _.memory.Free(originalNickname); } -// For handling nicknames of players after censoring is re-activated by -// config change. -private function CensorCurrentPlayersNicknames() -{ - local int i; - local Text nextNickname; - local MutableText alteredNickname; - local array currentPlayers; +// For handling nicknames of players after censoring is re-activated by +// config change. +private function CensorCurrentPlayersNicknames() { + local int i; + local Text nextNickname; + local MutableText alteredNickname; + local array currentPlayers; + currentPlayers = _.players.GetAll(); - for (i = 0; i < currentPlayers.length; i += 1) - { + for (i = 0; i < currentPlayers.length; i += 1) { nextNickname = currentPlayers[i].GetName(); alteredNickname = nextNickname.MutableCopy(); CensorNickname(alteredNickname, currentPlayers[i]); @@ -295,10 +199,10 @@ private function CensorCurrentPlayersNicknames() } } -private function CensorNickname(MutableText nickname, EPlayer affectedPlayer) -{ - local Text fallback; - local BaseText.Formatting newFormatting; +private function CensorNickname(MutableText nickname, EPlayer affectedPlayer) { + local Text fallback; + local BaseText.Formatting newFormatting; + if (nickname == none) return; if (affectedPlayer == none) return; @@ -314,25 +218,21 @@ private function CensorNickname(MutableText nickname, EPlayer affectedPlayer) if (maxNicknameLength >= 0) { nickname.Remove(maxNicknameLength); } - if (correctEmptyNicknames && nickname.IsEmpty()) - { + if (correctEmptyNicknames && nickname.IsEmpty()) { fallback = PickNextFallback(); nickname.Append(fallback); _.memory.Free(fallback); return; } - if (colorPermissions != NCP_AllowAnyColor) - { + if (colorPermissions != NCP_AllowAnyColor) { if (colorPermissions == NCP_ForceSingleColor) { newFormatting = nickname.GetCharacter(0).formatting; - } - else if (colorPermissions == NCP_ForceTeamColor) - { + } else if (colorPermissions == NCP_ForceTeamColor) { newFormatting.isColored = true; newFormatting.color = affectedPlayer.GetTeamColor(); } - // `colorPermissions == NCP_ForbidColor` - // `newFormatting` is colorless by default + // `colorPermissions == NCP_ForbidColor` + // `newFormatting` is colorless by default nickname.ChangeFormatting(newFormatting); } if (replaceSpacesWithUnderscores) { @@ -340,21 +240,18 @@ private function CensorNickname(MutableText nickname, EPlayer affectedPlayer) } } -// Asusmes `nickname != none`. -private function ReplaceSpaces(MutableText nickname) -{ - local int i; - local MutableText nicknameCopy; - local BaseText.Character nextCharacter, underscoreCharacter; +// Asusmes `nickname != none`. +private function ReplaceSpaces(MutableText nickname) { + local int i; + local MutableText nicknameCopy; + local BaseText.Character nextCharacter, underscoreCharacter; + nicknameCopy = nickname.MutableCopy(); nickname.Clear(); - underscoreCharacter = - _.text.CharacterFromCodePoint(CODEPOINT_UNDERSCORE); - for (i = 0; i < nicknameCopy.GetLength(); i += 1) - { + underscoreCharacter = _.text.CharacterFromCodePoint(CODEPOINT_UNDERSCORE); + for (i = 0; i < nicknameCopy.GetLength(); i += 1) { nextCharacter = nicknameCopy.GetCharacter(i); - if (_.text.IsWhitespace(nextCharacter)) - { + if (_.text.IsWhitespace(nextCharacter)) { // Replace character with underscore, leaving the formatting underscoreCharacter.formatting = nextCharacter.formatting; nextCharacter = underscoreCharacter; @@ -364,8 +261,7 @@ private function ReplaceSpaces(MutableText nickname) _.memory.Free(nicknameCopy); } -defaultproperties -{ +defaultproperties { configClass = class'FutilityNicknames' CODEPOINT_UNDERSCORE = 95 // '_' } \ No newline at end of file diff --git a/sources/Futility.uc b/sources/Futility.uc index 6aad23d..6227d7f 100644 --- a/sources/Futility.uc +++ b/sources/Futility.uc @@ -21,20 +21,16 @@ class Futility extends FeatureConfig perobjectconfig config(Futility); -protected function HashTable ToData() -{ +protected function HashTable ToData() { return _.collections.EmptyHashTable(); } -protected function FromData(HashTable source) -{ +protected function FromData(HashTable source) { } -protected function DefaultIt() -{ +protected function DefaultIt() { } -defaultproperties -{ +defaultproperties { configName = "Futility" } \ No newline at end of file