diff --git a/Classes/MutVoteSys.uc b/Classes/MutVoteSys.uc index f68f1a1..c37212d 100644 --- a/Classes/MutVoteSys.uc +++ b/Classes/MutVoteSys.uc @@ -1175,6 +1175,8 @@ function LoadPresetPassTwo(VS_Preset P) { P.bLoading = true; PC = P.Storage; P.MinimumMapRepeatDistance = PC.MinimumMapRepeatDistance; + P.MinPlayers = PC.MinPlayers; + P.MaxPlayers = PC.MaxPlayers; for (i = 0; i < PC.InheritFrom.Length; i++) { if (PC.InheritFrom[i] == "") @@ -1192,6 +1194,10 @@ function LoadPresetPassTwo(VS_Preset P) { P.Game = Base.Game; if (P.MinimumMapRepeatDistance < 0) P.MinimumMapRepeatDistance = Base.MinimumMapRepeatDistance; + if (P.MinPlayers < 0) + P.MinPlayers = Base.MinPlayers; + if (P.MaxPlayers < 0) + P.MaxPlayers = Base.MaxPlayers; P.AppendMutator(Base.Mutators); P.AppendParameter(Base.Parameters); diff --git a/Classes/Serialization.uc b/Classes/Serialization.uc index b4d1ea8..bba50f2 100644 --- a/Classes/Serialization.uc +++ b/Classes/Serialization.uc @@ -84,6 +84,8 @@ final function VS_Preset ParsePreset(string Line) { P.Category = DecodeString(Line); NextVariable(Line); P.MaxSequenceNumber = int(Line); NextVariable(Line); P.MinimumMapRepeatDistance = int(Line); NextVariable(Line); + P.MinPlayers = int(Line); NextVariable(Line); + P.MaxPlayers = int(Line); NextVariable(Line); P.SortPriority = int(Line); return P; @@ -118,6 +120,8 @@ final function string SerializePreset(VS_Preset P) { Result = Result$EncodeString(P.Category)$"/"; Result = Result$P.MaxSequenceNumber$"/"; Result = Result$P.MinimumMapRepeatDistance$"/"; + Result = Result$P.MinPlayers$"/"; + Result = Result$P.MaxPlayers$"/"; Result = Result$P.SortPriority; return Result; diff --git a/Classes/VS_PlayerChannel.uc b/Classes/VS_PlayerChannel.uc index e054d67..5d8263e 100644 --- a/Classes/VS_PlayerChannel.uc +++ b/Classes/VS_PlayerChannel.uc @@ -335,6 +335,7 @@ function ServerVote(string FullPresetName, string MapName) { local VS_Preset P; local VS_Map M; local VS_Info I; + local int NumPlayers; if (PlayerOwner == none || PlayerInfo().bCanVote == false) { LocalizeMessage(class'VS_Msg_LocalMessage', -7); @@ -349,10 +350,15 @@ function ServerVote(string FullPresetName, string MapName) { return; if (PlayerOwner.PlayerReplicationInfo.bAdmin == false) { + NumPlayers = Level.Game.NumPlayers; if (VotedFor.PresetRef == P && VotedFor.MapRef == M) return; if (M.Sequence > 0 && P.MaxSequenceNumber - M.Sequence < P.MinimumMapRepeatDistance) return; + if (NumPlayers < P.MinPlayers || (NumPlayers > P.MaxPlayers && P.MaxPlayers > 0)) + return; + if (NumPlayers < M.MinPlayers || (NumPlayers > M.MaxPlayers && M.MaxPlayers > 0)) + return; } if (VotedFor != none) diff --git a/Classes/VS_Preset.uc b/Classes/VS_Preset.uc index 8eaaef1..1b211d0 100644 --- a/Classes/VS_Preset.uc +++ b/Classes/VS_Preset.uc @@ -17,6 +17,8 @@ var bool bLoading; var bool bLoaded; var int MaxSequenceNumber; var int MinimumMapRepeatDistance; +var int MinPlayers; +var int MaxPlayers; function AppendMutator(string Mut) { if (Mut == "") diff --git a/Classes/VS_PresetConfig.uc b/Classes/VS_PresetConfig.uc index 1a57e78..2298135 100644 --- a/Classes/VS_PresetConfig.uc +++ b/Classes/VS_PresetConfig.uc @@ -27,7 +27,13 @@ var config array Packages; var config bool bDisabled; /** Overrides the server setting of the same name, if the value is 0 or greater */ var config int MinimumMapRepeatDistance; +/** At least this many players have to be on the server to allow voting for this preset */ +var config int MinPlayers; +/** At most this many players can be on the server to allow voting for this preset*/ +var config int MaxPlayers; defaultproperties { MinimumMapRepeatDistance=-1 + MinPlayers=-1 + MaxPlayers=-1 } diff --git a/Classes/VS_UI_CategoryTabItem.uc b/Classes/VS_UI_CategoryTabItem.uc index 579febc..4cbeffb 100644 --- a/Classes/VS_UI_CategoryTabItem.uc +++ b/Classes/VS_UI_CategoryTabItem.uc @@ -9,6 +9,7 @@ function AddPreset(VS_Preset P){ PresetList = new(none) class'VS_UI_CategoryPresetWrapper'; PresetListLast = PresetList; PresetList.Preset = P; + SelectedPreset = P; return; } diff --git a/Classes/VS_UI_PresetComboBox.uc b/Classes/VS_UI_PresetComboBox.uc index 3a83302..4e60964 100644 --- a/Classes/VS_UI_PresetComboBox.uc +++ b/Classes/VS_UI_PresetComboBox.uc @@ -2,8 +2,8 @@ class VS_UI_PresetComboBox extends VS_UI_ComboControl; var VS_Preset SelectedPreset; -function AddPreset(VS_Preset P) { - VS_UI_PresetComboList(List).AddPreset(P); +function AddPreset(VS_Preset P, bool bEnable) { + VS_UI_PresetComboList(List).AddPreset(P, bEnable); if (List.Selected == none) { List.Selected = UWindowComboListItem(List.Items.Next); List.ExecuteItem(List.Selected); @@ -14,7 +14,7 @@ function FocusPreset(string PresetName) { local VS_UI_PresetComboListItem I; for (I = VS_UI_PresetComboListItem(List.Items.Next); I != none; I = VS_UI_PresetComboListItem(I.Next)) { - if (I.Preset.PresetName == PresetName && List.Selected != I) { + if (I.bEnabled && I.Preset.PresetName == PresetName && List.Selected != I) { List.Selected = I; List.ExecuteItem(List.Selected); } diff --git a/Classes/VS_UI_PresetComboList.uc b/Classes/VS_UI_PresetComboList.uc index 2b900af..96e0b42 100644 --- a/Classes/VS_UI_PresetComboList.uc +++ b/Classes/VS_UI_PresetComboList.uc @@ -4,7 +4,7 @@ class VS_UI_PresetComboList extends UWindowComboList; function AddItem(string Value, optional string Value2, optional int SortWeight); function InsertItem(string Value, optional string Value2, optional int SortWeight); -function AddPreset(VS_Preset P) { +function AddPreset(VS_Preset P, bool bEnable) { local VS_UI_PresetComboListItem I; I = VS_UI_PresetComboListItem(Items.Append(class'VS_UI_PresetComboListItem')); @@ -12,6 +12,7 @@ function AddPreset(VS_Preset P) { I.Value = P.PresetName; I.Value2 = P.Abbreviation; I.SortWeight = P.SortPriority; + I.bEnabled = bEnable; } function Created() { @@ -29,3 +30,43 @@ function ExecuteItem(UWindowComboListItem I) { VS_UI_PresetComboBox(Owner).SelectedPreset = VS_UI_PresetComboListItem(I).Preset; super.ExecuteItem(I); } + +function SetSelected(float X, float Y) { + local VS_UI_PresetComboListItem NewSelected, Item; + local int i, Count; + + Count = Items.Count(); + + i = (Y - VBorder) / ItemHeight + VertSB.Pos; + + if (i < 0) + i = 0; + + if (i >= VertSB.Pos + Min(Count, MaxVisible)) + i = VertSB.Pos + Min(Count, MaxVisible) - 1; + + NewSelected = VS_UI_PresetComboListItem(Items.FindEntry(i)); + + if (NewSelected != none && NewSelected.bEnabled) + Selected = NewSelected; + else + Selected = none; +} + +function DrawItem(Canvas C, UWindowList Item, float X, float Y, float W, float H) { + local VS_UI_PresetComboListItem I; + + LookAndFeel.ComboList_DrawItem(Self, C, X, Y, W, H, "", Selected == Item); + + I = VS_UI_PresetComboListItem(Item); + if (I.bEnabled) { + C.DrawColor.R = 0; + C.DrawColor.G = 0; + C.DrawColor.B = 0; + } else { + C.DrawColor.R = 96; + C.DrawColor.G = 96; + C.DrawColor.B = 96; + } + ClipText(C, X + TextBorder + 2, Y + 1.5, I.Value); +} diff --git a/Classes/VS_UI_PresetComboListItem.uc b/Classes/VS_UI_PresetComboListItem.uc index b9ae8c6..1086a33 100644 --- a/Classes/VS_UI_PresetComboListItem.uc +++ b/Classes/VS_UI_PresetComboListItem.uc @@ -1,3 +1,4 @@ class VS_UI_PresetComboListItem extends UWindowComboListItem; var VS_Preset Preset; +var bool bEnabled; diff --git a/Classes/VS_UI_VoteClientWindow.uc b/Classes/VS_UI_VoteClientWindow.uc index 1d90037..6100d1d 100644 --- a/Classes/VS_UI_VoteClientWindow.uc +++ b/Classes/VS_UI_VoteClientWindow.uc @@ -117,6 +117,9 @@ function BeforePaint(Canvas C, float MouseX, float MouseY) { CategoryTabs.WinWidth = WinWidth; + VoteButton.bDisabled = (ActivePreset == none); + RandomButton.bDisabled = (ActivePreset == none); + if (ChatEdit.EditBox.bControlDown) ChatSay.SetText(ChatTeamSayText); else @@ -210,8 +213,12 @@ function Paint(Canvas C, float MouseX, float MouseY) { function UpdateActiveCategory() { local VS_UI_CategoryPresetWrapper P; + local bool bEnable; - if (CategoryTabs.SelectedTab != ActiveCategory) { + if (CategoryTabs.SelectedTab != ActiveCategory || + bWasAdmin != bAdmin || + PreviousNumPlayers != NumPlayers + ) { if (ActiveCategory != none) ActiveCategory.SelectedPreset = Presets.SelectedPreset; ActiveCategory = VS_UI_CategoryTabItem(CategoryTabs.SelectedTab); @@ -222,9 +229,16 @@ function UpdateActiveCategory() { if (ActiveCategory == none) return; - for (P = ActiveCategory.PresetList; P != none; P = P.Next) - Presets.AddPreset(P.Preset); + for (P = ActiveCategory.PresetList; P != none; P = P.Next) { + bEnable = (NumPlayers >= P.Preset.MinPlayers) && (NumPlayers <= P.Preset.MaxPlayers || P.Preset.MaxPlayers <= 0); + if (bAdmin) + bEnable = true; + Presets.AddPreset(P.Preset, bEnable); + } Presets.List.Items.Sort(); + + Presets.List.Selected = none; + Presets.SelectedPreset = none; if (ActiveCategory.SelectedPreset != none) Presets.FocusPreset(ActiveCategory.SelectedPreset.PresetName); } diff --git a/README.md b/README.md index 083b4ce..faaced2 100644 --- a/README.md +++ b/README.md @@ -343,6 +343,8 @@ InheritFrom=DM/Team DeathMatch GameSettings=MaxTeams=4 Mutators=Botpack.InstaGibDM MinimumMapRepeatDistance=4 +MinPlayers=4 +MaxPlayers=8 ``` Each preset is a different section inside VoteSysPresets.ini (e.g. `[VS_PresetConfig0]`, `[VS_PresetConfig1]`, etc.). Each preset section needs to start with VS_PresetConfig, followed by a number. The number needs to start from 0 and can go as high as you want. You can not leave out numbers. @@ -359,11 +361,11 @@ Each preset has a `Name`, a `Category` and an `Abbreviation`. You can inherit from an arbitrary number of other presets. Refer to other preset using their [full preset names](#full-preset-names). -You can inherit `Game`, `Mutators`, `Parameters`, `GameSettings`, and `MinimumMapRepeatDistance`. Other elements cannot be inherited. +You can inherit `Game`, `Mutators`, `Parameters`, `GameSettings`, `MinimumMapRepeatDistance`, `MinPlayers`, and `MaxPlayers`. Other elements cannot be inherited. If you dont specify a value for `Game` in the current preset, the first non-empty value in the list of presets you inherit from will be used. -If you dont specify a value, or if you specify a negative value for `MinimumMapRepeatDistance` in the current preset, the first non-empty and non-negative value in the list of presets you inherit from will be used. +If you dont specify a value, or if you specify a negative value for `MinimumMapRepeatDistance`, `MinPlayers`, or `MaxPlayers` in the current preset, the first non-empty and non-negative value in the list of presets you inherit from will be used. For `Mutators`, `Parameters`, and `GameSettings` the values will be combined in the same order you specified the base presets. If you specify any addition values in the current preset, they will be added at the end. @@ -435,6 +437,14 @@ Default is `False`. Specifying this setting allows you to override the server-wide setting on a per-preset basis. If not specified and not inherited from other presets, the server-wide setting will be used. +#### MinPlayers + +Specifies the minimum number of players that have to be present on the server in order to be allowed to vote for this preset. + +#### MaxPlayers + +Specifies the maximum number of players that can be present on the server to still be allowed to vote for this preset. + ### VoteSysMapLists.ini ```ini [CustomMapList] diff --git a/System/VoteSysPresets.ini b/System/VoteSysPresets.ini index 8d486ff..c13954c 100644 --- a/System/VoteSysPresets.ini +++ b/System/VoteSysPresets.ini @@ -32,3 +32,5 @@ InheritFrom=DM/Team DeathMatch GameSettings=MaxTeams=4 Mutators=Botpack.InstaGibDM MinimumMapRepeatDistance=4 +MinPlayers=4 +MaxPlayers=8