diff --git a/CTI/Classes/CTI.uc b/CTI/Classes/CTI.uc index 9d4653b..1af2144 100644 --- a/CTI/Classes/CTI.uc +++ b/CTI/Classes/CTI.uc @@ -1,7 +1,7 @@ class CTI extends Info config(CTI); -const LatestVersion = 4; +const LatestVersion = 5; const CfgRemoveItems = class'RemoveItems'; const CfgAddItems = class'AddItems'; @@ -23,6 +23,7 @@ var private config String UnlockDLC; var private config bool bPreloadContent; var private config bool bOfficialWeaponsList; var private config bool bDisableItemLimitCheck; +var private config bool bApplyPatch; var private KFGameInfo KFGI; var private KFGameReplicationInfo KFGRI; @@ -111,6 +112,9 @@ private function PreInit() case 3: bDisableItemLimitCheck = false; + case 4: + bApplyPatch = false; + case MaxInt: `Log_Info("Config updated to version" @ LatestVersion); break; @@ -206,6 +210,11 @@ private function PostInit() } `Log_Debug("DLCSkinUpdateRequired:" @ String(DLCSkinUpdateRequired.Value)); + if (bApplyPatch) + { + ServerPatch(); + } + Trader.static.OverwriteTraderItems(KFGRI, WeapDefs, LogLevel); `Log_Info("Trader items:" @ WeapDefs.Length); @@ -226,6 +235,41 @@ private function PostInit() } } +private function ServerPatch() +{ + local class AutoPurchaseHelper; + local class InventoryManager; + + if (KFGI.KFGFxManagerClass.GetPackageName() != 'CTI') + { + if (Unlocker.static.CustomGFxManager(KFGI)) + { + `Log_Warn("Custom KFGFxMoviePlayer_Manager detected:" @ String(KFGI.KFGFxManagerClass) $ ". There may be compatibility issues."); + } + + if (KFGameInfo_VersusSurvival(KFGI) != None) + { + KFGI.KFGFxManagerClass = class'CTI_GFxMoviePlayer_Manager_Versus'; + } + else + { + KFGI.KFGFxManagerClass = class'CTI_GFxMoviePlayer_Manager'; + } + } + + AutoPurchaseHelper = class(KFGI.PlayerControllerClass).default.PurchaseHelperClass; + if (AutoPurchaseHelper != class'KFPlayerController'.default.PurchaseHelperClass) + { + `Log_Warn("Custom PurchaseHelperClass detected:" @ String(AutoPurchaseHelper) $ ". There may be compatibility issues."); + } + + InventoryManager = class(KFGI.DefaultPawnClass.default.InventoryManagerClass); + if (InventoryManager != class'KFPawn'.default.InventoryManagerClass) + { + `Log_Warn("Custom InventoryManagerClass detected:" @ String(InventoryManager) $ ". There may be compatibility issues."); + } +} + private function Preload(const out Array > Content) { local Array PreloadContent; @@ -299,7 +343,7 @@ public function bool CreateRepInfo(Controller C) if (RepInfo == None) return false; - RepInfo.PrepareSync(Self, KFPlayerController(C), LogLevel, DLCSkinUpdateRequired.Value); + RepInfo.PrepareSync(Self, KFPlayerController(C), LogLevel, DLCSkinUpdateRequired.Value, bApplyPatch); RepInfos.AddItem(RepInfo); @@ -339,4 +383,4 @@ public function bool DestroyRepInfo(Controller C) DefaultProperties { ReadyToSync = false -} \ No newline at end of file +} diff --git a/CTI/Classes/CTI_AutoPurchaseHelper.uc b/CTI/Classes/CTI_AutoPurchaseHelper.uc new file mode 100644 index 0000000..4fe2775 --- /dev/null +++ b/CTI/Classes/CTI_AutoPurchaseHelper.uc @@ -0,0 +1,284 @@ +class CTI_AutoPurchaseHelper extends KFAutoPurchaseHelper; + +var private CTI_GFxObject_TraderItems CTI_TraderItems; +var private CTI_InventoryManager CTI_IM; + +private function CTI_GFxObject_TraderItems GetCTI_TraderItems() +{ + if (CTI_TraderItems == None) + { + if (TraderItems == None) + { + GetTraderItems(); + } + + if (TraderItems != None) + { + CTI_TraderItems = CTI_GFxObject_TraderItems(TraderItems); + } + } + + return CTI_TraderItems; +} + +private function CTI_InventoryManager GetCTI_IM() +{ + if (CTI_IM == None) + { + CTI_IM = CTI_InventoryManager(Pawn.InvManager); + } + + return CTI_IM; +} + +public function Initialize(optional bool bInitializeOwned = true) +{ + Super.Initialize(bInitializeOwned); + GetCTI_IM(); + GetCTI_TraderItems(); +} + +public function bool UpgradeWeapon(int OwnedItemIndex) +{ + local int ItemIndex; + local STraderItem DefaultItemInfo; + local SItemInformation ItemInfo; + local int Test1, Test2; + + ItemInfo = OwnedItemList[OwnedItemIndex]; + DefaultItemInfo = ItemInfo.DefaultItem; + + if (ItemInfo.bIsSecondaryAmmo || !CanUpgrade(DefaultItemInfo, Test1, Test2, true)) + { + return false; + } + + if (GetCTI_IM() == None) return false; + + CTI_GetItemIndicesFromArche(ItemIndex, DefaultItemInfo.ClassName); + CTI_IM.CTI_BuyUpgrade(ItemIndex, ItemInfo.ItemUpgradeLevel); + OwnedItemList[OwnedItemIndex].SellPrice = GetAdjustedSellPriceFor(DefaultItemInfo); + + if (MyGfxManager != None && MyGfxManager.TraderMenu != None) + { + MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList; + } + + return true; +} + +public function BoughtAmmo(float AmountPurchased, int Price, EItemType ItemType, optional name ClassName, optional bool bIsSecondaryAmmo) +{ + local int ItemIndex; + AddDosh(-Price); + + if (ItemType == EIT_Weapon) + { + CTI_GetItemIndicesFromArche(ItemIndex, ClassName); + } + + if (GetCTI_IM() == None) return; + + CTI_IM.CTI_BuyAmmo(AmountPurchased, ItemType, ItemIndex, bIsSecondaryAmmo); +} + +private function float AmmoCostScale() +{ + local KFGameReplicationInfo KFGRI; + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + return KFGRI == None? 1.0f : KFGRI.GameAmmoCostScale; +} + +public function int AddWeaponToOwnedItemList(STraderItem DefaultItem, optional bool bDoNotBuy, optional int OverrideItemUpgradeLevel = INDEX_NONE) +{ + local SItemInformation WeaponInfo; + local int ItemIndex, AddedWeaponIndex, OwnedSingleIdx, SingleDualAmmoDiff; + local bool bAddingDual; + + WeaponInfo.MagazineCapacity = DefaultItem.MagazineCapacity; + CurrentPerk.ModifyMagSizeAndNumber(None, WeaponInfo.MagazineCapacity, DefaultItem.AssociatedPerkClasses,, DefaultItem.ClassName); + + WeaponInfo.MaxSpareAmmo = DefaultItem.MaxSpareAmmo; + CurrentPerk.ModifyMaxSpareAmmoAmount(none, WeaponInfo.MaxSpareAmmo, DefaultItem); + WeaponInfo.MaxSpareAmmo += WeaponInfo.MagazineCapacity; + + WeaponInfo.SpareAmmoCount = DefaultItem.InitialSpareMags * DefaultItem.MagazineCapacity; + CurrentPerk.ModifySpareAmmoAmount(none, WeaponInfo.SpareAmmoCount, DefaultItem); + WeaponInfo.SpareAmmoCount += WeaponInfo.MagazineCapacity; + + bAddingDual = DefaultItem.SingleClassName != ''; + if (bAddingDual) + { + for (OwnedSingleIdx = 0; OwnedSingleIdx < OwnedItemList.Length; ++OwnedSingleIdx) + { + if (OwnedItemList[OwnedSingleIdx].DefaultItem.ClassName != DefaultItem.SingleClassName) continue; + + SingleDualAmmoDiff = OwnedItemList[OwnedSingleIdx].SpareAmmoCount - WeaponInfo.SpareAmmoCount; + SingleDualAmmoDiff = Max(0, SingleDualAmmoDiff); + + if (WeaponInfo.SpareAmmoCount > OwnedItemList[OwnedSingleIdx].SpareAmmoCount) + { + OwnedItemList[OwnedSingleIdx].SpareAmmoCount = WeaponInfo.SpareAmmoCount; + } + else + { + WeaponInfo.SpareAmmoCount = Min(OwnedItemList[OwnedSingleIdx].SpareAmmoCount, WeaponInfo.MaxSpareAmmo); + } + + WeaponInfo.ItemUpgradeLevel = OwnedItemList[OwnedSingleIdx].ItemUpgradeLevel; + break; + } + } + + CurrentPerk.MaximizeSpareAmmoAmount(DefaultItem.AssociatedPerkClasses, WeaponInfo.SpareAmmoCount, DefaultItem.MaxSpareAmmo + DefaultItem.MagazineCapacity); + + WeaponInfo.SecondaryAmmoCount = DefaultItem.InitialSecondaryAmmo; + CurrentPerk.ModifyMagSizeAndNumber(None, WeaponInfo.MagazineCapacity, DefaultItem.AssociatedPerkClasses, true, DefaultItem.ClassName); + CurrentPerk.ModifySpareAmmoAmount(None, WeaponInfo.SecondaryAmmoCount, DefaultItem, true); + + WeaponInfo.MaxSecondaryAmmo = DefaultItem.MaxSecondaryAmmo; + CurrentPerk.ModifyMaxSpareAmmoAmount(None, WeaponInfo.MaxSecondaryAmmo, DefaultItem, true); + + WeaponInfo.AmmoPricePerMagazine = AmmoCostScale() * DefaultItem.WeaponDef.default.AmmoPricePerMag; + WeaponInfo.SellPrice = GetAdjustedSellPriceFor(DefaultItem); + + WeaponInfo.DefaultItem = DefaultItem; + + if (OverrideItemUpgradeLevel > INDEX_NONE) + { + WeaponInfo.ItemUpgradeLevel = OverrideItemUpgradeLevel; + } + + AddedWeaponIndex = AddItemByPriority(WeaponInfo); + + if (GetCTI_IM() == None) return AddedWeaponIndex; + + CTI_GetItemIndicesFromArche(ItemIndex, DefaultItem.ClassName); + + if (!bDoNotBuy) + { + CTI_IM.CTI_ServerBuyWeapon(ItemIndex, WeaponInfo.ItemUpgradeLevel); + } + else + { + CTI_IM.CTI_ServerAddTransactionItem(ItemIndex, WeaponInfo.ItemUpgradeLevel); + AddBlocks(CTI_IM.GetWeaponBlocks(DefaultItem, WeaponInfo.ItemUpgradeLevel)); + } + + if (bAddingDual) + { + CTI_AddTransactionAmmo(ItemIndex, SingleDualAmmoDiff, false); + RemoveWeaponFromOwnedItemList(, DefaultItem.SingleClassName, true); + } + + return AddedWeaponIndex; +} + +public function RemoveWeaponFromOwnedItemList(optional int OwnedListIdx = INDEX_NONE, optional name ClassName, optional bool bDoNotSell) +{ + local SItemInformation ItemInfo; + local int ItemIndex; + local int SingleOwnedIndex; + + if (OwnedListIdx == INDEX_NONE && ClassName != '') + { + for (OwnedListIdx = 0; OwnedListIdx < OwnedItemList.length; ++OwnedListIdx) + { + if (OwnedItemList[OwnedListIdx].DefaultItem.ClassName == ClassName) break; + } + } + + if (OwnedListIdx >= OwnedItemList.length) return; + + ItemInfo = OwnedItemList[OwnedListIdx]; + + if (GetCTI_IM() == None) return; + + if (!bDoNotSell) + { + CTI_GetItemIndicesFromArche(ItemIndex, ItemInfo.DefaultItem.ClassName); + CTI_IM.CTI_ServerSellWeapon(ItemIndex); + } + else + { + AddBlocks(-CTI_IM.GetDisplayedBlocksRequiredFor(ItemInfo.DefaultItem)); + CTI_GetItemIndicesFromArche(ItemIndex, ItemInfo.DefaultItem.ClassName); + CTI_IM.CTI_ServerRemoveTransactionItem(ItemIndex); + } + + if (OwnedItemList[OwnedListIdx].bIsSecondaryAmmo) + { + OwnedItemList.Remove(OwnedListIdx, 1); + if (OwnedListIdx - 1 >= 0) + { + OwnedItemList.Remove(OwnedListIdx - 1, 1); + } + } + else if (OwnedItemList[OwnedListIdx].DefaultItem.WeaponDef.static.UsesSecondaryAmmo()) + { + if (OwnedListIdx + 1 < OwnedItemList.Length) + { + OwnedItemList.Remove(OwnedListIdx + 1, 1); + OwnedItemList.Remove(OwnedListIdx, 1); + } + } + else + { + OwnedItemList.Remove(OwnedListIdx, 1); + } + + if (ItemInfo.DefaultItem.SingleClassName == 'KFWeap_Pistol_9mm' || ItemInfo.DefaultItem.SingleClassName == 'KFWeap_HRG_93R') + { + if (CTI_GetItemIndicesFromArche(ItemIndex, ItemInfo.DefaultItem.SingleClassName)) + { + SingleOwnedIndex = AddWeaponToOwnedItemList(CTI_TraderItems.AllItems[ItemIndex], true, ItemInfo.ItemUpgradeLevel); + + CTI_AddTransactionAmmo(ItemIndex, ItemInfo.SpareAmmoCount - (ItemInfo.MaxSpareAmmo / 2.0) + ((ItemInfo.MaxSpareAmmo / 2.0) - OwnedItemList[SingleOwnedIndex].SpareAmmoCount), false); + OwnedItemList[SingleOwnedIndex].SpareAmmoCount = ItemInfo.SpareAmmoCount; + } + } + + if (MyGfxManager != None && MyGfxManager.TraderMenu != None) + { + MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList; + } +} + +public function SetWeaponInformation(KFWeapon KFW) +{ + local int i; + + GetCTI_TraderItems(); + + for (i = 0; i < CTI_TraderItems.AllItems.Length; i++) + { + if (KFW.Class.name == CTI_TraderItems.AllItems[i].ClassName) + { + SetWeaponInfo(KFW, CTI_TraderItems.AllItems[i]); + return; + } + } +} + +// native private final function AddTransactionAmmo( byte ItemIndex, int Amount, bool bSecondaryAmmo ); +private function CTI_AddTransactionAmmo(int ItemIndex, int Amount, bool bSecondaryAmmo); // TODO: impl + +private function bool CTI_GetItemIndicesFromArche(out int ItemIndex, name WeaponClassName) +{ + local int Index; + + if (GetCTI_TraderItems() == None) return false; + + Index = CTI_TraderItems.AllItems.Find('ClassName', WeaponClassName); + + if (Index == INDEX_NONE) return false; + + ItemIndex = Index; + + return true; +} + +defaultproperties +{ + +} diff --git a/CTI/Classes/CTI_GFxMenu_Trader.uc b/CTI/Classes/CTI_GFxMenu_Trader.uc index 0997ce9..d00f198 100644 --- a/CTI/Classes/CTI_GFxMenu_Trader.uc +++ b/CTI/Classes/CTI_GFxMenu_Trader.uc @@ -1,8 +1,219 @@ class CTI_GFxMenu_Trader extends KFGFxMenu_Trader dependsOn(CTI_GFxTraderContainer_Store); +var private int SelectedItemIndexInt; + +private function UpdateByteSelectedIndex() +{ + SelectedItemIndex = Clamp(SelectedItemIndexInt, 0, 255); +} + +public function SetTraderItemDetails(int ItemIndex) +{ + local STraderItem SelectedItem; + local bool bCanAfford, bCanBuyItem, bCanCarry; + SelectedList = TL_Shop; + + if (ItemDetails == None || ShopContainer == None) return; + + if (MyKFPC.GetPurchaseHelper().TraderItems.SaleItems.length >= 0 && ItemIndex < MyKFPC.GetPurchaseHelper().TraderItems.SaleItems.length) + { + SelectedItemIndexInt = ItemIndex; + SelectedItem = MyKFPC.GetPurchaseHelper().TraderItems.SaleItems[ItemIndex]; + + bCanAfford = MyKFPC.GetPurchaseHelper().GetCanAfford(MyKFPC.GetPurchaseHelper().GetAdjustedBuyPriceFor(SelectedItem)); + bCanCarry = MyKFPC.GetPurchaseHelper().CanCarry(SelectedItem); + + bCanBuyItem = bCanAfford && bCanCarry; + + PurchaseError(!bCanAfford, !bCanCarry); + + ItemDetails.SetShopItemDetails(SelectedItem, MyKFPC.GetPurchaseHelper().GetAdjustedBuyPriceFor(SelectedItem), bCanCarry, bCanBuyItem); + bCanBuyOrSellItem = bCanBuyItem; + } + else + { + ItemDetails.SetVisible(false); + } + + UpdateByteSelectedIndex(); +} + +public function SetPlayerItemDetails(int ItemIndex) +{ + local STraderItem SelectedItem; + + SelectedList = TL_Player; + if (ItemDetails == None || ItemIndex >= OwnedItemList.length) return; + + bGenericItemSelected = false; + SelectedItemIndexInt = ItemIndex; + SelectedItem = OwnedItemList[ItemIndex].DefaultItem; + ItemDetails.SetPlayerItemDetails(SelectedItem, OwnedItemList[ItemIndex].SellPrice, OwnedItemList[ItemIndex].ItemUpgradeLevel); + bCanBuyOrSellItem = MyKFPC.GetPurchaseHelper().IsSellable(SelectedItem); + PurchaseError(false, false); + + UpdateByteSelectedIndex(); +} + +public function SetNewSelectedIndex(int ListLength) +{ + if (SelectedItemIndexInt >= ListLength) + { + if (SelectedItemIndexInt != 0) + { + SelectedItemIndexInt--; + } + } + + UpdateByteSelectedIndex(); +} + +public function RefreshItemComponents(optional bool bInitOwnedItems = false) +{ + if (PlayerInventoryContainer == None || PlayerInfoContainer == None) return; + + if (bInitOwnedItems) + { + MyKFPC.GetPurchaseHelper().InitializeOwnedItemList(); + } + OwnedItemList = MyKFPC.GetPurchaseHelper().OwnedItemList; + PlayerInventoryContainer.RefreshPlayerInventory(); + RefreshShopItemList(CurrentTab, CurrentFilterIndex); + GameInfoContainer.UpdateGameInfo(); + GameInfoContainer.SetDosh(MyKFPC.GetPurchaseHelper().TotalDosh); + GameInfoContainer.SetCurrentWeight(MyKFPC.GetPurchaseHelper().TotalBlocks, MyKFPC.GetPurchaseHelper().MaxBlocks); + + if (SelectedList == TL_Shop) + { + SetTraderItemDetails(SelectedItemIndexInt); + } + else if (bGenericItemSelected) + { + SetGenericItemDetails(LastDefaultItemInfo, LastItemInfo); + } + else + { + SetPlayerItemDetails(SelectedItemIndexInt); + } +} + +public function RefreshShopItemList(TabIndices TabIndex, byte FilterIndex) +{ + if (ShopContainer == None || FilterContainer == None) return; + + switch (TabIndex) + { + case (TI_Perks): + ShopContainer.RefreshWeaponListByPerk(FilterIndex, MyKFPC.GetPurchaseHelper().TraderItems.SaleItems); + FilterContainer.SetPerkFilterData(FilterIndex); + break; + case (TI_Type): + ShopContainer.RefreshItemsByType(FilterIndex, MyKFPC.GetPurchaseHelper().TraderItems.SaleItems); + FilterContainer.SetTypeFilterData(FilterIndex); + break; + case (TI_Favorites): + ShopContainer.RefreshFavoriteItems(MyKFPC.GetPurchaseHelper().TraderItems.SaleItems); + FilterContainer.ClearFilters(); + break; + case (TI_All): + ShopContainer.RefreshAllItems(MyKFPC.GetPurchaseHelper().TraderItems.SaleItems); + FilterContainer.ClearFilters(); + break; + } + + FilterContainer.SetInt("selectedTab", TabIndex); + FilterContainer.SetInt("selectedFilter", FilterIndex); + + if (SelectedList == TL_Shop) + { + if (SelectedItemIndexInt >= MyKFPC.GetPurchaseHelper().TraderItems.SaleItems.length) + { + SelectedItemIndexInt = MyKFPC.GetPurchaseHelper().TraderItems.SaleItems.length - 1; + } + + SetTraderItemDetails(SelectedItemIndexInt); + ShopContainer.SetSelectedIndex(SelectedItemIndexInt); + } +} + +public function Callback_BuyOrSellItem() +{ + local STraderItem ShopItem; + local SItemInformation ItemInfo; + + if (bCanBuyOrSellItem) + { + if (SelectedList == TL_Shop) + { + ShopItem = MyKFPC.GetPurchaseHelper().TraderItems.SaleItems[SelectedItemIndexInt]; + + MyKFPC.GetPurchaseHelper().PurchaseWeapon(ShopItem); + SetNewSelectedIndex(MyKFPC.GetPurchaseHelper().TraderItems.SaleItems.length); + SetTraderItemDetails(SelectedItemIndexInt); + ShopContainer.ActionScriptVoid("itemBought"); + } + else + { + `log("Callback_BuyOrSellItem: SelectedItemIndex="$SelectedItemIndexInt, MyKFIM.bLogInventory); + ItemInfo = OwnedItemList[SelectedItemIndexInt]; + `log("Callback_BuyOrSellItem: ItemInfo="$ItemInfo.DefaultItem.ClassName, MyKFIM.bLogInventory); + MyKFPC.GetPurchaseHelper().SellWeapon(ItemInfo, SelectedItemIndexInt); + + SetNewSelectedIndex(OwnedItemList.length); + SetPlayerItemDetails(SelectedItemIndexInt); + PlayerInventoryContainer.ActionScriptVoid("itemSold"); + } + } + else if (SelectedList == TL_Shop) + { + ShopItem = MyKFPC.GetPurchaseHelper().TraderItems.SaleItems[SelectedItemIndexInt]; + + MyKFPC.PlayTraderSelectItemDialog(!MyKFPC.GetPurchaseHelper().GetCanAfford(MyKFPC.GetPurchaseHelper().GetAdjustedBuyPriceFor(ShopItem)), !MyKFPC.GetPurchaseHelper().CanCarry(ShopItem)); + } + RefreshItemComponents(); +} + +public function Callback_FavoriteItem() +{ + if (SelectedList == TL_Shop) + { + ToggleFavorite(MyKFPC.GetPurchaseHelper().TraderItems.SaleItems[SelectedItemIndexInt].ClassName); + if (CurrentTab == TI_Favorites) + { + SetNewSelectedIndex(MyKFPC.GetPurchaseHelper().TraderItems.SaleItems.length); + } + SetTraderItemDetails(SelectedItemIndexInt); + } + else + { + ToggleFavorite(OwnedItemList[SelectedItemIndexInt].DefaultItem.ClassName); + SetPlayerItemDetails(SelectedItemIndexInt); + } + RefreshItemComponents(); +} + +public function Callback_UpgradeItem() +{ + local SItemInformation ItemInfo; + local KFAutoPurchaseHelper PurchaseHelper; + + if (SelectedList != TL_Player) return; + + PurchaseHelper = MyKFPC.GetPurchaseHelper(); + if (PurchaseHelper.UpgradeWeapon(SelectedItemIndexInt)) + { + ItemInfo = PurchaseHelper.OwnedItemList[SelectedItemIndexInt]; + PurchaseHelper.OwnedItemList[SelectedItemIndexInt].ItemUpgradeLevel++; + PurchaseHelper.OwnedItemList[SelectedItemIndexInt].SellPrice = + PurchaseHelper.GetAdjustedSellPriceFor(ItemInfo.DefaultItem); + RefreshItemComponents(); + ShopContainer.ActionScriptVoid("itemBought"); + class'KFMusicStingerHelper'.static.PlayWeaponUpgradeStinger(MyKFPC); + } +} + defaultproperties { - SubWidgetBindings.Remove((WidgetName="shopContainer",WidgetClass=class'KFGFxTraderContainer_Store')) - SubWidgetBindings.Add((WidgetName="shopContainer",WidgetClass=class'CTI_GFxTraderContainer_Store')) + } diff --git a/CTI/Classes/CTI_GFxMenu_Trader_DLC.uc b/CTI/Classes/CTI_GFxMenu_Trader_DLC.uc new file mode 100644 index 0000000..6acc439 --- /dev/null +++ b/CTI/Classes/CTI_GFxMenu_Trader_DLC.uc @@ -0,0 +1,8 @@ +class CTI_GFxMenu_Trader_DLC extends CTI_GFxMenu_Trader + dependsOn(CTI_GFxTraderContainer_Store); + +defaultproperties +{ + SubWidgetBindings.Remove((WidgetName="shopContainer",WidgetClass=class'KFGFxTraderContainer_Store')) + SubWidgetBindings.Add((WidgetName="shopContainer",WidgetClass=class'CTI_GFxTraderContainer_Store')) +} diff --git a/CTI/Classes/CTI_GFxMoviePlayer_Manager_DLC.uc b/CTI/Classes/CTI_GFxMoviePlayer_Manager_DLC.uc new file mode 100644 index 0000000..36b0ac1 --- /dev/null +++ b/CTI/Classes/CTI_GFxMoviePlayer_Manager_DLC.uc @@ -0,0 +1,8 @@ +class CTI_GFxMoviePlayer_Manager_DLC extends KFGFxMoviePlayer_Manager + dependsOn(CTI_GFxMenu_Trader); + +defaultproperties +{ + WidgetBindings.Remove((WidgetName="traderMenu",WidgetClass=class'KFGFxMenu_Trader')) + WidgetBindings.Add((WidgetName="traderMenu",WidgetClass=class'CTI_GFxMenu_Trader_DLC')) +} diff --git a/CTI/Classes/CTI_GFxMoviePlayer_Manager_Versus_DLC.uc b/CTI/Classes/CTI_GFxMoviePlayer_Manager_Versus_DLC.uc new file mode 100644 index 0000000..2802bff --- /dev/null +++ b/CTI/Classes/CTI_GFxMoviePlayer_Manager_Versus_DLC.uc @@ -0,0 +1,8 @@ +class CTI_GFxMoviePlayer_Manager_Versus_DLC extends KFGFxMoviePlayer_Manager_Versus + dependsOn(CTI_GFxMenu_Trader); + +defaultproperties +{ + WidgetBindings.Remove((WidgetName="traderMenu",WidgetClass=class'KFGFxMenu_Trader')) + WidgetBindings.Add((WidgetName="traderMenu",WidgetClass=class'CTI_GFxMenu_Trader_DLC')) +} diff --git a/CTI/Classes/CTI_GFxObject_TraderItems.uc b/CTI/Classes/CTI_GFxObject_TraderItems.uc new file mode 100644 index 0000000..22ffd39 --- /dev/null +++ b/CTI/Classes/CTI_GFxObject_TraderItems.uc @@ -0,0 +1,21 @@ +class CTI_GFxObject_TraderItems extends KFGFxObject_TraderItems; + +var() Array AllItems; + +public function bool CTI_GetItemIndicesFromArche(out int ItemIndex, name WeaponClassName) +{ + local int Index; + + Index = AllItems.Find('ClassName', WeaponClassName); + + if (Index == INDEX_NONE) return false; + + ItemIndex = Index; + + return true; +} + +DefaultProperties +{ + +} \ No newline at end of file diff --git a/CTI/Classes/CTI_InventoryManager.uc b/CTI/Classes/CTI_InventoryManager.uc new file mode 100644 index 0000000..d42f4ca --- /dev/null +++ b/CTI/Classes/CTI_InventoryManager.uc @@ -0,0 +1,463 @@ +class CTI_InventoryManager extends KFInventoryManager; + +// simulated function final BuyAmmo( float AmountPurchased, EItemType ItemType, optional byte ItemIndex, optional bool bSecondaryAmmo ) +public simulated function CTI_BuyAmmo(float AmountPurchased, EItemType ItemType, optional int ItemIndex, optional bool bSecondaryAmmo) +{ + local STraderItem WeaponItem; + local KFWeapon KFW; + local int MagAmmoCount; + + switch (ItemType) + { + case EIT_Weapon: + MagAmmoCount = INDEX_NONE; + if (CTI_GetTraderItemFromWeaponLists(WeaponItem, ItemIndex) && GetWeaponFromClass(KFW, WeaponItem.ClassName)) + { + MagAmmoCount = bSecondaryAmmo ? KFW.AmmoCount[1] : KFW.AmmoCount[0]; + } + CTI_ServerBuyAmmo(int(AmountPurchased), MagAmmoCount, ItemIndex, bSecondaryAmmo); + break; + + case EIT_Armor: CTI_ServerBuyArmor(AmountPurchased); break; + case EIT_Grenade: CTI_ServerBuyGrenade(int(AmountPurchased)); break; + } +} + +// reliable server final private function ServerBuyAmmo(int AmountPurchased, byte ClientAmmoCount, byte ItemIndex, bool bSecondaryAmmo) +private reliable server function CTI_ServerBuyAmmo(int AmountPurchased, int ClientAmmoCount, int ItemIndex, bool bSecondaryAmmo) +{ + local STraderItem WeaponItem; + local KFWeapon KFW; + local int ClientMaxMagCapacity; + + if (Role != ROLE_Authority || !bServerTraderMenuOpen) return; + if (!CTI_GetTraderItemFromWeaponLists(WeaponItem, ItemIndex)) return; + if (!CTI_ProcessAmmoDosh(WeaponItem, AmountPurchased, bSecondaryAmmo)) return; + + if (!GetWeaponFromClass(KFW, WeaponItem.ClassName)) + { + CTI_ServerAddTransactionAmmo(AmountPurchased, ItemIndex, bSecondaryAmmo); + return; + } + + if (bSecondaryAmmo) + { + KFW.AddSecondaryAmmo(AmountPurchased); + } + else + { + if (ClientAmmoCount != INDEX_NONE) + { + ClientMaxMagCapacity = KFW.default.MagazineCapacity[0]; + if (KFW.GetPerk() != None) + { + KFW.GetPerk().ModifyMagSizeAndNumber(KFW, ClientMaxMagCapacity); + } + KFW.AmmoCount[0] = Clamp(ClientAmmoCount, 0, ClientMaxMagCapacity); + } + + KFW.AddAmmo(AmountPurchased); + } +} + +// reliable server final private event ServerAddTransactionAmmo( int AmountAdded, byte ItemIndex, bool bSecondaryAmmo ) +private reliable server event CTI_ServerAddTransactionAmmo(int AmountAdded, int ItemIndex, bool bSecondaryAmmo) +{ + local STraderItem WeaponItem; + local int TransactionIndex; + + if (!bServerTraderMenuOpen) return; + if (!CTI_GetTraderItemFromWeaponLists(WeaponItem, ItemIndex)) return; + + TransactionIndex = GetTransactionItemIndex(WeaponItem.ClassName); + if (TransactionIndex == INDEX_NONE) return; + + TransactionItems[TransactionIndex].AddedAmmo[byte(bSecondaryAmmo)] += AmountAdded; +} + +// simulated function final BuyUpgrade(byte ItemIndex, int CurrentUpgradeLevel) +public simulated function CTI_BuyUpgrade(int ItemIndex, int CurrentUpgradeLevel) +{ + local STraderItem WeaponItem; + local KFPlayerController KFPC; + + KFPC = KFPlayerController(Instigator.Owner); + + if (!CTI_GetTraderItemFromWeaponLists(WeaponItem, ItemIndex)) return; + + KFPC.GetPurchaseHelper().AddDosh(-WeaponItem.WeaponDef.static.GetUpgradePrice(CurrentUpgradeLevel)); //client tracking + KFPC.GetPurchaseHelper().AddBlocks(-GetDisplayedBlocksRequiredFor(WeaponItem));//remove the old weight + KFPC.GetPurchaseHelper().AddBlocks(GetDisplayedBlocksRequiredFor(WeaponItem, CurrentUpgradeLevel + 1)); //add the new + CTI_ServerBuyUpgrade(ItemIndex, CurrentUpgradeLevel); +} + +// reliable server final private function ServerBuyUpgrade(byte ItemIndex, int CurrentUpgradeLevel) +private reliable server function CTI_ServerBuyUpgrade(int ItemIndex, int CurrentUpgradeLevel) +{ + local STraderItem WeaponItem; + local KFWeapon KFW; + local int NewUpgradeLevel; + + if (Role != ROLE_Authority || !bServerTraderMenuOpen) return; + if (!CTI_GetTraderItemFromWeaponLists(WeaponItem, ItemIndex)) return; + if (!CTI_ProcessUpgradeDosh(WeaponItem, CurrentUpgradeLevel)) return; + + NewUpgradeLevel = CurrentUpgradeLevel + 1; + + if (GetWeaponFromClass(KFW, WeaponItem.ClassName)) + { + if (KFW == None) return; + + KFW.SetWeaponUpgradeLevel(NewUpgradeLevel); + if (CurrentUpgradeLevel > 0) + { + AddCurrentCarryBlocks(-KFW.GetUpgradeStatAdd(EWUS_Weight, CurrentUpgradeLevel)); + } + + AddCurrentCarryBlocks(KFW.GetUpgradeStatAdd(EWUS_Weight, NewUpgradeLevel)); + } + else + { + CTI_ServerAddTransactionUpgrade(ItemIndex, NewUpgradeLevel); + } + +} + +// reliable server final function ServerBuyWeapon( byte ItemIndex, optional byte WeaponUpgrade ) +public reliable server function CTI_ServerBuyWeapon(int ItemIndex, optional int WeaponUpgrade ) +{ + local STraderItem PurchasedItem; + local int BlocksRequired; + + if (Role != ROLE_Authority || !bServerTraderMenuOpen) return; + if (!CTI_GetTraderItemFromWeaponLists(PurchasedItem, ItemIndex)) return; + + BlocksRequired = GetWeaponBlocks(PurchasedItem, WeaponUpgrade); + + if (CurrentCarryBlocks > CurrentCarryBlocks + BlocksRequired) return; + if (!CTI_ProcessWeaponDosh(PurchasedItem)) return; + + CTI_AddTransactionItem( PurchasedItem, WeaponUpgrade); +} + +// final function AddTransactionItem( const out STraderItem ItemToAdd, optional byte WeaponUpgrade ) +public function CTI_AddTransactionItem(const out STraderItem ItemToAdd, optional int WeaponUpgrade) +{ + local TransactionItem NewTransactionItem; + + if (Role < ROLE_Authority || !bServerTraderMenuOpen) return; + + NewTransactionItem.ClassName = ItemToAdd.ClassName; + NewTransactionItem.DLOString = ItemToAdd.WeaponDef.default.WeaponClassPath; + NewTransactionItem.AddedAmmo[0] = 0; + NewTransactionItem.AddedAmmo[1] = 0; + NewTransactionItem.WeaponUpgradeLevel = WeaponUpgrade; + + TransactionItems.AddItem(NewTransactionItem); + + AddCurrentCarryBlocks(GetWeaponBlocks(ItemToAdd, WeaponUpgrade)); +} + +// reliable server final function ServerAddTransactionItem( byte ItemIndex, optional byte WeaponUpgrade) +public reliable server function CTI_ServerAddTransactionItem(int ItemIndex, optional int WeaponUpgrade) +{ + local STraderItem PurchasedItem; + + if (Role != ROLE_Authority || !bServerTraderMenuOpen) return; + + if (CTI_GetTraderItemFromWeaponLists(PurchasedItem, ItemIndex)) + { + CTI_AddTransactionItem(PurchasedItem, WeaponUpgrade); + } +} + +// final function RemoveTransactionItem( const out STraderItem ItemToRemove ) +final function CTI_RemoveTransactionItem(const out STraderItem ItemToRemove) +{ + local int Index; + + if (Role < ROLE_Authority || !bServerTraderMenuOpen) return; + + Index = GetTransactionItemIndex( ItemToRemove.ClassName ); + + if (Index == INDEX_NONE) return; + + AddCurrentCarryBlocks(-GetDisplayedBlocksRequiredFor(ItemToRemove, TransactionItems[Index].WeaponUpgradeLevel)); + TransactionItems.Remove(Index, 1); +} + +// reliable server final function ServerRemoveTransactionItem( int ItemIndex ) +public reliable server final function CTI_ServerRemoveTransactionItem(int ItemIndex) +{ + local STraderItem ItemToRemove; + local KFWeapon InvWeap; + + if (!bServerTraderMenuOpen) return; + if (!CTI_GetTraderItemFromWeaponLists(ItemToRemove, ItemIndex)) return; + + CTI_RemoveTransactionItem(ItemToRemove); + + if (!GetWeaponFromClass(InvWeap, ItemToRemove.ClassName)) return; + + RemoveFromInventory(InvWeap); +} + +// reliable server final function ServerSellWeapon( byte ItemIndex ) +public reliable server function CTI_ServerSellWeapon(int ItemIndex) +{ + local STraderItem SoldItem; + local int SellPrice, TransactionIndex; + local KFWeapon KFW; + local KFPlayerReplicationInfo KFPRI; + + if (Role != ROLE_Authority || !bServerTraderMenuOpen) return; + + KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + + if (KFPRI == None) return; + + if (!CTI_GetTraderItemFromWeaponLists(SoldItem, ItemIndex)) return; + + if (GetWeaponFromClass(KFW, SoldItem.ClassName)) + { + SellPrice = GetAdjustedSellPriceFor(SoldItem); + KFPRI.AddDosh(SellPrice); + ServerRemoveFromInventory(KFW); + KFW.Destroy(); + } + else + { + TransactionIndex = GetTransactionItemIndex(SoldItem.ClassName); + + if (TransactionIndex == INDEX_NONE) return; + + SellPrice = GetAdjustedSellPriceFor(SoldItem); + KFPRI.AddDosh(SellPrice); + CTI_RemoveTransactionItem(SoldItem); + } +} + +// private final simulated function bool GetTraderItemFromWeaponLists(out STraderItem TraderItem, byte ItemIndex ) +private simulated function bool CTI_GetTraderItemFromWeaponLists(out STraderItem TraderItem, int ItemIndex) +{ + local CTI_GFxObject_TraderItems TraderItems; + + if (WorldInfo.GRI == None) return false; + + TraderItems = CTI_GFxObject_TraderItems(KFGameReplicationInfo(WorldInfo.GRI).TraderItems); + + if (TraderItems == None) return false; + + if (ItemIndex < TraderItems.AllItems.Length) + { + TraderItem = TraderItems.AllItems[ItemIndex]; + return true; + } + + return false; +} + +// private final function bool ProcessWeaponDosh(out STraderItem PurchasedItem) +private function bool CTI_ProcessWeaponDosh(out STraderItem PurchasedItem) +{ + local int BuyPrice; + local KFPlayerReplicationInfo KFPRI; + + KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + if (KFPRI == None) return false; + + BuyPrice = GetAdjustedBuyPriceFor(PurchasedItem); + + if (KFPRI.Score - BuyPrice >= 0) + { + KFPRI.AddDosh(-BuyPrice); + return true; + } + + return false; +} + +private function float AmmoCostScale() +{ + local KFGameReplicationInfo KFGRI; + KFGRI = KFGameReplicationInfo(WorldInfo.GRI); + return KFGRI == None ? 1.0f : KFGRI.GameAmmoCostScale; +} + +// private final function bool ProcessAmmoDosh(out STraderItem PurchasedItem, int AdditionalAmmo, optional bool bSecondaryAmmo) +private function bool CTI_ProcessAmmoDosh(out STraderItem PurchasedItem, int AdditionalAmmo, optional bool bSecondaryAmmo) +{ + local int BuyPrice; + local float PricePerMag, MagSize; + local KFPlayerReplicationInfo KFPRI; + + KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + if (KFPRI == None) return false; + + if (bSecondaryAmmo) + { + PricePerMag = AmmoCostScale() * PurchasedItem.WeaponDef.default.SecondaryAmmoMagPrice; + MagSize = PurchasedItem.WeaponDef.default.SecondaryAmmoMagSize; + BuyPrice = FCeil((PricePerMag / MagSize) * float(AdditionalAmmo)); + } + else + { + PricePerMag = AmmoCostScale() * PurchasedItem.WeaponDef.default.AmmoPricePerMag; + MagSize = PurchasedItem.MagazineCapacity; + BuyPrice = FCeil((PricePerMag / MagSize) * float(AdditionalAmmo)); + } + + if (KFPRI.Score - BuyPrice >= 0) + { + KFPRI.AddDosh(-BuyPrice); + return true; + } + + return false; +} + +// private final function bool ProcessUpgradeDosh(const out STraderItem PurchasedItem, int NewUpgradeLevel) +private function bool CTI_ProcessUpgradeDosh(const out STraderItem PurchasedItem, int NewUpgradeLevel) +{ + local int BuyPrice; + local KFPlayerController KFPC; + local KFPlayerReplicationInfo KFPRI; + + KFPC = KFPlayerController(Instigator.Owner); + KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + + if (KFPC == None || KFPRI == none) return false; + + BuyPrice = PurchasedItem.WeaponDef.static.GetUpgradePrice(NewUpgradeLevel); + if (BuyPrice <= KFPRI.Score) + { + KFPRI.AddDosh(-BuyPrice); + return true; + } + + return false; +} + +// private final function bool ProcessGrenadeDosh(int AmountPurchased) +private function bool CTI_ProcessGrenadeDosh(int AmountPurchased) +{ + local int BuyPrice; + local KFGFxObject_TraderItems TraderItems; + local KFPlayerController KFPC; + local KFPlayerReplicationInfo KFPRI; + + KFPC = KFPlayerController(Instigator.Owner); + KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + if (KFPC == None || KFPRI == None) return false; + + TraderItems = KFGameReplicationInfo(WorldInfo.GRI).TraderItems; + BuyPrice = TraderItems.GrenadePrice * AmountPurchased; + if (BuyPrice <= KFPRI.Score) + { + KFPRI.AddDosh(-BuyPrice); + return true; + } + + return false; +} + +// reliable server final private function ServerBuyArmor( float PercentPurchased ) +private reliable server function CTI_ServerBuyArmor(float PercentPurchased) +{ + local KFPawn_Human KFP; + local int AmountPurchased; + local float MaxArmor; + + KFP = KFPawn_Human(Instigator); + if (Role != ROLE_Authority || KFP == none || !bServerTraderMenuOpen) return; + if (!CTI_ProcessArmorDosh(PercentPurchased)) return; + + MaxArmor = KFP.GetMaxArmor(); + AmountPurchased = FCeil(MaxArmor * (PercentPurchased / 100.0)); + + KFP.AddArmor(AmountPurchased); +} + +// private final function bool ProcessArmorDosh(float PercentPurchased) +private function bool CTI_ProcessArmorDosh(float PercentPurchased) +{ + local int BuyPrice; + local KFGFxObject_TraderItems TraderItems; + local KFPlayerController KFPC; + local KFPerk CurrentPerk; + local int ArmorPricePerPercent; + local KFPlayerReplicationInfo KFPRI; + + KFPRI = KFPlayerReplicationInfo(Instigator.PlayerReplicationInfo); + if (KFPRI == None) return false; + + TraderItems = KFGameReplicationInfo(WorldInfo.GRI).TraderItems; + ArmorPricePerPercent = TraderItems.ArmorPrice; + + KFPC = KFPlayerController(Instigator.Owner); + if (KFPC != None) + { + CurrentPerk = KFPC.GetPerk(); + if (CurrentPerk != None) + { + ArmorPricePerPercent *= CurrentPerk.GetArmorDiscountMod(); + } + } + + BuyPrice = FCeil(ArmorPricePerPercent * PercentPurchased); + if (BuyPrice <= KFPRI.Score) + { + KFPRI.AddDosh(-BuyPrice); + return true; + } + + return false; +} + +// reliable server final private event ServerAddTransactionUpgrade(int ItemIndex, int NewUpgradeLevel) +private reliable server event CTI_ServerAddTransactionUpgrade(int ItemIndex, int NewUpgradeLevel) +{ + if (bServerTraderMenuOpen) + { + CTI_AddTransactionUpgrade(ItemIndex, NewUpgradeLevel); + } +} + +// final function AddTransactionUpgrade(int ItemIndex, int NewUpgradeLevel) +private function CTI_AddTransactionUpgrade(int ItemIndex, int NewUpgradeLevel) +{ + local STraderItem WeaponItem; + local int TransactionIndex; + + if (Role < ROLE_Authority || !bServerTraderMenuOpen) return; + + if (CTI_GetTraderItemFromWeaponLists(WeaponItem, ItemIndex)) + { + TransactionIndex = GetTransactionItemIndex(WeaponItem.ClassName); + if (TransactionIndex == INDEX_NONE) return; + + TransactionItems[TransactionIndex].WeaponUpgradeLevel = NewUpgradeLevel; + TransactionItems[TransactionIndex].AddedWeight = WeaponItem.WeaponUpgradeWeight[NewUpgradeLevel]; + if (NewUpgradeLevel > 0) + { + AddCurrentCarryBlocks(-WeaponItem.WeaponUpgradeWeight[NewUpgradeLevel-1]); + } + AddCurrentCarryBlocks(WeaponItem.WeaponUpgradeWeight[NewUpgradeLevel]); + } +} + +// reliable server final private function ServerBuyGrenade( int AmountPurchased ) +private reliable server function CTI_ServerBuyGrenade(int AmountPurchased) +{ + if (Role != ROLE_Authority || !bServerTraderMenuOpen) return; + + if (CTI_ProcessGrenadeDosh(AmountPurchased)) + { + AddGrenades(AmountPurchased); + } +} + +defaultproperties +{ + +} diff --git a/CTI/Classes/CTI_PawnHuman.uc b/CTI/Classes/CTI_PawnHuman.uc new file mode 100644 index 0000000..c6d3437 --- /dev/null +++ b/CTI/Classes/CTI_PawnHuman.uc @@ -0,0 +1,6 @@ +class CTI_PawnHuman extends KFPawn_Human; + +defaultproperties +{ + InventoryManagerClass=class'CTI_InventoryManager' +} diff --git a/CTI/Classes/CTI_RepInfo.uc b/CTI/Classes/CTI_RepInfo.uc index ada7ca7..e99ad83 100644 --- a/CTI/Classes/CTI_RepInfo.uc +++ b/CTI/Classes/CTI_RepInfo.uc @@ -3,9 +3,11 @@ class CTI_RepInfo extends ReplicationInfo const CAPACITY = 64; // max: 128 -const Trader = class'Trader'; -const LocalMessage = class'CTI_LocalMessage'; -const Replacements = class'WeaponReplacements'; +const Trader = class'Trader'; +const LocalMessage = class'CTI_LocalMessage'; +const Replacements = class'WeaponReplacements'; +const PurchaseHelper = class'CTI_AutoPurchaseHelper'; +const InventoryManager = class'CTI_InventoryManager'; struct ReplicationStruct { @@ -40,11 +42,14 @@ var private ReplicationStruct RepData; var private Array > RepArray; var private bool SkinUpdateRequired; +var private bool PatchRequired; + +var private bool ClientReady, ServerReady; replication { if (bNetInitial && Role == ROLE_Authority) - LogLevel, SkinUpdateRequired; + LogLevel, SkinUpdateRequired, PatchRequired; } public simulated function bool SafeDestroy() @@ -54,10 +59,36 @@ public simulated function bool SafeDestroy() return (bPendingDelete || bDeleteMe || Destroy()); } +public function PrepareSync( + CTI _CTI, KFPlayerController _KFPC, E_LogLevel _LogLevel, + bool _SkinUpdateRequired, bool _PatchRequired) +{ + `Log_Trace(); + + CTI = _CTI; + KFPC = _KFPC; + LogLevel = _LogLevel; + SkinUpdateRequired = _SkinUpdateRequired; + PatchRequired = _PatchRequired; +} + public function Replicate(const out Array > WeapDefs) { `Log_Trace(); + ServerReady = !PatchRequired; + + if (PatchRequired) + { + if (GetKFPC() != None) + { + KFPC.PurchaseHelperClass = PurchaseHelper; + KFPC.PurchaseHelper = None; + } + + InitInventoryManager(); + } + RepArray = WeapDefs; RepData.Size = RepArray.Length; @@ -111,16 +142,6 @@ private reliable client function Send(ReplicationStruct RD) Sync(); } -public function PrepareSync(CTI _CTI, KFPlayerController _KFPC, E_LogLevel _LogLevel, bool _SkinUpdateRequired) -{ - `Log_Trace(); - - CTI = _CTI; - KFPC = _KFPC; - LogLevel = _LogLevel; - SkinUpdateRequired = _SkinUpdateRequired; -} - private simulated function Progress(int Value, int Size) { `Log_Trace(); @@ -140,7 +161,7 @@ private simulated function Finished() `Log_Trace(); - if (GetGRI(WaitingGRI > WaitingGRIThreshold) == None && WaitingGRI++ < WaitingGRILimit) + if ((GetGRI(WaitingGRI > WaitingGRIThreshold) == None) && WaitingGRI++ < WaitingGRILimit) { `Log_Debug("Finished: Waiting GRI" @ WaitingGRI); NotifyWaitingGRI(); @@ -148,6 +169,12 @@ private simulated function Finished() return; } + if (PatchRequired && GetKFPC() != None) + { + KFPC.PurchaseHelperClass = PurchaseHelper; + KFPC.PurchaseHelper = None; + } + KFGRI = KFGameReplicationInfo(GRI); if (KFGRI != None) { @@ -165,39 +192,42 @@ private simulated function Finished() if (SkinUpdateRequired) { - SetTimer(1.0f, true, nameof(UpdateSkinsDLC)); + SkinUpdate(); } else { - ClientCleanup(); + ClientFinished(); } } -private simulated function UpdateSkinsDLC() +private simulated function SkinUpdate() { local SWeapReplace WeapReplace; - `Log_Debug("Wait for spawn"); - if (GetKFPRI() != None && KFPRI.bHasSpawnedIn) + if (GetKFPRI() == None || !KFPRI.bHasSpawnedIn) { - foreach Replacements.default.DLC(WeapReplace) - { - // sometimes "WeapReplace.Weap.default.SkinItemId" can give values greater than zero while actually being zero - // this is the same bug that prevents creating the correct default config - // so for now let’s shorten the check a little so that the skinId of the WeapReplace is guaranteed to be correct - // but if this bug is ever fixed, then it’s worth replacing the check with this one: - // if (WeapReplace.WeapParent.default.SkinItemId > 0 && WeapReplace.Weap.default.SkinItemId != WeapReplace.WeapParent.default.SkinItemId) - // to reduce the number of meaningless disk writes - if (WeapReplace.WeapParent.default.SkinItemId > 0) - { - `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(); + `Log_Debug("Wait for spawn (SkinUpdate)"); + SetTimer(1.0f, false, nameof(SkinUpdate)); + return; } + + foreach Replacements.default.DLC(WeapReplace) + { + // sometimes "WeapReplace.Weap.default.SkinItemId" can give values greater than zero while actually being zero + // this is the same bug that prevents creating the correct default config + // so for now let’s shorten the check a little so that the skinId of the WeapReplace is guaranteed to be correct + // but if this bug is ever fixed, then it’s worth replacing the check with this one: + // if (WeapReplace.WeapParent.default.SkinItemId > 0 && WeapReplace.Weap.default.SkinItemId != WeapReplace.WeapParent.default.SkinItemId) + // to reduce the number of meaningless disk writes + if (WeapReplace.WeapParent.default.SkinItemId > 0) + { + `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(SkinUpdate)); + ClientFinished(); } private simulated function GameReplicationInfo GetGRI(optional bool ForcedSearch = false) @@ -361,14 +391,19 @@ private simulated function KeepNotification() NotificationPercent); } -private simulated function ClientCleanup() +private reliable server function ClientFinished() { - `Log_Debug("Cleanup"); - ServerCleanup(); - SafeDestroy(); + ClientReady = true; + if (ClientReady && ServerReady) Cleanup(); } -private reliable server function ServerCleanup() +private function ServerFinished() +{ + ServerReady = true; + if (ClientReady && ServerReady) Cleanup(); +} + +private reliable server function Cleanup() { `Log_Trace(); @@ -380,6 +415,69 @@ private reliable server function ServerCleanup() } } +public function InitInventoryManager() +{ + local InventoryManager PrevInventoryManger; + local InventoryManager NextInventoryManger; + + local KFInventoryManager PrevKFInventoryManger; + local KFInventoryManager NextKFInventoryManger; + + local Inventory Item; + + `Log_Trace(); + + if (GetKFPRI() == None || !KFPRI.bHasSpawnedIn) + { + `Log_Debug("Wait for spawn (InventoryManager)"); + SetTimer(1.0f, false, nameof(InitInventoryManager)); + return; + } + + PrevInventoryManger = KFPC.Pawn.InvManager; + + KFPC.Pawn.InventoryManagerClass = InventoryManager; + NextInventoryManger = Spawn(KFPC.Pawn.InventoryManagerClass, KFPC.Pawn); + + if (NextInventoryManger == None) + { + `Log_Error("Can't spawn" @ String(KFPC.Pawn.InventoryManagerClass)); + ServerFinished(); + return; + } + + KFPC.Pawn.InvManager = NextInventoryManger; + KFPC.Pawn.InvManager.SetupFor(KFPC.Pawn); + + if (PrevInventoryManger == None) + { + KFPC.Pawn.AddDefaultInventory(); + } + else + { + for (Item = PrevInventoryManger.InventoryChain; Item != None; Item = PrevInventoryManger.InventoryChain) + { + PrevInventoryManger.RemoveFromInventory(Item); + NextInventoryManger.AddInventory(Item); + } + } + + PrevKFInventoryManger = KFInventoryManager(PrevInventoryManger); + NextKFInventoryManger = KFInventoryManager(NextInventoryManger); + + if (PrevKFInventoryManger != None && NextKFInventoryManger != None) + { + NextKFInventoryManger.GrenadeCount = PrevKFInventoryManger.GrenadeCount; + } + + PrevKFInventoryManger.InventoryChain = None; + PrevKFInventoryManger.Destroy(); + + `Log_Debug("InventoryManager initialized"); + + ServerFinished(); +} + private simulated function NotifyWaitingGRI() { if (!IsTimerActive(nameof(KeepNotification))) @@ -431,4 +529,7 @@ defaultproperties WaitingGRI = 0 WaitingGRIThreshold = 15 WaitingGRILimit = 30 + + ClientReady = false + ServerReady = false } diff --git a/CTI/Classes/Trader.uc b/CTI/Classes/Trader.uc index 30ff1eb..4f93721 100644 --- a/CTI/Classes/Trader.uc +++ b/CTI/Classes/Trader.uc @@ -154,16 +154,19 @@ public static simulated function OverwriteTraderItems( const out Array > WeapDefs, E_LogLevel LogLevel) { - local KFGFxObject_TraderItems TraderItems; + local CTI_GFxObject_TraderItems TraderItemsCTI; + local KFGFxObject_TraderItems TraderItemsDef; local STraderItem Item; local class WeapDef; local int MaxItemID; `Log_TraceStatic(); - TraderItems = GetTraderItems(KFGRI, LogLevel); + TraderItemsDef = GetTraderItems(KFGRI, LogLevel); + TraderItemsCTI = new class'CTI_GFxObject_TraderItems'; + TraderItemsCTI.AllItems = TraderItemsDef.SaleItems; - TraderItems.SaleItems.Length = 0; + TraderItemsCTI.SaleItems.Length = 0; MaxItemID = 0; `Log_Debug("Trader Items:"); @@ -171,13 +174,21 @@ public static simulated function OverwriteTraderItems( { Item.WeaponDef = WeapDef; Item.ItemID = MaxItemID++; - TraderItems.SaleItems.AddItem(Item); + TraderItemsCTI.SaleItems.AddItem(Item); + TraderItemsCTI.AllItems.AddItem(Item); `Log_Debug("[" $ MaxItemID $ "]" @ String(WeapDef)); } - TraderItems.SetItemsInfo(TraderItems.SaleItems); + foreach TraderItemsDef.SaleItems(Item) + { + Item.ItemID = MaxItemID++; + TraderItemsCTI.AllItems.AddItem(Item); + } - KFGRI.TraderItems = TraderItems; + TraderItemsCTI.SetItemsInfo(TraderItemsCTI.SaleItems); + TraderItemsCTI.SetItemsInfo(TraderItemsCTI.AllItems); + + KFGRI.TraderItems = TraderItemsCTI; } private static function bool WeaponClassIsUnique(String WeaponClassPath, const out Array > WeapDefs, E_LogLevel LogLevel) diff --git a/CTI/Classes/Unlocker.uc b/CTI/Classes/Unlocker.uc index ba5ca2b..dc4a3de 100644 --- a/CTI/Classes/Unlocker.uc +++ b/CTI/Classes/Unlocker.uc @@ -63,22 +63,11 @@ private static function bool Auto( out BoolWrapper DLCSkinUpdateRequired, E_LogLevel LogLevel) { - local bool CustomGFxManager; - `Log_TraceStatic(); if (KFGI == None) return false; - if (KFGameInfo_VersusSurvival(KFGI) != None) - { - CustomGFxManager = (KFGI.KFGFxManagerClass != class'KFGameInfo_VersusSurvival'.default.KFGFxManagerClass); - } - else - { - CustomGFxManager = (KFGI.KFGFxManagerClass != class'KFGameInfo'.default.KFGFxManagerClass); - } - - if (CustomGFxManager) + if (CustomGFxManager(KFGI)) { return ReplaceWeapons(KFGRI, WeapDefs, DLCSkinUpdateRequired, LogLevel); } @@ -89,6 +78,18 @@ private static function bool Auto( } } +public static function bool CustomGFxManager(KFGameInfo KFGI) +{ + if (KFGameInfo_VersusSurvival(KFGI) != None) + { + return (KFGI.KFGFxManagerClass != class'KFGameInfo_VersusSurvival'.default.KFGFxManagerClass); + } + else + { + return (KFGI.KFGFxManagerClass != class'KFGameInfo'.default.KFGFxManagerClass); + } +} + private static function bool ReplaceWeapons( KFGameReplicationInfo KFGRI, out Array > WeapDefs, @@ -170,13 +171,18 @@ private static function bool ReplaceFilter(KFGameInfo KFGI, E_LogLevel LogLevel) if (KFGI == None) return false; + if (CustomGFxManager(KFGI)) + { + `Log_Warn("Custom KFGFxMoviePlayer_Manager detected:" @ String(KFGI.KFGFxManagerClass) $ ". There may be compatibility issues."); + } + if (KFGameInfo_VersusSurvival(KFGI) != None) { - KFGI.KFGFxManagerClass = class'CTI_GFxMoviePlayer_Manager_Versus'; + KFGI.KFGFxManagerClass = class'CTI_GFxMoviePlayer_Manager_Versus_DLC'; } else { - KFGI.KFGFxManagerClass = class'CTI_GFxMoviePlayer_Manager'; + KFGI.KFGFxManagerClass = class'CTI_GFxMoviePlayer_Manager_DLC'; } return true;