class YAS extends Info config(YAS); const LatestVersion = 1; const CfgRanks = class'Ranks'; const CfgRankRelations = class'RankRelations'; const CfgMessageOfTheDay = class'MessageOfTheDay'; const UpdateInterval = 1.0f; const MatchUID = "0x"; const MatchPlayerSteamID64 = "76561"; const MatchGroupSteamID64 = "10358279"; var private config int Version; var private config E_LogLevel LogLevel; var private KFGameInfo KFGI; var private KFGameInfo_Survival KFGIS; var private KFGameInfo_Endless KFGIE; var private KFGameReplicationInfo KFGRI; var private KFOnlineGameSettings KFOGS; var private OnlineSubsystemSteamworks OSS; var private Array RepInfos; var private Array PlayerRelations; var private Array GroupRelations; var private int LastMessageID; public simulated function bool SafeDestroy() { `Log_Trace(); return (bPendingDelete || bDeleteMe || Destroy()); } public event PreBeginPlay() { `Log_Trace(); if (WorldInfo.NetMode == NM_Client) { `Log_Fatal("NetMode == NM_Client"); SafeDestroy(); return; } Super.PreBeginPlay(); PreInit(); } public event PostBeginPlay() { `Log_Trace(); if (bPendingDelete || bDeleteMe) return; Super.PostBeginPlay(); PostInit(); } private function PreInit() { `Log_Trace(); if (Version == `NO_CONFIG) { LogLevel = LL_Info; SaveConfig(); } CfgRanks.static.InitConfig(Version, LatestVersion); CfgRankRelations.static.InitConfig(Version, LatestVersion); CfgMessageOfTheDay.static.InitConfig(Version, LatestVersion); switch (Version) { case `NO_CONFIG: `Log_Info("Config created"); case MaxInt: `Log_Info("Config updated to version" @ LatestVersion); break; case LatestVersion: `Log_Info("Config is up-to-date"); break; default: `Log_Warn("The config version is higher than the current version (are you using an old mutator?)"); `Log_Warn("Config version is" @ Version @ "but current version is" @ LatestVersion); `Log_Warn("The config version will be changed to" @ LatestVersion); break; } if (LatestVersion != Version) { Version = LatestVersion; SaveConfig(); } if (LogLevel == LL_WrongLevel) { LogLevel = LL_Info; `Log_Warn("Wrong 'LogLevel', return to default value"); SaveConfig(); } `Log_Base("LogLevel:" @ LogLevel); OSS = OnlineSubsystemSteamworks(class'GameEngine'.static.GetOnlineSubsystem()); if (OSS != None) { InitRanks(); } else { `Log_Error("Can't get online subsystem!"); } } private function InitRanks() { local Array Relations; local RankRelation Relation; Relations = CfgRankRelations.default.Relation; foreach Relations(Relation) { if (IsUID(Relation.ObjectID) || IsPlayerSteamID64(Relation.ObjectID)) { AddRelation(Relation, PlayerRelations); } else if (IsGroupSteamID64(Relation.ObjectID)) { AddRelation(Relation, GroupRelations); } else { `Log_Warn("Can't parse ID:" @ Relation.ObjectID); } } } private function AddRelation(RankRelation Relation, out Array OutArray) { local CachedRankRelation CachedRankRelation; local Array Ranks; local Rank Rank; if (AnyToUID(Relation.ObjectID, CachedRankRelation.UID)) { CachedRankRelation.RawID = Relation.ObjectID; Ranks = CfgRanks.default.Rank; foreach Ranks(Rank) { if (Rank.RankID == Relation.RankID) { CachedRankRelation.Rank = Rank; break; } } if (CachedRankRelation.Rank.RankID > 0) { OutArray.AddItem(CachedRankRelation); } else { `Log_Warn("Rank with ID" @ Relation.RankID @ "not found"); } } else { `Log_Warn("Can't convert to UniqueNetID:" @ Relation.ObjectID); } } private static function bool IsUID(String ID) { return (Left(ID, Len(MatchUID)) ~= MatchUID); } private static function bool IsPlayerSteamID64(String ID) { return (Left(ID, Len(MatchPlayerSteamID64)) ~= MatchPlayerSteamID64); } private static function bool IsGroupSteamID64(String ID) { return (Left(ID, Len(MatchGroupSteamID64)) ~= MatchGroupSteamID64); } private function bool AnyToUID(String ID, out UniqueNetId UID) { return IsUID(ID) ? OSS.StringToUniqueNetId(ID, UID) : OSS.Int64ToUniqueNetId(ID, UID); } private function PostInit() { `Log_Trace(); if (WorldInfo == None || WorldInfo.Game == None) { SetTimer(1.0f, false, nameof(PostInit)); return; } KFGI = KFGameInfo(WorldInfo.Game); if (KFGI == None || KFGameInfo_VersusSurvival(KFGI) != None) // VersusSurvival is not supported (yet) { `Log_Fatal("Incompatible gamemode:" @ WorldInfo.Game); SafeDestroy(); return; } KFGI.HUDType = class'YAS_HUD'; if (KFGI.GameReplicationInfo == None) { SetTimer(1.0f, false, nameof(PostInit)); return; } KFGRI = KFGameReplicationInfo(KFGI.GameReplicationInfo); if (KFGRI == None) { `Log_Fatal("Incompatible Replication info:" @ KFGI.GameReplicationInfo); SafeDestroy(); return; } if (KFGI.PlayfabInter != None && KFGI.PlayfabInter.GetGameSettings() != None) { KFOGS = KFOnlineGameSettings(KFGI.PlayfabInter.GetGameSettings()); } else if (KFGI.GameInterface != None) { KFOGS = KFOnlineGameSettings( KFGI.GameInterface.GetGameSettings( KFGI.PlayerReplicationInfoClass.default.SessionName)); } if (KFOGS == None) { SetTimer(1.0f, false, nameof(PostInit)); return; } KFGIS = KFGameInfo_Survival(KFGI); KFGIE = KFGameInfo_Endless(KFGI); SetTimer(UpdateInterval, true, nameof(UpdateTimer)); if (CfgMessageOfTheDay.default.Message.Length > 0) { MessageOfTheDayTimer(); SetTimer(CfgMessageOfTheDay.default.DisplayTime, true, nameof(MessageOfTheDayTimer)); } } private function UpdateTimer() { local YAS_RepInfoOwner RepInfo; foreach RepInfos(RepInfo) { RepInfo.DynamicServerName = KFOGS.OwningPlayerName; RepInfo.UsesStats = KFOGS.bUsesStats; RepInfo.Custom = KFOGS.bCustom; RepInfo.PasswordRequired = KFOGS.bRequiresPassword; } } private function MessageOfTheDayTimer() { local YAS_RepInfoOwner RepInfo; local int MessageIndex; if (CfgMessageOfTheDay.default.bRandomize) { MessageIndex = Rand(CfgMessageOfTheDay.default.Message.Length); } else { MessageIndex = LastMessageID + 1; } if (MessageIndex == LastMessageID) { ++MessageIndex; } if (MessageIndex >= CfgMessageOfTheDay.default.Message.Length) { MessageIndex = 0; } foreach RepInfos(RepInfo) { RepInfo.MessageOfTheDay = CfgMessageOfTheDay.default.Message[MessageIndex]; } LastMessageID = MessageIndex; } public function NotifyLogin(Controller C) { local YAS_RepInfoOwner RepInfo; `Log_Trace(); RepInfo = CreateRepInfo(C); if (RepInfo == None) { `Log_Error("Can't create RepInfo for:" @ C); return; } InitRank(RepInfo); } public function NotifyLogout(Controller C) { local YAS_RepInfoOwner RepInfo; `Log_Trace(); RepInfo = FindRepInfo(C); if (!DestroyRepInfo(RepInfo)) { `Log_Error("Can't destroy RepInfo of:" @ C); } } public function YAS_RepInfoOwner CreateRepInfo(Controller C) { local YAS_RepInfoOwner OwnerRepInfo; local YAS_RepInfoPlayer PlayerRepInfo; `Log_Trace(); OwnerRepInfo = Spawn(class'YAS_RepInfoOwner', C); PlayerRepInfo = Spawn(class'YAS_RepInfoPlayer', C); if (OwnerRepInfo != None && PlayerRepInfo != None) { RepInfos.AddItem(OwnerRepInfo); OwnerRepInfo.PlayerRepInfo = PlayerRepInfo; OwnerRepInfo.YAS = Self; OwnerRepInfo.LogLevel = LogLevel; OwnerRepInfo.RankPlayer = CfgRanks.default.Player; OwnerRepInfo.RankAdmin = CfgRanks.default.Admin; OwnerRepInfo.MessageOfTheDay = CfgMessageOfTheDay.default.Message[LastMessageID]; return OwnerRepInfo; } return None; } private function YAS_RepInfoOwner FindRepInfo(Controller C) { local YAS_RepInfoOwner RepInfo; if (C == None) return None; foreach RepInfos(RepInfo) { if (RepInfo.Owner == C) { return RepInfo; } } return None; } public function bool DestroyRepInfo(YAS_RepInfoOwner RepInfo) { `Log_Trace(); if (RepInfo == None) return false; RepInfos.RemoveItem(RepInfo); RepInfo.PlayerRepInfo.SafeDestroy(); RepInfo.SafeDestroy(); return true; } private function InitRank(YAS_RepInfoOwner RepInfo) { local CachedRankRelation Rel; local String JoinedGroupIDs; local PlayerReplicationInfo PRI; local KFPlayerController KFPC; local Array StringGroupIDs; `Log_Trace(); KFPC = RepInfo.GetKFPC(); if (KFPC == None) return; PRI = KFPC.PlayerReplicationInfo; if (PRI == None) return; foreach PlayerRelations(Rel) { if (Rel.UID.Uid == PRI.UniqueID.Uid) { RepInfo.PlayerRepInfo.Rank = Rel.Rank; break; } } if (RepInfo.PlayerRepInfo.Rank.RankID <= 0 && !KFPC.bIsEosPlayer) { foreach GroupRelations(Rel) { StringGroupIDs.AddItem(Rel.RawID); } JoinArray(StringGroupIDs, JoinedGroupIDs); RepInfo.CheckGroupRanks(JoinedGroupIDs); } } public function Rank RankByGroupID(UniqueNetId GroupUID) { local CachedRankRelation Rel; foreach GroupRelations(Rel) if (Rel.UID == GroupUID) break; return Rel.Rank; } DefaultProperties { }