diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml index 24897f3..e9b52d6 100644 --- a/.github/workflows/mega-linter.yml +++ b/.github/workflows/mega-linter.yml @@ -30,7 +30,7 @@ jobs: - name: MegaLinter id: ml - uses: oxsecurity/megalinter@v6 + uses: oxsecurity/megalinter@v7 env: VALIDATE_ALL_CODEBASE: true GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -68,5 +68,5 @@ jobs: with: branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }} commit_message: "[MegaLinter] Apply linters fixes" - commit_user_name: megalinter-bot - commit_user_email: nicolas.vuillamy@ox.security + commit_user_name: "github-actions" + commit_user_email: "github-actions[bot]@users.noreply.github.com" diff --git a/CTI/Classes/CTI.uc b/CTI/Classes/CTI.uc index f5f0a92..9bcbbc2 100644 --- a/CTI/Classes/CTI.uc +++ b/CTI/Classes/CTI.uc @@ -35,6 +35,19 @@ var private Array RepInfos; var private bool ReadyToSync; +// To bypass "Booleans may not be out parameters" error +struct BoolWrapper +{ + var bool Value; + + structdefaultproperties + { + Value = false + } +}; + +var private BoolWrapper DLCSkinUpdateRequired; + public simulated function bool SafeDestroy() { `Log_Trace(); @@ -174,10 +187,11 @@ private function PostInit() return; } - if (Unlocker.static.UnlockDLC(KFGI, KFGRI, UnlockDLC, RemoveItems, AddItems, LogLevel)) + if (Unlocker.static.UnlockDLC(KFGI, KFGRI, UnlockDLC, RemoveItems, AddItems, DLCSkinUpdateRequired, LogLevel)) { `Log_Info("DLC unlocked"); } + `Log_Debug("DLCSkinUpdateRequired:" @ String(DLCSkinUpdateRequired.Value)); if (bPreloadContent) { @@ -280,7 +294,7 @@ public function bool CreateRepInfo(Controller C) if (RepInfo == None) return false; - RepInfo.PrepareSync(Self, KFPlayerController(C), LogLevel); + RepInfo.PrepareSync(Self, KFPlayerController(C), LogLevel, DLCSkinUpdateRequired.Value); RepInfos.AddItem(RepInfo); diff --git a/CTI/Classes/CTI_RepInfo.uc b/CTI/Classes/CTI_RepInfo.uc index 1fc18d0..f34c0a9 100644 --- a/CTI/Classes/CTI_RepInfo.uc +++ b/CTI/Classes/CTI_RepInfo.uc @@ -1,9 +1,11 @@ -class CTI_RepInfo extends ReplicationInfo; +class CTI_RepInfo extends ReplicationInfo + dependson(WeaponReplacements); const CAPACITY = 64; // max: 128 const Trader = class'Trader'; const LocalMessage = class'CTI_LocalMessage'; +const Replacements = class'WeaponReplacements'; struct ReplicationStruct { @@ -20,6 +22,7 @@ var private CTI CTI; var private E_LogLevel LogLevel; var private KFPlayerController KFPC; +var private KFPlayerReplicationInfo KFPRI; var private KFGFxWidget_PartyInGame PartyInGameWidget; var private GFxObject Notification; @@ -34,10 +37,12 @@ var private int WaitingGRILimit; var private ReplicationStruct RepData; var private Array > RepArray; +var private bool SkinUpdateRequired; + replication { if (bNetInitial && Role == ROLE_Authority) - LogLevel; + LogLevel, SkinUpdateRequired; } public simulated function bool SafeDestroy() @@ -104,13 +109,14 @@ private reliable client function Send(ReplicationStruct RD) Sync(); } -public function PrepareSync(CTI _CTI, KFPlayerController _KFPC, E_LogLevel _LogLevel) +public function PrepareSync(CTI _CTI, KFPlayerController _KFPC, E_LogLevel _LogLevel, bool _SkinUpdateRequired) { `Log_Trace(); - CTI = _CTI; - KFPC = _KFPC; - LogLevel = _LogLevel; + CTI = _CTI; + KFPC = _KFPC; + LogLevel = _LogLevel; + SkinUpdateRequired = _SkinUpdateRequired; } private simulated function Progress(int Value, int Size) @@ -155,8 +161,35 @@ private simulated function Finished() ShowReadyButton(); - Cleanup(); - SafeDestroy(); + if (SkinUpdateRequired) + { + SetTimer(1.0f, true, nameof(UpdateSkinsDLC)); + } + else + { + ClientCleanup(); + } +} + +private simulated function UpdateSkinsDLC() +{ + local SWeapReplace WeapReplace; + + `Log_Debug("Wait for spawn"); + if (GetKFPRI() != None && KFPRI.bHasSpawnedIn) + { + foreach Replacements.default.DLC(WeapReplace) + { + if (WeapReplace.WeapParent.default.SkinItemId > 0 && WeapReplace.Weap.default.SkinItemId != WeapReplace.WeapParent.default.SkinItemId) + { + `Log_Debug("Update skin for:" @ String(WeapReplace.WeapDef) @ "SkinId:" @ WeapReplace.WeapParent.default.SkinItemId); + class'KFWeaponSkinList'.static.SaveWeaponSkin(WeapReplace.WeapDef, WeapReplace.WeapParent.default.SkinItemId); + } + } + + ClearTimer(nameof(UpdateSkinsDLC)); + ClientCleanup(); + } } private simulated function KFPlayerController GetKFPC() @@ -175,6 +208,19 @@ private simulated function KFPlayerController GetKFPC() return KFPC; } +private simulated function KFPlayerReplicationInfo GetKFPRI() +{ + `Log_Trace(); + + if (KFPRI != None) return KFPRI; + + if (GetKFPC() == None) return None; + + KFPRI = KFPlayerReplicationInfo(KFPC.PlayerReplicationInfo); + + return KFPRI; +} + public reliable client function WriteToChatLocalized( E_CTI_LocalMessageType LMT, optional String HexColor, @@ -284,7 +330,13 @@ private simulated function KeepNotification() NotificationPercent); } -private reliable server function Cleanup() +private simulated function ClientCleanup() +{ + ServerCleanup(); + SafeDestroy(); +} + +private reliable server function ServerCleanup() { `Log_Trace(); diff --git a/CTI/Classes/Unlocker.uc b/CTI/Classes/Unlocker.uc index 5524c2c..ca4767a 100644 --- a/CTI/Classes/Unlocker.uc +++ b/CTI/Classes/Unlocker.uc @@ -1,4 +1,5 @@ class Unlocker extends Object + dependson(WeaponReplacements) abstract; // TODO: @@ -6,9 +7,8 @@ class Unlocker extends Object // without replacing KFGFxMoviePlayer_Manager // but how? 🤔 -const Trader = class'Trader'; - -var private const Array > WeapDefDLCReplacements; +const Trader = class'Trader'; +const Replacements = class'WeaponReplacements'; public static function bool IsValidTypeUnlockDLC(String UnlockType, E_LogLevel LogLevel) { @@ -33,6 +33,7 @@ public static function bool UnlockDLC( String UnlockType, out Array > RemoveItems, out Array > AddItems, + out BoolWrapper DLCSkinUpdateRequired, E_LogLevel LogLevel) { `Log_TraceStatic(); @@ -41,12 +42,14 @@ public static function bool UnlockDLC( { case "true": case "auto": - return Auto(KFGI, KFGRI, RemoveItems, AddItems, LogLevel); + return Auto(KFGI, KFGRI, RemoveItems, AddItems, DLCSkinUpdateRequired, LogLevel); case "replaceweapons": + DLCSkinUpdateRequired.Value = true; return ReplaceWeapons(KFGRI, RemoveItems, AddItems, LogLevel); case "replacefilter": + DLCSkinUpdateRequired.Value = false; return ReplaceFilter(KFGI, LogLevel); case "false": @@ -60,6 +63,7 @@ private static function bool Auto( KFGameReplicationInfo KFGRI, out Array > RemoveItems, out Array > AddItems, + out BoolWrapper DLCSkinUpdateRequired, E_LogLevel LogLevel) { local bool CustomGFxManager; @@ -79,10 +83,12 @@ private static function bool Auto( if (CustomGFxManager) { + DLCSkinUpdateRequired.Value = true; return ReplaceWeapons(KFGRI, RemoveItems, AddItems, LogLevel); } else { + DLCSkinUpdateRequired.Value = false; return ReplaceFilter(KFGI, LogLevel); } } @@ -100,6 +106,8 @@ private static function bool ReplaceWeapons( `Log_TraceStatic(); + `Log_Debug("Unlock by replace weapons"); + Unlock = false; PartialUnlock = false; @@ -139,15 +147,15 @@ private static function bool ReplaceWeapons( private static function class PickReplacementWeapDefDLC(class WeapDefDLC, E_LogLevel LogLevel) { - local class WeapDef; + local SWeapReplace WeapReplace; `Log_TraceStatic(); - foreach default.WeapDefDLCReplacements(WeapDef) + foreach Replacements.default.DLC(WeapReplace) { - if (ClassIsChildOf(WeapDef, WeapDefDLC)) + if (ClassIsChildOf(WeapReplace.WeapDef, WeapDefDLC)) { - return WeapDef; + return WeapReplace.WeapDef; } } @@ -158,6 +166,8 @@ private static function bool ReplaceFilter(KFGameInfo KFGI, E_LogLevel LogLevel) { `Log_TraceStatic(); + `Log_Debug("Unlock by replace filter"); + if (KFGI == None) return false; if (KFGameInfo_VersusSurvival(KFGI) != None) @@ -174,32 +184,5 @@ private static function bool ReplaceFilter(KFGameInfo KFGI, E_LogLevel LogLevel) defaultproperties { - WeapDefDLCReplacements.Add(class'CTI_WeapDef_AutoTurret') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_BladedPistol') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Blunderbuss') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_ChainBat') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_ChiappaRhino') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_ChiappaRhinoDual') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_CompoundBow') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Doshinegun') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_DualBladed') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_FAMAS') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_G18') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_G36C') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_GravityImploder') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_HVStormCannon') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_IonThruster') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Mine_Reconstructor') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Minigun') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_MosinNagant') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_ParasiteImplanter') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Pistol_DualG18') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Pistol_G18C') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Rifle_FrostShotgunAxe') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Scythe') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Shotgun_S12') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_ShrinkRayGun') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_ThermiteBore') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_ZedMKIII') - WeapDefDLCReplacements.Add(class'CTI_WeapDef_Zweihander') + } diff --git a/CTI/Classes/WeaponReplacements.uc b/CTI/Classes/WeaponReplacements.uc new file mode 100644 index 0000000..5aed595 --- /dev/null +++ b/CTI/Classes/WeaponReplacements.uc @@ -0,0 +1,183 @@ +class WeaponReplacements extends Object; + +struct SWeapReplace +{ + var const class WeapDef; + var const class WeapDefParent; + var const class Weap; + var const class WeapParent; +}; + +var public const Array DLC; + +defaultproperties +{ + DLC.Add({( + WeapDef=class'CTI_WeapDef_AutoTurret', + WeapDefParent=class'KFWeapDef_AutoTurret', + Weap=class'CTI_Weap_AutoTurret', + WeapParent=class'KFWeap_AutoTurret' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_BladedPistol', + WeapDefParent=class'KFWeapDef_BladedPistol', + Weap=class'CTI_Weap_Pistol_Bladed', + WeapParent=class'KFWeap_Pistol_Bladed' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Blunderbuss', + WeapDefParent=class'KFWeapDef_Blunderbuss', + Weap=class'CTI_Weap_Pistol_Blunderbuss', + WeapParent=class'KFWeap_Pistol_Blunderbuss' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_ChainBat', + WeapDefParent=class'KFWeapDef_ChainBat', + Weap=class'CTI_Weap_Blunt_ChainBat', + WeapParent=class'KFWeap_Blunt_ChainBat' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_ChiappaRhino', + WeapDefParent=class'KFWeapDef_ChiappaRhino', + Weap=class'CTI_Weap_Pistol_ChiappaRhino', + WeapParent=class'KFWeap_Pistol_ChiappaRhino' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_ChiappaRhinoDual', + WeapDefParent=class'KFWeapDef_ChiappaRhinoDual', + Weap=class'CTI_Weap_Pistol_ChiappaRhinoDual', + WeapParent=class'KFWeap_Pistol_ChiappaRhinoDual' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_CompoundBow', + WeapDefParent=class'KFWeapDef_CompoundBow', + Weap=class'CTI_Weap_Bow_CompoundBow', + WeapParent=class'KFWeap_Bow_CompoundBow' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Doshinegun', + WeapDefParent=class'KFWeapDef_Doshinegun', + Weap=class'CTI_Weap_AssaultRifle_Doshinegun', + WeapParent=class'KFWeap_AssaultRifle_Doshinegun' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_DualBladed', + WeapDefParent=class'KFWeapDef_DualBladed', + Weap=class'CTI_Weap_Pistol_DualBladed', + WeapParent=class'KFWeap_Pistol_DualBladed' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_FAMAS', + WeapDefParent=class'KFWeapDef_FAMAS', + Weap=class'CTI_Weap_AssaultRifle_FAMAS', + WeapParent=class'KFWeap_AssaultRifle_FAMAS' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_G18', + WeapDefParent=class'KFWeapDef_G18', + Weap=class'CTI_Weap_SMG_G18', + WeapParent=class'KFWeap_SMG_G18' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_G36C', + WeapDefParent=class'KFWeapDef_G36C', + Weap=class'CTI_Weap_AssaultRifle_G36C', + WeapParent=class'KFWeap_AssaultRifle_G36C' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_GravityImploder', + WeapDefParent=class'KFWeapDef_GravityImploder', + Weap=class'CTI_Weap_GravityImploder', + WeapParent=class'KFWeap_GravityImploder' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_HVStormCannon', + WeapDefParent=class'KFWeapDef_HVStormCannon', + Weap=class'CTI_Weap_HVStormCannon', + WeapParent=class'KFWeap_HVStormCannon' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_IonThruster', + WeapDefParent=class'KFWeapDef_IonThruster', + Weap=class'CTI_Weap_Edged_IonThruster', + WeapParent=class'KFWeap_Edged_IonThruster' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Mine_Reconstructor', + WeapDefParent=class'KFWeapDef_Mine_Reconstructor', + Weap=class'CTI_Weap_Mine_Reconstructor', + WeapParent=class'KFWeap_Mine_Reconstructor' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Minigun', + WeapDefParent=class'KFWeapDef_Minigun', + Weap=class'CTI_Weap_Minigun', + WeapParent=class'KFWeap_Minigun' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_MosinNagant', + WeapDefParent=class'KFWeapDef_MosinNagant', + Weap=class'CTI_Weap_Rifle_MosinNagant', + WeapParent=class'KFWeap_Rifle_MosinNagant' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_ParasiteImplanter', + WeapDefParent=class'KFWeapDef_ParasiteImplanter', + Weap=class'CTI_Weap_Rifle_ParasiteImplanter', + WeapParent=class'KFWeap_Rifle_ParasiteImplanter' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Pistol_DualG18', + WeapDefParent=class'KFWeapDef_Pistol_DualG18', + Weap=class'CTI_Weap_Pistol_DualG18', + WeapParent=class'KFWeap_Pistol_DualG18' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Pistol_G18C', + WeapDefParent=class'KFWeapDef_Pistol_G18C', + Weap=class'CTI_Weap_Pistol_G18C', + WeapParent=class'KFWeap_Pistol_G18C' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Rifle_FrostShotgunAxe', + WeapDefParent=class'KFWeapDef_Rifle_FrostShotgunAxe', + Weap=class'CTI_Weap_Rifle_FrostShotgunAxe', + WeapParent=class'KFWeap_Rifle_FrostShotgunAxe' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Scythe', + WeapDefParent=class'KFWeapDef_Scythe', + Weap=class'CTI_Weap_Edged_Scythe', + WeapParent=class'KFWeap_Edged_Scythe' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Shotgun_S12', + WeapDefParent=class'KFWeapDef_Shotgun_S12', + Weap=class'CTI_Weap_Shotgun_S12', + WeapParent=class'KFWeap_Shotgun_S12' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_ShrinkRayGun', + WeapDefParent=class'KFWeapDef_ShrinkRayGun', + Weap=class'CTI_Weap_ShrinkRayGun', + WeapParent=class'KFWeap_ShrinkRayGun' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_ThermiteBore', + WeapDefParent=class'KFWeapDef_ThermiteBore', + Weap=class'CTI_Weap_RocketLauncher_ThermiteBore', + WeapParent=class'KFWeap_RocketLauncher_ThermiteBore' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_ZedMKIII', + WeapDefParent=class'KFWeapDef_ZedMKIII', + Weap=class'CTI_Weap_ZedMKIII', + WeapParent=class'KFWeap_ZedMKIII' + )}) + DLC.Add({( + WeapDef=class'CTI_WeapDef_Zweihander', + WeapDefParent=class'KFWeapDef_Zweihander', + Weap=class'CTI_Weap_Edged_Zweihander', + WeapParent=class'KFWeap_Edged_Zweihander' + )}) +}