From 476859dddfa399abdba3b255c1f1580f4f062052 Mon Sep 17 00:00:00 2001 From: GenZmeY Date: Mon, 31 May 2021 04:46:53 +0300 Subject: [PATCH] add player ranks --- README.md | 14 +- ScoreboardExt/Classes/KFScoreBoard.uc | 95 ++++++++-- ScoreboardExt/Classes/PlayerGroups.uc | 5 + ScoreboardExt/Classes/PlayerInfos.uc | 5 + ScoreboardExt/Classes/ScoreboardExtMut.uc | 165 +++++++++++++++++- ScoreboardExt/Classes/ScoreboardExtRepInfo.uc | 62 +++++++ ScoreboardExt/Classes/SystemAdminGroup.uc | 7 + ScoreboardExt/Classes/SystemPlayerGroup.uc | 7 + ScoreboardExt/Classes/Types.uc | 58 ++++++ ScoreboardExt/Globals.uci | 16 -- 10 files changed, 390 insertions(+), 44 deletions(-) create mode 100644 ScoreboardExt/Classes/PlayerGroups.uc create mode 100644 ScoreboardExt/Classes/PlayerInfos.uc create mode 100644 ScoreboardExt/Classes/ScoreboardExtRepInfo.uc create mode 100644 ScoreboardExt/Classes/SystemAdminGroup.uc create mode 100644 ScoreboardExt/Classes/SystemPlayerGroup.uc create mode 100644 ScoreboardExt/Classes/Types.uc diff --git a/README.md b/README.md index f547593..076289c 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,5 @@ **TODO:** 1. Customizable colors for player level (depending on difficulty) -2. Customizable statuses: - - status name (String) - - status color (RGB) - - apply status color to: - - status (bool) - - player (bool) - - perk (bool) - - kills (bool) - - assists (bool) - - override admin status (bool) -3. Players and status relations -4. Check fields char capacity (crop if text is large then cap) \ No newline at end of file +2. Check fields char capacity (crop if text is large then cap) +3. Check steam group (?) \ No newline at end of file diff --git a/ScoreboardExt/Classes/KFScoreBoard.uc b/ScoreboardExt/Classes/KFScoreBoard.uc index e23eb8a..c758ba2 100644 --- a/ScoreboardExt/Classes/KFScoreBoard.uc +++ b/ScoreboardExt/Classes/KFScoreBoard.uc @@ -1,4 +1,5 @@ -class KFScoreBoard extends KFGUI_Page; +class KFScoreBoard extends KFGUI_Page + dependson(Types); var transient float StatusXPos, PerkXPos, PlayerXPos, HealthXPos, TimeXPos, KillsXPos, AssistXPos, CashXPos, DeathXPos, PingXPos; var transient float StatusWBox, PlayerWBox, PerkWBox, CashWBox, KillsWBox, AssistWBox, HealthWBox, PingWBox; @@ -16,6 +17,18 @@ var KFPlayerController OwnerPC; var Color PingColor; var float PingBars,IdealPing,MaxPing; +// Groups +var array PlayerGroups; +var array PlayerInfos; + +var string SystemAdminRank; +var TextColor SystemAdminColor; +var Fields SystemAdminApplyColorToFields; + +var string SystemPlayerRank; +var TextColor SystemPlayerColor; +var Fields SystemPlayerApplyColorToFields; + function InitMenu() { Super.InitMenu(); @@ -246,9 +259,47 @@ function DrawPlayerEntry( Canvas C, int Index, float YOffset, float Height, floa local byte Level, PrestigeLevel; local bool bIsZED; local int Ping; + + local PlayerGroupEntry Group; + local bool HasGroup; + local int PlayerInfoIndex, PlayerGroupIndex; YOffset *= 1.05; KFPRI = KFPRIArray[Index]; + + HasGroup = false; + PlayerInfoIndex = PlayerInfos.Find('UID', KFPRI.UniqueId); + if (PlayerInfoIndex != INDEX_NONE ) + { + PlayerGroupIndex = PlayerGroups.Find('ID', PlayerInfos[PlayerInfoIndex].GroupID); + if (PlayerGroupIndex != INDEX_NONE) + { + HasGroup = true; + Group = PlayerGroups[PlayerGroupIndex]; + } + } + + if (KFPRI.bAdmin) + { + if (!HasGroup || (HasGroup && !Group.OverrideAdminRank)) + { + Group.Rank = SystemAdminRank; + Group.Color = SystemAdminColor; + Group.ApplyColorToFields = SystemAdminApplyColorToFields; + HasGroup = true; + } + } + else // Player + { + if (!HasGroup) + { + Group.Rank = SystemPlayerRank; + Group.Color = SystemPlayerColor; + Group.ApplyColorToFields = SystemPlayerApplyColorToFields; + HasGroup = true; + } + } + // Now all players belongs to 'Group' if( KFGRI.bVersusGame ) bIsZED = KFTeamInfo_Zeds(KFPRI.Team) != None; @@ -266,21 +317,19 @@ function DrawPlayerEntry( Canvas C, int Index, float YOffset, float Height, floa C.SetDrawColor(250,250,250,255); - // Status - if (KFPRI.bAdmin) - { - S = "Admin"; - } - else - { - S = "Player"; - } + // Rank + if (Group.ApplyColorToFields.Rank) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); + S = Group.Rank; DrawTextShadowHLeftVCenter(S, StatusXPos, TextYOffset, FontScalar); + C.SetDrawColor(250,250,250,255); // Perk if( bIsZED ) { C.SetDrawColor(255,0,0,255); + if (Group.ApplyColorToFields.Perk) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); C.SetPos (PerkXPos, YOffset - ((Height-5) * 0.5f)); C.DrawRect (Height-5, Height-5, Texture2D'UI_Widgets.MenuBarWidget_SWF_IF'); @@ -315,16 +364,21 @@ function DrawPlayerEntry( Canvas C, int Index, float YOffset, float Height, floa } C.SetDrawColor(250,250,250,255); + if (Group.ApplyColorToFields.Perk) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); S = Level@KFPRI.CurrentPerkClass.default.PerkName; DrawTextShadowHLeftVCenter(S, PerkXPos, TextYOffset, FontScalar); } else { C.SetDrawColor(250,250,250,255); + if (Group.ApplyColorToFields.Perk) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); S = "No Perk"; DrawTextShadowHLeftVCenter(S, PerkXPos, TextYOffset, FontScalar); } } + C.SetDrawColor(250,250,250,255); // Avatar if( KFPRI.Avatar != None ) @@ -339,20 +393,29 @@ function DrawPlayerEntry( Canvas C, int Index, float YOffset, float Height, floa } else if( !KFPRI.bBot ) CheckAvatar(KFPRI, OwnerPC); + C.SetDrawColor(250,250,250,255); // Player + if (Group.ApplyColorToFields.Player) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); if( Len(KFPRI.PlayerName) > 25 ) S = Left(KFPRI.PlayerName, 25); else S = KFPRI.PlayerName; DrawTextShadowHLeftVCenter(S, PlayerXPos, TextYOffset, FontScalar); - C.SetDrawColor(255,255,255,255); + C.SetDrawColor(250,250,250,255); // Kill + if (Group.ApplyColorToFields.Kills) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); DrawTextShadowHVCenter(string (KFPRI.Kills), KillsXPos, TextYOffset, KillsWBox, FontScalar); + C.SetDrawColor(250,250,250,255); // Assist + if (Group.ApplyColorToFields.Assists) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); DrawTextShadowHVCenter(string (KFPRI.Assists), AssistXPos, TextYOffset, AssistWBox, FontScalar); + C.SetDrawColor(250,250,250,255); // Cash if( bIsZED ) @@ -365,9 +428,11 @@ function DrawPlayerEntry( Canvas C, int Index, float YOffset, float Height, floa C.SetDrawColor(250, 250, 100, 255); StrValue = GetNiceSize(int(KFPRI.Score)); } + if (Group.ApplyColorToFields.Dosh) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); DrawTextShadowHVCenter(StrValue, CashXPos, TextYOffset, CashWBox, FontScalar); - C.SetDrawColor(255,255,255,255); + C.SetDrawColor(250,250,250,255); // Health if( !KFPRI.bReadyToPlay && KFGRI.bMatchHasBegun ) @@ -400,6 +465,8 @@ function DrawPlayerEntry( Canvas C, int Index, float YOffset, float Height, floa S = string (KFPRI.PlayerHealth) @"HP"; } + if (Group.ApplyColorToFields.Health) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); DrawTextShadowHVCenter(S, HealthXPos, TextYOffset, HealthWBox, FontScalar); C.SetDrawColor(250,250,250,255); @@ -421,8 +488,10 @@ function DrawPlayerEntry( Canvas C, int Index, float YOffset, float Height, floa } C.TextSize(MaxPing, XL, YL, FontScalar, FontScalar); - + if (Group.ApplyColorToFields.Ping) + C.SetDrawColor(Group.Color.R,Group.Color.G,Group.Color.B,255); DrawTextShadowHVCenter(S, PingXPos, TextYOffset, PingWBox/2, FontScalar); + C.SetDrawColor(250,250,250,255); DrawPingBars(C, YOffset + (Height/2) - ((Height*0.5)/2), Width - (Height*0.5) - (Owner.HUDOwner.ScaledBorderSize*2), Height*0.5, Height*0.5, float(Ping)); } diff --git a/ScoreboardExt/Classes/PlayerGroups.uc b/ScoreboardExt/Classes/PlayerGroups.uc new file mode 100644 index 0000000..12ac7f1 --- /dev/null +++ b/ScoreboardExt/Classes/PlayerGroups.uc @@ -0,0 +1,5 @@ +class PlayerGroups extends Object + dependson(Types) + config(ScoreboardExt); + +var config array PlayerGroup; diff --git a/ScoreboardExt/Classes/PlayerInfos.uc b/ScoreboardExt/Classes/PlayerInfos.uc new file mode 100644 index 0000000..ee251e0 --- /dev/null +++ b/ScoreboardExt/Classes/PlayerInfos.uc @@ -0,0 +1,5 @@ +class PlayerInfos extends Object + dependson(Types) + config(ScoreboardExt); + +var config array PlayerInfo; diff --git a/ScoreboardExt/Classes/ScoreboardExtMut.uc b/ScoreboardExt/Classes/ScoreboardExtMut.uc index 1e0a0f4..036fd1d 100644 --- a/ScoreboardExt/Classes/ScoreboardExtMut.uc +++ b/ScoreboardExt/Classes/ScoreboardExtMut.uc @@ -1,11 +1,170 @@ -class ScoreboardExtMut extends KFMutator; +class ScoreboardExtMut extends KFMutator + dependson(PlayerGroups, PlayerInfos) + config(ScoreboardExt); + +const SteamIDLen = 17; +const UniqueIDLen = 18; + +const CurrentVersion = 1; + +var config int ConfigVersion; + +struct SClient +{ + var ScoreboardExtRepInfo RepInfo; + var KFPlayerController KFPC; +}; + +var private array RepClients; + +var private array UIDInfos; function PostBeginPlay() { Super.PostBeginPlay(); - WorldInfo.Game.HUDType = class'ScoreboardExtHUD'; + WorldInfo.Game.HUDType = class'ScoreboardExtHUD'; + InitConfig(); + LoadGroupPlayers(); } -defaultproperties +function NotifyLogin(Controller C) { + AddPlayerInfo(C); + Super.NotifyLogin(C); +} + +function NotifyLogout(Controller C) +{ + RemovePlayerInfo(C); + Super.NotifyLogout(C); +} + +private function InitConfig() +{ + local PlayerGroupEntry ExampleGroup; + local PlayerInfoEntry ExamplePlayer; + + // Update from config version to current version if needed + switch (ConfigVersion) + { + case 0: // which means there is no config right now + // Default admin + class'SystemAdminGroup'.default.Rank = "Admin"; + class'SystemAdminGroup'.default.Color.R = 250; + class'SystemAdminGroup'.default.Color.G = 0; + class'SystemAdminGroup'.default.Color.B = 0; + class'SystemAdminGroup'.static.StaticSaveConfig(); + + // Default player + class'SystemPlayerGroup'.default.Rank = "Player"; + class'SystemPlayerGroup'.default.Color.R = 250; + class'SystemPlayerGroup'.default.Color.G = 250; + class'SystemPlayerGroup'.default.Color.B = 250; + class'SystemPlayerGroup'.static.StaticSaveConfig(); + + // Example group + ExampleGroup.ID = 0; + ExampleGroup.Rank = "Scoreboard Creator"; + ExampleGroup.Color.R = 130; + ExampleGroup.Color.G = 250; + ExampleGroup.Color.B = 235; + ExampleGroup.OverrideAdminRank = true; + class'PlayerGroups'.default.PlayerGroup.AddItem(ExampleGroup); + class'PlayerGroups'.static.StaticSaveConfig(); + + // Example player + ExamplePlayer.PlayerID = "76561198001617867"; // GenZmeY SteamID64 + ExamplePlayer.GroupID = ExampleGroup.ID; + class'PlayerInfos'.default.PlayerInfo.AddItem(ExamplePlayer); + class'PlayerInfos'.static.StaticSaveConfig(); + + case 2147483647: + `log("[ScoreboardExt] Config updated to version"@CurrentVersion); + break; + case CurrentVersion: + `log("[ScoreboardExt] Config is up-to-date"); + break; + default: + `log("[ScoreboardExt] Warn: The config version is higher than the current version (are you using an old mutator?)"); + `log("[ScoreboardExt] Warn: Config version is"@ConfigVersion@"but current version is"@CurrentVersion); + `log("[ScoreboardExt] Warn: The config version will be changed to "@CurrentVersion); + break; + } + + ConfigVersion = CurrentVersion; + SaveConfig(); +} + +private function LoadGroupPlayers() +{ + local PlayerInfoEntry Player; + local OnlineSubsystem steamworks; + local UIDInfoEntry UIDInfo; + + steamworks = class'GameEngine'.static.GetOnlineSubsystem(); + + foreach class'PlayerInfos'.default.PlayerInfo(Player) + { + UIDInfo.GroupID = Player.GroupID; + if (Len(Player.PlayerID) == UniqueIDLen && steamworks.StringToUniqueNetId(Player.PlayerID, UIDInfo.UID)) + { + if (UIDInfos.Find('Uid', UIDInfo.UID) == INDEX_NONE) + UIDInfos.AddItem(UIDInfo); + } + else if (Len(Player.PlayerID) == SteamIDLen && steamworks.Int64ToUniqueNetId(Player.PlayerID, UIDInfo.UID)) + { + if (UIDInfos.Find('Uid', UIDInfo.UID) == INDEX_NONE) + UIDInfos.AddItem(UIDInfo); + } + else `Log("[ScoreboardExt] WARN: Can't add player:"@Player.PlayerID); + } +} + +function AddPlayerInfo(Controller C) +{ + local KFPlayerController KFPC; + local SClient RepClient; + + KFPC = KFPlayerController(C); + if (KFPC == None) + return; + + RepClient.RepInfo = Spawn(class'ScoreboardExtRepInfo', KFPC); + RepClient.KFPC = KFPC; + + RepClients.AddItem(RepClient); + + RepClient.RepInfo.ClientInit( + class'PlayerGroups'.default.PlayerGroup, + UIDInfos, + class'SystemAdminGroup'.default.Rank, + class'SystemAdminGroup'.default.Color, + class'SystemAdminGroup'.default.ApplyColorToFields, + class'SystemPlayerGroup'.default.Rank, + class'SystemPlayerGroup'.default.Color, + class'SystemPlayerGroup'.default.ApplyColorToFields); +} + +function RemovePlayerInfo(Controller C) +{ + local KFPlayerController KFPC; + local int Index; + + KFPC = KFPlayerController(C); + if (KFPC == None) + return; + + Index = RepClients.Find('KFPC', KFPC); + if (Index == INDEX_NONE) + return; + + if (RepClients[Index].RepInfo != None) + RepClients[Index].RepInfo.Destroy(); + + RepClients.Remove(Index, 1); +} + +DefaultProperties +{ + } \ No newline at end of file diff --git a/ScoreboardExt/Classes/ScoreboardExtRepInfo.uc b/ScoreboardExt/Classes/ScoreboardExtRepInfo.uc new file mode 100644 index 0000000..2c1a347 --- /dev/null +++ b/ScoreboardExt/Classes/ScoreboardExtRepInfo.uc @@ -0,0 +1,62 @@ +class ScoreboardExtRepInfo extends ReplicationInfo; + +var private array PlayerInfos; +var private array PlayerGroups; + +var private string SystemAdminRank; +var private TextColor SystemAdminColor; +var private Fields SystemAdminApplyColorToFields; + +var private string SystemPlayerRank; +var private TextColor SystemPlayerColor; +var private Fields SystemPlayerApplyColorToFields; + +public reliable client final function ClientInit( + array _PlayerGroups, + array _PlayerInfos, + string _SystemAdminRank, + TextColor _SystemAdminColor, + Fields _SystemAdminApplyColorToFields, + string _SystemPlayerRank, + TextColor _SystemPlayerColor, + Fields _SystemPlayerApplyColorToFields) +{ + PlayerGroups = _PlayerGroups; + PlayerInfos = _PlayerInfos; + SystemAdminRank = _SystemAdminRank; + SystemAdminColor = _SystemAdminColor; + SystemAdminApplyColorToFields = _SystemAdminApplyColorToFields; + SystemPlayerRank = _SystemPlayerRank; + SystemPlayerColor = _SystemPlayerColor; + SystemPlayerApplyColorToFields = _SystemPlayerApplyColorToFields; + + ClientApply(); +} + +private reliable client final function ClientApply() +{ + local KFScoreBoard SC; + + SC = ScoreboardExtHUD(PlayerController(Owner).myHUD).Scoreboard; + if (SC == None) + { + SetTimer(0.5f, false, nameof(ClientApply)); + return; + } + + SC.PlayerGroups = PlayerGroups; + SC.PlayerInfos = PlayerInfos; + SC.SystemAdminRank = SystemAdminRank; + SC.SystemAdminColor = SystemAdminColor; + SC.SystemAdminApplyColorToFields = SystemAdminApplyColorToFields; + SC.SystemPlayerRank = SystemPlayerRank; + SC.SystemPlayerColor = SystemPlayerColor; + SC.SystemPlayerApplyColorToFields = SystemPlayerApplyColorToFields; + + Destroy(); +} + +defaultproperties +{ + +} \ No newline at end of file diff --git a/ScoreboardExt/Classes/SystemAdminGroup.uc b/ScoreboardExt/Classes/SystemAdminGroup.uc new file mode 100644 index 0000000..4087fd1 --- /dev/null +++ b/ScoreboardExt/Classes/SystemAdminGroup.uc @@ -0,0 +1,7 @@ +class SystemAdminGroup extends Object + dependson(Types) + config(ScoreboardExt); + +var config string Rank; +var config TextColor Color; +var config Fields ApplyColorToFields; diff --git a/ScoreboardExt/Classes/SystemPlayerGroup.uc b/ScoreboardExt/Classes/SystemPlayerGroup.uc new file mode 100644 index 0000000..90eb329 --- /dev/null +++ b/ScoreboardExt/Classes/SystemPlayerGroup.uc @@ -0,0 +1,7 @@ +class SystemPlayerGroup extends Object + dependson(Types) + config(ScoreboardExt); + +var config string Rank; +var config TextColor Color; +var config Fields ApplyColorToFields; diff --git a/ScoreboardExt/Classes/Types.uc b/ScoreboardExt/Classes/Types.uc new file mode 100644 index 0000000..30d19b1 --- /dev/null +++ b/ScoreboardExt/Classes/Types.uc @@ -0,0 +1,58 @@ +class Types extends Object; + +struct TextColor +{ + var byte R, G, B; + + StructDefaultProperties + { + R=250 + G=250 + B=250 + } +}; + +struct Fields +{ + var bool Rank; + var bool Player; + var bool Perk; + var bool Dosh; + var bool Kills; + var bool Assists; + var bool Health; + var bool Ping; + + StructDefaultProperties + { + Rank = true; + Player = true; + Perk = false; + Dosh = false; + Kills = false; + Assists = false; + Health = false; + Ping = false; + } +}; + +struct PlayerGroupEntry +{ + var int ID; + var string Rank; + var TextColor Color; + var bool OverrideAdminRank; + var Fields ApplyColorToFields; +}; + +struct PlayerInfoEntry +{ + var string PlayerID; + var int GroupID; +}; + +struct UIDInfoEntry +{ + var UniqueNetId UID; + var int GroupID; +}; diff --git a/ScoreboardExt/Globals.uci b/ScoreboardExt/Globals.uci index a886177..1c80c22 100644 --- a/ScoreboardExt/Globals.uci +++ b/ScoreboardExt/Globals.uci @@ -19,20 +19,10 @@ `define ITEMBOX_DISABLED 1 `define ITEMBOX_HIGHLIGHTED 2 -`define ITEMBOX_BAR_NORMAL 3 -`define ITEMBOX_BAR_DISABLED 4 -`define ITEMBOX_BAR_HIGHLIGHTED 5 - -`define PROGRESS_BAR_NORMAL 0 -`define PROGRESS_BAR_SELECTED 1 - `define CHECKMARK_NORMAL 0 `define CHECKMARK_DISABLED 1 `define CHECKMARK_HIGHLIGHTED 2 -`define PERK_BOX_SELECTED 0 -`define PERK_BOX_UNSELECTED 1 - `define ARROW_DOWN 0 `define ARROW_LEFT 1 `define ARROW_RIGHT 2 @@ -50,13 +40,7 @@ `define PEN_BLACK 1 `define PEN_GRAY 2 -`define SLIDER_NORMAL 0 -`define SLIDER_GRIP 1 -`define SLIDER_DISABLED 2 - `define CURSOR_DEFAULT 0 `define CURSOR_SELECTION 1 `define CURSOR_RESIZEVERT 2 `define CURSOR_RESIZEHORZ 3 - -`define Print(log) LocalPlayer(class'WorldInfo'.static.GetWorldInfo().GetALocalPlayerController().Player).ViewportClient.ViewportConsole.OutputText(`log) \ No newline at end of file