From cf0903cd14b11ffba1cc9361163504050f9c708c Mon Sep 17 00:00:00 2001 From: GenZmeY Date: Wed, 17 Aug 2022 21:25:39 +0300 Subject: [PATCH] RPL --- Localization/INT/MSKGS.int | Bin 592 -> 1092 bytes Localization/RUS/MSKGS.rus | Bin 544 -> 1042 bytes MSKGS-SRV/Classes/CfgLevels.uc | 139 +++++++++++ MSKGS-SRV/Classes/CfgPerks.uc | 106 ++++++++ MSKGS-SRV/Classes/MSKGS.uc | 65 ++++- MSKGS/Classes/MSKGS_Endless.uc | 2 +- MSKGS/Classes/MSKGS_GFxMenu_Perks.uc | 42 ++++ MSKGS/Classes/MSKGS_GFxMenu_Trader.uc | 8 + MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager.uc | 11 + .../MSKGS_GFxMoviePlayer_Manager_Versus.uc | 11 + .../MSKGS_GFxPerksContainer_Selection.uc | 51 ++++ .../Classes/MSKGS_GFxTraderContainer_Store.uc | 20 ++ MSKGS/Classes/MSKGS_LocalMessage.uc | 47 +++- MSKGS/Classes/MSKGS_Objective.uc | 2 +- MSKGS/Classes/MSKGS_PlayerController.uc | 230 ++++++++++++++++++ MSKGS/Classes/MSKGS_RepInfo.uc | 8 +- MSKGS/Classes/MSKGS_Survival.uc | 2 +- MSKGS/Classes/MSKGS_VersusSurvival.uc | 2 +- MSKGS/Classes/MSKGS_WeeklySurvival.uc | 2 +- 19 files changed, 728 insertions(+), 20 deletions(-) create mode 100644 MSKGS-SRV/Classes/CfgLevels.uc create mode 100644 MSKGS-SRV/Classes/CfgPerks.uc create mode 100644 MSKGS/Classes/MSKGS_GFxMenu_Perks.uc create mode 100644 MSKGS/Classes/MSKGS_GFxMenu_Trader.uc create mode 100644 MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager.uc create mode 100644 MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager_Versus.uc create mode 100644 MSKGS/Classes/MSKGS_GFxPerksContainer_Selection.uc create mode 100644 MSKGS/Classes/MSKGS_GFxTraderContainer_Store.uc create mode 100644 MSKGS/Classes/MSKGS_PlayerController.uc diff --git a/Localization/INT/MSKGS.int b/Localization/INT/MSKGS.int index db4ef3e3800e4d6f5d6df3987af48ff2d44cce51..08e2f5dd652224ba2ccb347a92054c75f85aace0 100644 GIT binary patch literal 1092 zcmb7D?MlNy5S-tF?{EsDBIW_41}a5=*h)bKMMTnGw54gQ`S9cA)!Dt&OWOmLK)CGA z&d$zWzCQ2J!zIpf#`godm}7_p8KWr*J_(+9y2mCq&}Tfs2fuUT$9PrD32Wv=mN;cB z*V8e!(ZX{BAH$GoQDZRpsWPmbGh1TBe8E$p9fUo{7McFi`}d9qD~h~=7(48G!}x$Y-b$Fh2fyb&!sku6B2+s%xb^@$ctZEif%+7yt{cei`OZyV6#afY)C!-&1A0Ao|D z;g*~~GWU>ugxzgWT=c9Rb#Tboj895z8BlS{e8s+2al6DA>PXZ_!#`>ziTD-jEV||12%mUu1L{h~rbLME@=rSLmgh(xH|00K;=o=2 delta 7 OcmX@Yae-w+022TVWdfrB diff --git a/Localization/RUS/MSKGS.rus b/Localization/RUS/MSKGS.rus index 37f2c1bf486cae8a2fa50a55120300dca71eb669..a30001671d837bbab36d67a4146a87c470242c8f 100644 GIT binary patch literal 1042 zcma)*T}uK{5QgXCTm{{ATbU3Pk!Tp!w!5}jNvI`M5JZH1B3g#p*PpMRImflN_Cl6D zoIM}!yz|WL_t&K~WxSTU^yF4r(q;8t20Sf!WOgO9G9yjaTk^?wpYv^bvuF0W z)8ph&4q5BlSs+>QZh}9-)Y0!Q|1} zF(>G09FI4STw%WU$Jx!;e<;fm$3J6rXi5C$r!g1MKO%$egsMkwsyZCsnbge41?*g2 z4KzPQl~!OJv9p?zaUHS`=%r^_CQAr;fsU72G(s>phWy`qEonS;KCX;6^ zWWNTpyopsJD%eHo9Y1$;$Gxq2mm2R|hb?(!-}#(JQRyEr7IEjJrIaevHni0ZOx-9e zU!LfcXKu!N+8yho9p#hUaoo;1KOkD$R^`T?XmYo7xYvwxrIdeN?Bj00|I@?kGhS}-n$Ai4($&JVY@DxY wJmsJ?M default.NoRestrictionsMax) + { + `Log_Error("Max" @ "(" $ default.Max $ ")" @ "must be equal or less than" @ default.NoRestrictionsMax); + } + + if (default.Min > default.Max) + { + `Log_Error("Min" @ "(" $ default.Min $ ")" @ "must be less than Max (" $ default.Max $ ")"); + } + + if (!IsValidHexColor(default.HexColorInfo, LogLevel)) + { + `Log_Error("HexColorInfo" @ "(" $ default.HexColorInfo $ ")" @ "is not valid hex color"); + } + + if (!IsValidHexColor(default.HexColorWarn, LogLevel)) + { + `Log_Error("HexColorWarn" @ "(" $ default.HexColorWarn $ ")" @ "is not valid hex color"); + } + + if (!IsValidHexColor(default.HexColorError, LogLevel)) + { + `Log_Error("HexColorError" @ "(" $ default.HexColorError $ ")" @ "is not valid hex color"); + } +} + +public static function bool Available(byte Level) +{ + return Level >= MinLevel() && Level <= MaxLevel(); +} + +public static function byte MinLevel() +{ + return byte(default.Min); +} + +public static function byte MaxLevel() +{ + return byte(default.Max); +} + +protected static function ApplyDefault() +{ + default.Min = default.DefaultMin; + default.Max = default.DefaultMax; + + default.DisconnectTime = 15; + + default.HexColorInfo = class'KFLocalMessage'.default.EventColor; + default.HexColorWarn = class'KFLocalMessage'.default.PriorityColor; + default.HexColorError = class'KFLocalMessage'.default.InteractionColor; +} + +private static function bool IsValidHexColor(String HexColor, E_LogLevel LogLevel) +{ + local byte Index; + + `Log_TraceStatic(); + + if (len(HexColor) != 6) return false; + + HexColor = Locs(HexColor); + + for (Index = 0; Index < 6; ++Index) + { + switch (Mid(HexColor, Index, 1)) + { + case "0": break; + case "1": break; + case "2": break; + case "3": break; + case "4": break; + case "5": break; + case "6": break; + case "7": break; + case "8": break; + case "9": break; + case "a": break; + case "b": break; + case "c": break; + case "d": break; + case "e": break; + case "f": break; + default: return false; + } + } + + return true; +} + +defaultproperties +{ + DefaultMin = 0 + DefaultMax = `MAX_PERK_LEVEL + + NoRestrictionsMin = 0 + NoRestrictionsMax = `MAX_PERK_LEVEL +} diff --git a/MSKGS-SRV/Classes/CfgPerks.uc b/MSKGS-SRV/Classes/CfgPerks.uc new file mode 100644 index 0000000..a2d79ed --- /dev/null +++ b/MSKGS-SRV/Classes/CfgPerks.uc @@ -0,0 +1,106 @@ +class CfgPerks extends Object + config(RPL) + abstract; + +var public config bool bHideDisabledPerks; + +var private config bool bBerserker; +var private config bool bCommando; +var private config bool bSupport; +var private config bool bFieldMedic; +var private config bool bDemolitionist; +var private config bool bFirebug; +var private config bool bGunslinger; +var private config bool bSharpshooter; +var private config bool bSwat; +var private config bool bSurvivalist; + +public static function InitConfig(int Version, int LatestVersion, E_LogLevel LogLevel) +{ + switch (Version) + { + case `NO_CONFIG: + ApplyDefault(); + + default: break; + } + + if (LatestVersion != Version) + { + StaticSaveConfig(); + } +} + +public static function PerkAvailableData Load(E_LogLevel LogLevel) +{ + local PerkAvailableData PerkAvailableData; + + PerkAvailableData.bPerksAvailableLimited = PerksAvailableLimited(); + + PerkAvailableData.bBerserkerAvailable = default.bBerserker; + PerkAvailableData.bCommandoAvailable = default.bCommando; + PerkAvailableData.bSupportAvailable = default.bSupport; + PerkAvailableData.bFieldMedicAvailable = default.bFieldMedic; + PerkAvailableData.bDemolitionistAvailable = default.bDemolitionist; + PerkAvailableData.bFirebugAvailable = default.bFirebug; + PerkAvailableData.bGunslingerAvailable = default.bGunslinger; + PerkAvailableData.bSharpshooterAvailable = default.bSharpshooter; + PerkAvailableData.bSwatAvailable = default.bSwat; + PerkAvailableData.bSurvivalistAvailable = default.bSurvivalist; + + return PerkAvailableData; +} + +public static function bool Available(class Perk) +{ + switch (Perk) + { + case class'KFPerk_Berserker': return default.bBerserker; + case class'KFPerk_Commando': return default.bCommando; + case class'KFPerk_Support': return default.bSupport; + case class'KFPerk_FieldMedic': return default.bFieldMedic; + case class'KFPerk_Demolitionist': return default.bDemolitionist; + case class'KFPerk_Firebug': return default.bFirebug; + case class'KFPerk_Gunslinger': return default.bGunslinger; + case class'KFPerk_Sharpshooter': return default.bSharpshooter; + case class'KFPerk_SWAT': return default.bSwat; + case class'KFPerk_Survivalist': return default.bSurvivalist; + default: return true; + } +} + +private static function bool PerksAvailableLimited() +{ + return ( + !default.bBerserker || + !default.bCommando || + !default.bSupport || + !default.bFieldMedic || + !default.bDemolitionist || + !default.bFirebug || + !default.bGunslinger || + !default.bSharpshooter || + !default.bSwat || + !default.bSurvivalist); +} + +private static function ApplyDefault() +{ + default.bHideDisabledPerks = true; + + default.bBerserker = true; + default.bCommando = true; + default.bSupport = true; + default.bFieldMedic = true; + default.bDemolitionist = true; + default.bFirebug = true; + default.bGunslinger = true; + default.bSharpshooter = true; + default.bSwat = true; + default.bSurvivalist = true; +} + +defaultproperties +{ + +} diff --git a/MSKGS-SRV/Classes/MSKGS.uc b/MSKGS-SRV/Classes/MSKGS.uc index 7f8d3b3..46ea6b9 100644 --- a/MSKGS-SRV/Classes/MSKGS.uc +++ b/MSKGS-SRV/Classes/MSKGS.uc @@ -10,6 +10,9 @@ const CfgSpawnManager = class'CfgSpawnManager'; const CfgXPBoost = class'CfgXPBoost'; const CfgSrvRank = class'CfgSrvRank'; +const CfgPerks = class'CfgPerks'; +const CfgLevels = class'CfgLevels'; + const MSKGS_GameInfo = class'MSKGS_GameInfo'; struct ZedMap @@ -91,7 +94,9 @@ private function PreInit() CfgSpawnManager.static.InitConfig(Version, LatestVersion, LogLevel); CfgXPBoost.static.InitConfig(Version, LatestVersion, LogLevel); CfgSrvRank.static.InitConfig(Version, LatestVersion, LogLevel); - + CfgPerks.static.InitConfig(Version, LatestVersion, LogLevel); + CfgLevels.static.InitConfig(Version, LatestVersion, LogLevel); + switch (Version) { case `NO_CONFIG: @@ -132,6 +137,8 @@ private function PreInit() CfgXPBoost.static.Load(LogLevel); CfgSrvRank.static.Load(LogLevel); + CfgLevels.static.Load(LogLevel); + OS = class'GameEngine'.static.GetOnlineSubsystem(); if (OS == None) { @@ -154,6 +161,8 @@ private function PostInit() return; } + WorldInfo.Game.PlayerControllerClass = class'MSKGS_PlayerController'; + KFGI = KFGameInfo(WorldInfo.Game); if (KFGI == None) { @@ -168,14 +177,7 @@ private function PostInit() return; } - KFGRI = KFGameReplicationInfo(KFGI.GameReplicationInfo); - if (KFGRI == None) - { - `Log_Fatal("Incompatible Replication info:" @ KFGI.GameReplicationInfo); - SafeDestroy(); - return; - } - + XPNotifications = false; if (MSKGS_Endless(KFGI) != None) { XPNotifications = true; @@ -185,21 +187,21 @@ private function PostInit() } else if (MSKGS_Objective(KFGI) != None) { - XPNotifications = (KFGI.GameDifficulty != 3); + XPNotifications = true; MSKGS_Objective(KFGI).MSKGS = Self; MSKGS_Objective(KFGI).GI = new MSKGS_GameInfo; MSKGS_Objective(KFGI).LogLevel = LogLevel; } else if (MSKGS_Survival(KFGI) != None) { - XPNotifications = (KFGI.GameDifficulty != 3); + XPNotifications = true; MSKGS_Survival(KFGI).MSKGS = Self; MSKGS_Survival(KFGI).GI = new MSKGS_GameInfo; MSKGS_Survival(KFGI).LogLevel = LogLevel; } else if (MSKGS_VersusSurvival(KFGI) != None) { - XPNotifications = false; + XPNotifications = true; MSKGS_VersusSurvival(KFGI).MSKGS = Self; MSKGS_VersusSurvival(KFGI).GI = new MSKGS_GameInfo; MSKGS_VersusSurvival(KFGI).LogLevel = LogLevel; @@ -212,9 +214,19 @@ private function PostInit() MSKGS_WeeklySurvival(KFGI).LogLevel = LogLevel; } + KFGI.UpdateGameSettings(); + `Log_Info("GameInfo initialized:" @ KFGI); - KFGI.UpdateGameSettings(); + KFGRI = KFGameReplicationInfo(KFGI.GameReplicationInfo); + if (KFGRI == None) + { + `Log_Fatal("Incompatible Replication info:" @ KFGI.GameReplicationInfo); + SafeDestroy(); + return; + } + + KFGRI.PerksAvailableData = CfgPerks.static.Load(LogLevel); ModifySpawnManager(); @@ -313,9 +325,23 @@ public function SetMaxPlayers(int MaxPlayers) public function NotifyLogin(Controller C) { + local MSKGS_PlayerController MSKGSPC; local MSKGS_RepInfo RepInfo; `Log_Trace(); + + MSKGSPC = MSKGS_PlayerController(C); + + if (MSKGSPC == None) + { + `Log_Error("Can't cast" @ C @ "to MSKGS_PlayerController"); + return; + } + + if (CfgPerks.default.bHideDisabledPerks) + { + MSKGSPC.ServerHidePerks(); + } RepInfo = CreateRepInfo(C); if (RepInfo == None) @@ -324,11 +350,22 @@ public function NotifyLogin(Controller C) return; } + MSKGSPC.RepInfo = RepInfo; + MSKGSPC.MinLevel = CfgLevels.static.MinLevel(); + MSKGSPC.MaxLevel = CfgLevels.static.MaxLevel(); + MSKGSPC.DisconnectTimer = CfgLevels.default.DisconnectTime; + if (RepInfo.PlayerType() >= MSKGS_Admin) { `Log_Info("Increase boost:" @ RepInfo.PlayerType()); IncreaseXPBoost(RepInfo.GetKFPC()); } + + RepInfo.WriteToChatLocalized( + MSKGS_AllowedLevels, + CfgLevels.default.HexColorInfo, + String(CfgLevels.static.MinLevel()), + String(CfgLevels.static.MaxLevel())); } public function NotifyLogout(Controller C) @@ -557,6 +594,8 @@ private function int PlayerXPBoost(MSKGS_RepInfo RepInfo) { `Log_Trace(); + `Log_Debug("PlayerType:" @ RepInfo.PlayerType()); + if (RepInfo != None) switch (RepInfo.PlayerType()) { case MSKGS_Owner: return CfgXPBoost.default.BoostOwner; diff --git a/MSKGS/Classes/MSKGS_Endless.uc b/MSKGS/Classes/MSKGS_Endless.uc index 14f2a4c..f73458b 100644 --- a/MSKGS/Classes/MSKGS_Endless.uc +++ b/MSKGS/Classes/MSKGS_Endless.uc @@ -32,5 +32,5 @@ protected function DistributeMoneyAndXP(class MonsterClass, cons defaultproperties { - + KFGFxManagerClass = class'MSKGS_GFxMoviePlayer_Manager' } diff --git a/MSKGS/Classes/MSKGS_GFxMenu_Perks.uc b/MSKGS/Classes/MSKGS_GFxMenu_Perks.uc new file mode 100644 index 0000000..be93e43 --- /dev/null +++ b/MSKGS/Classes/MSKGS_GFxMenu_Perks.uc @@ -0,0 +1,42 @@ +class MSKGS_GFxMenu_Perks extends KFGFxMenu_Perks + dependson(MSKGS_GFxPerksContainer_Selection); + +function PerkChanged(byte NewPerkIndex, bool bClickedIndex) +{ + local KFGameReplicationInfo KFGRI; + local MSKGS_PlayerController MSKGSPC; + + if (KFPC == None) return; + + KFGRI = KFGameReplicationInfo(KFPC.WorldInfo.GRI); + MSKGSPC = MSKGS_PlayerController(KFPC); + + if (KFGRI == None || MSKGSPC == None) return; + + if (!MSKGSPC.IsPerkAllowed(MSKGSPC.PerkList[NewPerkIndex])) return; + + UpdateSkillsHolder(MSKGSPC.PerkList[NewPerkIndex].PerkClass); + + bChangesMadeDuringLobby = !IsMatchStarted(); + + if (bClickedIndex) + { + LastPerkIndex = NewPerkIndex; + bModifiedPerk = true; + + if (MSKGSPC.Pawn == None || !MSKGSPC.Pawn.IsAliveAndWell()) + { + SavePerkData(); + SelectionContainer.SavePerk( NewPerkIndex ); + Manager.CachedProfile.SetProfileSettingValueInt( KFID_SavedPerkIndex, NewPerkIndex ); + } + } + + UpdateContainers(MSKGSPC.PerkList[NewPerkIndex].PerkClass, bClickedIndex); +} + +defaultproperties +{ + SubWidgetBindings.Remove((WidgetName="SelectionContainer",WidgetClass=class'KFGFxPerksContainer_Selection')) + SubWidgetBindings.Add((WidgetName="SelectionContainer",WidgetClass=class'MSKGS_GFxPerksContainer_Selection')) +} diff --git a/MSKGS/Classes/MSKGS_GFxMenu_Trader.uc b/MSKGS/Classes/MSKGS_GFxMenu_Trader.uc new file mode 100644 index 0000000..7211582 --- /dev/null +++ b/MSKGS/Classes/MSKGS_GFxMenu_Trader.uc @@ -0,0 +1,8 @@ +class MSKGS_GFxMenu_Trader extends KFGFxMenu_Trader + dependsOn(MSKGS_GFxTraderContainer_Store); + +defaultproperties +{ + SubWidgetBindings.Remove((WidgetName="shopContainer",WidgetClass=class'KFGFxTraderContainer_Store')) + SubWidgetBindings.Add((WidgetName="shopContainer",WidgetClass=class'MSKGS_GFxTraderContainer_Store')) +} diff --git a/MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager.uc b/MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager.uc new file mode 100644 index 0000000..b92d9fc --- /dev/null +++ b/MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager.uc @@ -0,0 +1,11 @@ +class MSKGS_GFxMoviePlayer_Manager extends KFGFxMoviePlayer_Manager + dependson(MSKGS_GFxMenu_Perks); + +defaultproperties +{ + WidgetBindings.Remove((WidgetName="PerksMenu",WidgetClass=class'KFGFxMenu_Perks')) + WidgetBindings.Add((WidgetName="PerksMenu",WidgetClass=class'MSKGS_GFxMenu_Perks')) + + WidgetBindings.Remove((WidgetName="traderMenu",WidgetClass=class'KFGFxMenu_Trader')) + WidgetBindings.Add((WidgetName="traderMenu",WidgetClass=class'MSKGS_GFxMenu_Trader')) +} diff --git a/MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager_Versus.uc b/MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager_Versus.uc new file mode 100644 index 0000000..2384bce --- /dev/null +++ b/MSKGS/Classes/MSKGS_GFxMoviePlayer_Manager_Versus.uc @@ -0,0 +1,11 @@ +class MSKGS_GFxMoviePlayer_Manager_Versus extends KFGFxMoviePlayer_Manager_Versus + dependson(MSKGS_GFxMenu_Perks, MSKGS_GFxMenu_Trader); + +defaultproperties +{ + WidgetBindings.Remove((WidgetName="PerksMenu",WidgetClass=class'KFGFxMenu_Perks')) + WidgetBindings.Add((WidgetName="PerksMenu",WidgetClass=class'MSKGS_GFxMenu_Perks')) + + WidgetBindings.Remove((WidgetName="traderMenu",WidgetClass=class'KFGFxMenu_Trader')) + WidgetBindings.Add((WidgetName="traderMenu",WidgetClass=class'MSKGS_GFxMenu_Trader')) +} diff --git a/MSKGS/Classes/MSKGS_GFxPerksContainer_Selection.uc b/MSKGS/Classes/MSKGS_GFxPerksContainer_Selection.uc new file mode 100644 index 0000000..7ffa6dc --- /dev/null +++ b/MSKGS/Classes/MSKGS_GFxPerksContainer_Selection.uc @@ -0,0 +1,51 @@ +class MSKGS_GFxPerksContainer_Selection extends KFGFxPerksContainer_Selection; + +var const Texture2D NegativeIcon; + +function UpdatePerkSelection(byte SelectedPerkIndex) +{ + local int Index; + local GFxObject DataProvider; + local GFxObject TempObj; + local MSKGS_PlayerController MSKGSPC; + local byte bTierUnlocked; + local int UnlockedPerkLevel; + local PerkInfo PerkInfo; + + MSKGSPC = MSKGS_PlayerController(GetPC()); + + if (MSKGSPC == None) return; + + DataProvider = CreateArray(); + + foreach MSKGSPC.PerkList(PerkInfo, Index) + { + class'KFPerk'.static.LoadTierUnlockFromConfig(PerkInfo.PerkClass, bTierUnlocked, UnlockedPerkLevel); + TempObj = CreateObject("Object"); + TempObj.SetInt("PerkLevel", PerkInfo.PerkLevel); + TempObj.SetString("Title", PerkInfo.PerkClass.default.PerkName); + if (MSKGSPC.IsPerkAllowed(PerkInfo)) + { + TempObj.SetString("iconSource", "img://" $ PerkInfo.PerkClass.static.GetPerkIconPath()); + TempObj.SetBool("bPerkAllowed", true); + } + else + { + TempObj.SetString("iconSource", "img://" $ PathName(NegativeIcon)); + TempObj.SetBool("bPerkAllowed", false); + } + TempObj.SetBool("bTierUnlocked", bool(bTierUnlocked) && PerkInfo.PerkLevel >= UnlockedPerkLevel); + DataProvider.SetElementObject(Index, TempObj); + } + + SetObject("perkData", DataProvider); + SetInt("SelectedIndex", SelectedPerkIndex); + SetInt("ActiveIndex", SelectedPerkIndex); + + UpdatePendingPerkInfo(SelectedPerkIndex); +} + +defaultproperties +{ + NegativeIcon = Texture2D'UI_VoiceComms_TEX.UI_VoiceCommand_Icon_Negative' +} \ No newline at end of file diff --git a/MSKGS/Classes/MSKGS_GFxTraderContainer_Store.uc b/MSKGS/Classes/MSKGS_GFxTraderContainer_Store.uc new file mode 100644 index 0000000..8666b63 --- /dev/null +++ b/MSKGS/Classes/MSKGS_GFxTraderContainer_Store.uc @@ -0,0 +1,20 @@ +class MSKGS_GFxTraderContainer_Store extends KFGFxTraderContainer_Store; + +function bool IsItemFiltered(STraderItem Item, optional bool bDebug) +{ + if (KFPC.GetPurchaseHelper().IsInOwnedItemList(Item.ClassName)) + return true; + if (KFPC.GetPurchaseHelper().IsInOwnedItemList(Item.DualClassName)) + return true; + if (!KFPC.GetPurchaseHelper().IsSellable(Item)) + return true; + if (Item.WeaponDef.default.PlatformRestriction != PR_All && class'KFUnlockManager'.static.IsPlatformRestricted(Item.WeaponDef.default.PlatformRestriction)) + return true; + + return false; +} + +defaultproperties +{ + +} diff --git a/MSKGS/Classes/MSKGS_LocalMessage.uc b/MSKGS/Classes/MSKGS_LocalMessage.uc index c87b777..0620f2b 100644 --- a/MSKGS/Classes/MSKGS_LocalMessage.uc +++ b/MSKGS/Classes/MSKGS_LocalMessage.uc @@ -7,7 +7,11 @@ enum E_MSKGS_LocalMessageType MSKGS_PlayerGiveBoostToServerMax, MSKGS_BoosterLeaveServer, MSKGS_BoosterLeaveServerMax, - MSKGS_BoosterLeaveServerNoBoost + MSKGS_BoosterLeaveServerNoBoost, + + MSKGS_AllowedLevels, + MSKGS_UnsuitablePerksLocked, + MSKGS_NoPerksDisconnect }; var const String PlayerGivesBoostDefault; @@ -23,6 +27,13 @@ var private localized String PlayerLeft; var const String NoBoostDefault; var private localized String NoBoost; +var const String AllowedLevelsDefault; +var private localized String AllowedLevels; +var const String UnsuitablePerksLockedDefault; +var private localized String UnsuitablePerksLocked; +var const String NoPerksDisconnectDefault; +var private localized String NoPerksDisconnect; + private static function String ReplPlayer(String Str, String Player) { return Repl(Str, "", Player, false); @@ -38,6 +49,21 @@ private static function String ReplTotalBoost(String Str, String Boost) return Repl(Str, "", Boost, false); } +private static function String ReplMinLevel(String Str, String MinLevel) +{ + return Repl(Str, "", MinLevel, false); +} + +private static function String ReplMaxLevel(String Str, String MaxLevel) +{ + return Repl(Str, "", MaxLevel, false); +} + +private static function String ReplDisconnectTime(String Str, String DisconnectTime) +{ + return Repl(Str, "", DisconnectTime, false); +} + public static function String GetLocalizedString( E_LogLevel LogLevel, E_MSKGS_LocalMessageType LMT, @@ -97,6 +123,21 @@ public static function String GetLocalizedString( @ (default.NoBoost != "" ? default.NoBoost : default.NoBoostDefault); RV = ReplPlayer(RV, String1); break; + + case MSKGS_AllowedLevels: + RV = (default.AllowedLevels != "" ? default.AllowedLevels : default.AllowedLevelsDefault); + RV = ReplMinLevel(RV, String1); + RV = ReplMaxLevel(RV, String2); + break; + + case MSKGS_UnsuitablePerksLocked: + RV = (default.UnsuitablePerksLocked != "" ? default.UnsuitablePerksLocked : default.UnsuitablePerksLockedDefault); + break; + + case MSKGS_NoPerksDisconnect: + RV = (default.NoPerksDisconnect != "" ? default.NoPerksDisconnect : default.NoPerksDisconnectDefault); + RV = ReplDisconnectTime(RV, String1); + break; } return RV; @@ -110,4 +151,8 @@ defaultproperties MaxDefault = "(MAX)" PlayerLeftDefault = " left the server." NoBoostDefault = "Now there is no XP boost." + + AllowedLevelsDefault = "Allowed levels: - " + UnsuitablePerksLockedDefault = "Perks with unsuitable level are locked" + NoPerksDisconnectDefault = "You don't have perks with required level. Disconnect after seconds..." } diff --git a/MSKGS/Classes/MSKGS_Objective.uc b/MSKGS/Classes/MSKGS_Objective.uc index 900c4ec..98ccdac 100644 --- a/MSKGS/Classes/MSKGS_Objective.uc +++ b/MSKGS/Classes/MSKGS_Objective.uc @@ -32,5 +32,5 @@ protected function DistributeMoneyAndXP(class MonsterClass, cons defaultproperties { - + KFGFxManagerClass = class'MSKGS_GFxMoviePlayer_Manager' } diff --git a/MSKGS/Classes/MSKGS_PlayerController.uc b/MSKGS/Classes/MSKGS_PlayerController.uc new file mode 100644 index 0000000..7849cb4 --- /dev/null +++ b/MSKGS/Classes/MSKGS_PlayerController.uc @@ -0,0 +1,230 @@ +class MSKGS_PlayerController extends KFPlayerController; + +var public MSKGS_RepInfo RepInfo; +var public byte MinLevel, MaxLevel; +var public int DisconnectTimer; +var public String HexColorInfo; +var public String HexColorWarn; +var public String HexColorError; + +var private KFGameReplicationInfo KFGRI; + +var private bool StatsInitialized; +var private KFGFxWidget_PartyInGame PartyInGameWidget; +var private bool bChatMessageRecieved; + +replication +{ + if (bNetInitial && Role == ROLE_Authority) + RepInfo, MinLevel, MaxLevel, DisconnectTimer, + HexColorInfo, HexColorWarn, HexColorError; +} + +public simulated event PreBeginPlay() +{ + super.PreBeginPlay(); +} + +public simulated event PostBeginPlay() +{ + super.PostBeginPlay(); +} + +private simulated function KFGameReplicationInfo GetKFGRI() +{ + if (KFGRI == None) + { + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + } + + return KFGRI; +} + +private simulated function SetPartyInGameWidget() +{ + if (MyGFxManager == None) return; + if (MyGFxManager.PartyWidget == None) return; + + PartyInGameWidget = KFGFxWidget_PartyInGame(MyGFxManager.PartyWidget); +} + +private simulated function bool CheckPartyInGameWidget() +{ + if (PartyInGameWidget == None) + { + SetPartyInGameWidget(); + } + + return (PartyInGameWidget != None); +} + +private simulated function HideReadyButton() +{ + if (CheckPartyInGameWidget()) + { + PartyInGameWidget.SetReadyButtonVisibility(false); + } +} + +private simulated function ShowReadyButton() +{ + if (CheckPartyInGameWidget()) + { + PartyInGameWidget.SetReadyButtonVisibility(true); + PartyInGameWidget.UpdateReadyButtonText(); + PartyInGameWidget.UpdateReadyButtonVisibility(); + } +} + +private simulated function NoPerkDisconnect() +{ + if (CheckPartyInGameWidget()) + { + if (!bChatMessageRecieved) + { + RepInfo.WriteToChatLocalized( + MSKGS_NoPerksDisconnect, + HexColorError, + String(DisconnectTimer)); + bChatMessageRecieved = true; + } + + if (DisconnectTimer-- <= 0) + { + ClearTimer(nameof(HideReadyButton)); + ClearTimer(nameof(NoPerkDisconnect)); + ClientWasKicked(); + } + } +} + +private simulated function PerksLocked() +{ + if (CheckPartyInGameWidget() && !bChatMessageRecieved) + { + ClearTimer(nameof(PerksLocked)); + RepInfo.WriteToChatLocalized( + MSKGS_UnsuitablePerksLocked, + HexColorWarn); + bChatMessageRecieved = true; + } +} + +public simulated function OnStatsInitialized(bool bWasSuccessful) +{ + Super.OnStatsInitialized(bWasSuccessful); + StatsInitialized = true; + RequestPerkChange(CheckCurrentPerkAllowed()); +} + +public reliable server function ServerHidePerks() +{ + HidePerks(); + ClientHidePerks(); +} + +private reliable client function ClientHidePerks() +{ + HidePerks(); +} + +private simulated function HidePerks() +{ + local int Index; + + if (GetKFGRI() == None) + { + SetTimer(0.1f, false, nameof(HidePerks)); + return; + } + + for (Index = PerkList.length - 1; Index >= 0; --Index) + { + if (!KFGRI.IsPerkAllowed(PerkList[Index].PerkClass)) + { + PerkList.Remove(Index, 1); + } + } + + SavedPerkIndex = CheckCurrentPerkAllowed(); +} + +public simulated function byte CheckCurrentPerkAllowed() +{ + local PerkInfo Perk; + + if (SavedPerkIndex >= PerkList.length || !IsPerkAllowed(PerkList[SavedPerkIndex])) + { + SavedPerkIndex = 0; + for (SavedPerkIndex = 0; SavedPerkIndex < PerkList.length; SavedPerkIndex++) + { + if (IsPerkAllowed(PerkList[SavedPerkIndex])) + { + break; + } + } + } + + if (SavedPerkIndex >= PerkList.length) + { + SavedPerkIndex = 0; + if (StatsInitialized && ROLE < ROLE_Authority) + { + SetTimer(0.1f, true, nameof(HideReadyButton)); + SetTimer(1.0f, true, nameof(NoPerkDisconnect)); + } + } + else if (StatsInitialized && ROLE < ROLE_Authority) + { + foreach PerkList(Perk) + { + if (!IsPerkAllowed(Perk)) + { + SetTimer(1.0f, true, nameof(PerksLocked)); + break; + } + } + } + + return SavedPerkIndex; +} + +public simulated function bool IsPerkAllowed(PerkInfo Perk) +{ + local bool PerkAllowed; + + PerkAllowed = true; + + if (GetKFGRI() != None) + { + PerkAllowed = KFGRI.IsPerkAllowed(Perk.PerkClass); + } + + return (PerkAllowed && Perk.PerkLevel >= MinLevel && Perk.PerkLevel <= MaxLevel); +} + +public simulated function InitPerkLoadout() +{ + if (CurrentPerk == None) // Problem here: it is NONE for some reason + { + CurrentPerk = GetPerk(); // even after that + // dunno where and how it is initialized + // and why it dont happened now + } + + Super.InitPerkLoadout(); +} + +defaultproperties +{ + StatsInitialized = false + bChatMessageRecieved = false + + DisconnectTimer = 15 + MinLevel = 0 + MaxLevel = 25 + + HexColorInfo = "0000FF" + HexColorWarn = "FFFF00" + HexColorError = "FF0000" +} \ No newline at end of file diff --git a/MSKGS/Classes/MSKGS_RepInfo.uc b/MSKGS/Classes/MSKGS_RepInfo.uc index ba7a11d..1f9b6af 100644 --- a/MSKGS/Classes/MSKGS_RepInfo.uc +++ b/MSKGS/Classes/MSKGS_RepInfo.uc @@ -14,6 +14,7 @@ enum MSKGS_PlayerType var private IMSKGS MSKGS; var private bool ServerOwner; var private bool GroupMember; +var private bool Admin; var private repnotify E_LogLevel LogLevel; var private repnotify UniqueNetId GroupID; @@ -165,7 +166,12 @@ public simulated function bool IsServerOwner() public simulated function bool IsAdmin() { - return (GetKFPC() != None && KFPC.PlayerReplicationInfo != None && KFPC.PlayerReplicationInfo.bAdmin); + if (!Admin) + { + Admin = (GetKFPC() != None && KFPC.PlayerReplicationInfo != None && KFPC.PlayerReplicationInfo.bAdmin); + } + + return Admin; } public simulated function bool IsGroupMember() diff --git a/MSKGS/Classes/MSKGS_Survival.uc b/MSKGS/Classes/MSKGS_Survival.uc index 2addd77..8881284 100644 --- a/MSKGS/Classes/MSKGS_Survival.uc +++ b/MSKGS/Classes/MSKGS_Survival.uc @@ -32,5 +32,5 @@ protected function DistributeMoneyAndXP(class MonsterClass, cons defaultproperties { - + KFGFxManagerClass = class'MSKGS_GFxMoviePlayer_Manager' } diff --git a/MSKGS/Classes/MSKGS_VersusSurvival.uc b/MSKGS/Classes/MSKGS_VersusSurvival.uc index 709f146..410fe42 100644 --- a/MSKGS/Classes/MSKGS_VersusSurvival.uc +++ b/MSKGS/Classes/MSKGS_VersusSurvival.uc @@ -32,5 +32,5 @@ protected function DistributeMoneyAndXP(class MonsterClass, cons defaultproperties { - + KFGFxManagerClass = class'MSKGS_GFxMoviePlayer_Manager_Versus' } diff --git a/MSKGS/Classes/MSKGS_WeeklySurvival.uc b/MSKGS/Classes/MSKGS_WeeklySurvival.uc index b41bcb8..795cf69 100644 --- a/MSKGS/Classes/MSKGS_WeeklySurvival.uc +++ b/MSKGS/Classes/MSKGS_WeeklySurvival.uc @@ -32,5 +32,5 @@ protected function DistributeMoneyAndXP(class MonsterClass, cons defaultproperties { - + KFGFxManagerClass = class'MSKGS_GFxMoviePlayer_Manager' }