1
0
KF2-Dev-Scripts/KFGame/Classes/KFAutoPurchaseHelper.uc

1483 lines
45 KiB
Ucode
Raw Normal View History

2020-12-13 15:01:13 +00:00
//=============================================================================
// KFAutoPurchaseHeler
//=============================================================================
// Hold logic for auto purchase
//=============================================================================
// Killing Floor 2
// Copyright (C) 2016 Tripwire Interactive LLC
//=============================================================================
class KFAutoPurchaseHelper extends Object within KFPlayerController
dependson(KFGFxMenu_Trader)
native(UI);
var KFPlayerReplicationInfo MyKFPRI;
var KFInventoryManager MyKFIM;
var KFGFxObject_TraderItems TraderItems;
var array<SItemInformation> OwnedItemList;
var SItemInformation GrenadeItem;
var SItemInformation ArmorItem;
var int TotalDosh; // The total amount of dosh we have
var bool bPendingDoshUpdate; // Set this to true if we spent money but haven't received acknowledgement from the server
var int TotalBlocks; // The total amount of blocks that our inventory takes up, plus any transactions
var byte MaxBlocks; // The maximum number of blocks available
var int PrevArmor;
var int CostPerAutofillCycle;
var int DoshBuffer;
2021-09-02 21:46:08 +00:00
var int ArmorMagSize; // Percentage of armor bought individually
2020-12-13 15:01:13 +00:00
function Initialize(optional bool bInitOwnedItems = true)
{
if( Pawn != none && PlayerReplicationInfo != none )
{
MyKFPRI = KFPlayerReplicationInfo( PlayerReplicationInfo );
MyKFIM = KFInventoryManager( Pawn.InvManager );
if( MyKFPRI != none && MyKFIM != none )
{
// Grab the weapons in our inventory and add them to a stored array called OwnedItemList
if (bInitOwnedItems)
{
InitializeOwnedItemList();
}
TotalBlocks = MyKFIM.CurrentCarryBlocks;
TotalDosh = MyKFPRI.Score;
MaxBlocks = MyKFIM.MaxCarryBlocks;
}
}
}
/*************************
@Name - Auto purchase
**************************/
function DoAutoPurchase()
{
local int PotentialDosh, i;
local Array <STraderItem> OnPerkWeapons;
local STraderItem TopTierWeapon;
local int ItemIndex;
local bool bSecondaryWeaponPurchased;
local bool bUpgradeSuccess;
local bool bAutoFillPurchasedItem;
local string AutoFillMessageString;
GetTraderItems();
if(CurrentPerk.AutoBuyLoadOutPath.length == 0)
{
`log("!!!Autobuy load out path not set!!!");
return;
}
for (i = 0; i < CurrentPerk.AutoBuyLoadOutPath.length; i++)
{
ItemIndex = TraderItems.SaleItems.Find('WeaponDef', CurrentPerk.AutoBuyLoadOutPath[i]);
if(ItemIndex != INDEX_NONE)
{
OnPerkWeapons.AddItem(TraderItems.SaleItems[ItemIndex]);
}
}
SellOffPerkWeapons();
TopTierWeapon = GetTopTierWeapon(OnPerkWeapons);
//can I afford my top teir without selling my current weapon?
if(!DoIOwnThisWeapon(TopTierWeapon) && GetCanAfford( GetAdjustedBuyPriceFor(TopTierWeapon) + DoshBuffer ) && CanCarry( TopTierWeapon ) )
{
bUpgradeSuccess = AttemptUpgrade(TotalDosh, OnPerkWeapons, true);
}
else
{
PotentialDosh = GetPotentialDosh();
bUpgradeSuccess = AttemptUpgrade(PotentialDosh+TotalDosh, OnPerkWeapons);
}
bAutoFillPurchasedItem = StartAutoFill();
if(DoIOwnThisWeapon(TopTierWeapon))
{
while(AttemptToPurchaseNextLowerTier(TotalDosh, OnPerkWeapons))
{
bSecondaryWeaponPurchased = true;
AttemptToPurchaseNextLowerTier(TotalDosh, OnPerkWeapons);
}
}
MyKFIM.ServerCloseTraderMenu();
if(bUpgradeSuccess)
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.WeaponUpgradeComepleteString;
}
else if(bSecondaryWeaponPurchased)
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.SecondaryWeaponPurchasedString;
}
else if(bAutoFillPurchasedItem)
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.AutoFillCompleteString;
}
else
{
AutoFillMessageString = class'KFCommon_LocalizedStrings'.default.NoItemsPurchasedString;
}
if(MyGFxHUD != none)
{
MyGFxHUD.ShowNonCriticalMessage( class'KFCommon_LocalizedStrings'.default.AutoTradeCompleteString$AutoFillMessageString );
}
}
function bool AttemptToPurchaseNextLowerTier(int UseableDosh, const out Array <STraderItem>OnPerkWeapons)
{
local int LastAfforableItemIndex;
local STraderItem TempTraderItem;
LastAfforableItemIndex = GetLastAffordableItemIndex(UseableDosh, OnPerkWeapons);
if(LastAfforableItemIndex != INDEX_NONE)
{
TempTraderItem = OnPerkWeapons[LastAfforableItemIndex];
PurchaseWeapon(TempTraderItem);
StartAutoFill();
return true;
}
return false;
}
function STraderItem GetTopTierWeapon(const out Array <STraderItem>OnPerkWeapons)
{
local STraderItem HighestValuedWeapon;
HighestValuedWeapon = GetHighValuedOnPerkWeapon(OnPerkWeapons);
return HighestValuedWeapon;
}
function bool AttemptUpgrade(int UseableDosh, const out Array<STraderItem> OnPerkWeapons, optional bool bHaveTopTier)
{
local STraderItem TempTraderItem;
local bool bUpgradeSuccess;
local int LastAfforableItemIndex;
local SItemInformation MyHighestValuedWeapon;
MyHighestValuedWeapon = GetHighValuedWeapon(OwnedItemList);
LastAfforableItemIndex = GetLastAffordableItemIndex(UseableDosh, OnPerkWeapons, MyHighestValuedWeapon);
if(LastAfforableItemIndex != INDEX_NONE)
{
TempTraderItem = OnPerkWeapons[LastAfforableItemIndex];
if(MyHighestValuedWeapon.DefaultItem.WeaponDef.default.BuyPrice < TempTraderItem.WeaponDef.default.BuyPrice)
{
//Sell on perk weapons
if(!bHaveTopTier)
{
SellOnPerkWeapons();
}
PurchaseWeapon(TempTraderItem);
bUpgradeSuccess = true;
}
}
return bUpgradeSuccess;
}
function int GetLastAffordableItemIndex(int UseableDosh, const out Array <STraderItem>OnPerkWeapons, optional SItemInformation TradeInItem)
{
local int LastAfforableItemIndex, i;
local STraderItem TempTraderItem;
local int TradeInItemWeight;
TradeInItemWeight = MyKFIM.GetDisplayedBlocksRequiredFor(TradeInItem.DefaultItem);
LastAfforableItemIndex = INDEX_NONE;
//figure out which weapon we can afford
for (i = 0; i < OnPerkWeapons.length; i++)
{
TempTraderItem = OnPerkWeapons[i];
if(UseableDosh > GetAdjustedBuyPriceFor(TempTraderItem) + DoshBuffer )
{
if(!DoIOwnThisWeapon(TempTraderItem) && !( (TotalBlocks - TradeInItemWeight + MyKFIM.GetDisplayedBlocksRequiredFor(TempTraderItem)) > MaxBlocks) && !IsInOwnedItemList(TempTraderItem.DualClassName))
{
LastAfforableItemIndex = i;
}
}
else
{
break;
}
}
return LastAfforableItemIndex;
}
function STraderItem GetHighValuedOnPerkWeapon(const out array<STraderItem> ItemList)
{
local STraderItem HighestValuedWeapon;
local int i;
for (i = 0; i < ItemList.length; i++)
{
if( HighestValuedWeapon.WeaponDef == none || ItemList[i].WeaponDef.default.BuyPrice > HighestValuedWeapon.WeaponDef.default.BuyPrice)
{
HighestValuedWeapon = ItemList[i];
}
}
return HighestValuedWeapon;
}
function SItemInformation GetHighValuedWeapon(const out array<SItemInformation> ItemList)
{
local SItemInformation HighestValuedWeapon;
local int i;
for (i = 0; i < ItemList.length; i++)
{
if(ItemList[i].DefaultItem.BlocksRequired == -1)
{
continue;
}
if( HighestValuedWeapon.DefaultItem.WeaponDef == none || ItemList[i].DefaultItem.WeaponDef.default.BuyPrice > HighestValuedWeapon.DefaultItem.WeaponDef.default.BuyPrice)
{
HighestValuedWeapon = ItemList[i];
}
}
return HighestValuedWeapon;
}
function SellOnPerkWeapons()
{
local int i;
for (i = 0; i < OwnedItemList.length; i++)
{
if( OwnedItemList[i].DefaultItem.AssociatedPerkClasses.length > 0 && OwnedItemList[i].DefaultItem.AssociatedPerkClasses[0] == CurrentPerk.Class && OwnedItemList[i].DefaultItem.BlocksRequired != -1)
{
SellWeapon(OwnedItemList[i], i);
i=-1;
}
}
}
function SellOffPerkWeapons()
{
local int i;
for (i = 0; i < OwnedItemList.length; i++)
{
if( OwnedItemList[i].DefaultItem.AssociatedPerkClasses[0] != CurrentPerk.Class && OwnedItemList[i].DefaultItem.BlocksRequired != -1 && OwnedItemList[i].SellPrice != 0 )
{
if(CurrentPerk.ShouldAutosellWeapon(OwnedItemList[i].DefaultItem.WeaponDef))
{
SellWeapon(OwnedItemList[i], i);
i=-1;
}
}
}
}
function bool DoIOwnThisWeapon(const out STraderItem TraderItem)
{
return OwnedItemList.Find('DefaultItem', TraderItem) != INDEX_NONE;
}
function int GetPotentialDosh()
{
local int PotentialDosh, i;
for (i = 0; i <OwnedItemList.length; i++)
{
if(OwnedItemList[i].SellPrice != 0)
{
PotentialDosh += OwnedItemList[i].SellPrice;
}
}
return PotentialDosh;
}
/******************
@Name - Trader Items
*******************/
function bool bCanPurchase(STraderItem SelectedItem, optional bool bReturnError = true)
{
local bool bCanAfford, bCanCarry, bNotOwned;
bCanAfford = GetCanAfford( GetAdjustedBuyPriceFor(SelectedItem) );
bCanCarry = CanCarry( SelectedItem );
bNotOwned = !DoIOwnThisWeapon(SelectedItem);
if (MyGfxManager != none && MyGfxManager.TraderMenu != none && bReturnError)
{
MyGFxManager.TraderMenu.PurchaseError(!bCanAfford, !bCanCarry);
}
return bCanCarry && bCanAfford && bNotOwned;
}
// Checks if we can have enough dosh to buy this item
function bool GetCanAfford(int BuyPrice)
{
if (BuyPrice > TotalDosh)
{
return false;
}
return true;
}
// Checks if we can have enough blocks to hold this item
function bool CanCarry(const out STraderItem Item, optional int OverrideLevelValue = INDEX_NONE)
{
if (TotalBlocks + MyKFIM.GetDisplayedBlocksRequiredFor(Item, OverrideLevelValue) > MaxBlocks)
{
return false;
}
return true;
}
function bool CanUpgrade(STraderItem SelectedItem, out int CanCarryIndex, out int bCanAffordIndex, optional bool bPlayDialog)
{
local bool bCanAfford, bCanCarry;
local int UpgradePrice;
local int ItemUpgradeLevel;
local KFPlayerController MyKFPC;
local int AddedWeightBlocks;
MyKFPC = Outer;
ItemUpgradeLevel = GetItemUpgradeLevelByClassName(SelectedItem.ClassName);
if (ItemUpgradeLevel == INDEX_NONE || !(ItemUpgradeLevel < SelectedItem.WeaponDef.default.UpgradePrice.length))
{
`log("Item at max level");
return false;
}
UpgradePrice = SelectedItem.WeaponDef.static.GetUpgradePrice(ItemUpgradeLevel);
bCanAfford = GetCanAfford(UpgradePrice);
AddedWeightBlocks = SelectedItem.WeaponUpgradeWeight[ItemUpgradeLevel + 1] - SelectedItem.WeaponUpgradeWeight[ItemUpgradeLevel];
bCanCarry = !(TotalBlocks + AddedWeightBlocks > MaxBlocks);
//bCanUpgrade = MyKFIM.ItemEligableForUpgrade(SelectedItem);
if (bPlayDialog)
{
MyKFPC.PlayTraderSelectItemDialog(!bCanAfford, !bCanCarry);
}
CanCarryIndex = bCanCarry ? 1 : 0;
bCanAffordIndex = bCanAfford ? 1 : 0;
return bCanAfford && bCanCarry;
}
function PurchaseWeapon(STraderItem ShopItem)
{
local int ItemUpgradeLevel;
if(!bCanPurchase(ShopItem, true))
{
return;
}
ItemUpgradeLevel = ShopItem.SingleClassName != '' ?
GetItemUpgradeLevelByClassName(ShopItem.SingleClassName) :
INDEX_None;
AddDosh(-GetAdjustedBuyPriceFor(ShopItem));
AddBlocks(MyKFIM.GetWeaponBlocks(ShopItem, ItemUpgradeLevel));
AddWeaponToOwnedItemList(ShopItem);
}
function SellWeapon(SItemInformation ItemInfo, optional int SelectedItemIndex = -1)
{
AddDosh(GetAdjustedSellPriceFor(ItemInfo.DefaultItem));
AddBlocks( -MyKFIM.GetDisplayedBlocksRequiredFor(ItemInfo.DefaultItem) );
if(SelectedItemIndex != INDEX_NONE)
{
RemoveWeaponFromOwnedItemList( SelectedItemIndex );
}
}
function bool UpgradeWeapon(int OwnedItemIndex)
{
local byte ItemIndex;
local STraderItem DefaultItemInfo;
local SItemInformation ItemInfo;
local int Test1, Test2; //place holder ints
ItemInfo = OwnedItemList[OwnedItemIndex];
DefaultItemInfo = ItemInfo.DefaultItem;
if (ItemInfo.bIsSecondaryAmmo || !CanUpgrade(DefaultItemInfo, Test1, Test2, true))
{
`log("cannot upgrade");
return false;
}
TraderItems.GetItemIndicesFromArche(ItemIndex, DefaultItemInfo.ClassName);
MyKFIM.BuyUpgrade(ItemIndex, ItemInfo.ItemUpgradeLevel);
OwnedItemList[OwnedItemIndex].SellPrice = GetAdjustedSellPriceFor(DefaultItemInfo);
if (MyGfxManager != none && MyGfxManager.TraderMenu != none)
{
MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList;
}
return true;
}
/******************
@Name - Player Inventory
*******************/
function int GetFillArmorCost()
{
2021-09-02 21:46:08 +00:00
// local float ArmorPercentage, FillCost, ArmorPricePerPercent;
2020-12-13 15:01:13 +00:00
2021-09-02 21:46:08 +00:00
// ArmorPercentage = (float() / float(ArmorItem.MaxSpareAmmo)) * 100.f;
// ArmorPricePerPercent = ArmorItem.AmmoPricePerMagazine;
// FillCost = FCeil( (ArmorItem.SpareAmmoCount - ArmorItem.MaxSpareAmmo) * ArmorItem.AmmoPricePerMagazine );
2020-12-13 15:01:13 +00:00
2021-09-02 21:46:08 +00:00
return FCeil( (ArmorItem.MaxSpareAmmo - ArmorItem.SpareAmmoCount) * ArmorItem.AmmoPricePerMagazine );
}
function int GetChunkArmorCost()
{
return FCeil ( FMin(ArmorItem.MaxSpareAmmo - ArmorItem.SpareAmmoCount, ArmorMagSize) * ArmorItem.AmmoPricePerMagazine );
2020-12-13 15:01:13 +00:00
}
function int FillArmor( )
{
local float ArmorPricePerPercent, FillCost;
local float PercentBoughtUnit, PercentArmorBought;
local int ActualArmorPointsAvailable;
FillCost = GetFillArmorCost();
ActualArmorPointsAvailable = ArmorItem.MaxSpareAmmo - ArmorItem.SpareAmmoCount;
PercentBoughtUnit = float(ActualArmorPointsAvailable) / float(ArmorItem.MaxSpareAmmo);
PercentArmorBought = PercentBoughtUnit * 100.f;
// Buy as much armor as we possibly can
if (FillCost > TotalDosh)
{
ArmorPricePerPercent = ArmorItem.AmmoPricePerMagazine;
// Because we are using ints this will round down and we can get how much we actually spent
PercentArmorBought = TotalDosh / ArmorPricePerPercent;
PercentBoughtUnit = PercentArmorBought / 100.f;
FillCost = ArmorPricePerPercent * PercentArmorBought;
}
PercentArmorBought = (PercentArmorBought > 0.f && PercentArmorBought < 1.f) ? 1.f : PercentArmorBought;
ArmorItem.SpareAmmoCount = FMin( float(ArmorItem.SpareAmmoCount) + (PercentBoughtUnit * float(ArmorItem.MaxSpareAmmo)), float(ArmorItem.MaxSpareAmmo) );
BoughtAmmo(PercentArmorBought, FillCost, EIT_Armor);
return FillCost;
}
2021-09-02 21:46:08 +00:00
function int BuyArmorMag( )
{
local float ArmorPricePerPercent;
local float ChunkCost;
local float ArmorAvailable;
local float PercentArmorBought;
local float ArmorAmmountBought;
ArmorAvailable = (1 - float(ArmorItem.SpareAmmoCount) / ArmorItem.MaxSpareAmmo) * 100;
ArmorAmmountBought = ArmorMagSize;
PercentArmorBought = ArmorMagSize * 100.0f / ArmorItem.MaxSpareAmmo;
if (ArmorAvailable < PercentArmorBought)
return FillArmor();
ChunkCost = ArmorAmmountBought * ArmorItem.AmmoPricePerMagazine;
// Buy as much armor as we possibly can
if (ChunkCost > TotalDosh)
{
ArmorPricePerPercent = ArmorItem.AmmoPricePerMagazine;
// Because we are using ints this will round down and we can get how much we actually spent
PercentArmorBought = TotalDosh / ArmorPricePerPercent;
ChunkCost = ArmorPricePerPercent * PercentArmorBought;
ArmorAmmountBought = ArmorItem.MaxSpareAmmo * PercentArmorBought / 100;
}
PercentArmorBought = (PercentArmorBought > 0.f && PercentArmorBought < 1.f) ? 1.f : PercentArmorBought;
ArmorItem.SpareAmmoCount = FMin(ArmorItem.SpareAmmoCount + ArmorAmmountBought, ArmorItem.MaxSpareAmmo);
BoughtAmmo(PercentArmorBought, ChunkCost, EIT_Armor);
return ChunkCost;
}
2020-12-13 15:01:13 +00:00
function bool AttemptBuyArmorChunk( out int InAutoFillDosh )
{
2021-09-02 21:46:08 +00:00
local float PercentArmorBought;
local int ArmorPricePerPercent;
local int ChunkCost;
local int ActualArmorPointsAvailable;
ActualArmorPointsAvailable = ArmorItem.MaxSpareAmmo - ArmorItem.SpareAmmoCount;
2020-12-13 15:01:13 +00:00
ArmorPricePerPercent = ArmorItem.AmmoPricePerMagazine;
2021-09-02 21:46:08 +00:00
PercentArmorBought = 0;
2020-12-13 15:01:13 +00:00
if( ArmorItem.SpareAmmoCount < ArmorItem.MaxSpareAmmo )
{
// Because we are using int's this will round down and we can get how much we actually spent
2021-09-02 21:46:08 +00:00
PercentArmorBought = FMin(CostPerAutofillCycle / ArmorPricePerPercent, float(ActualArmorPointsAvailable));
ChunkCost = ArmorPricePerPercent * PercentArmorBought;
2020-12-13 15:01:13 +00:00
if( InAutoFillDosh < ChunkCost )
{
2021-09-02 21:46:08 +00:00
PercentArmorBought = FMin(InAutoFillDosh / ArmorPricePerPercent, float(ActualArmorPointsAvailable));
ChunkCost = ArmorPricePerPercent * PercentArmorBought;
2020-12-13 15:01:13 +00:00
}
InAutoFillDosh -= ChunkCost;
2021-09-02 21:46:08 +00:00
PercentArmorBought = (PercentArmorBought > 0.f && PercentArmorBought < 1.f) ? 1.f : PercentArmorBought;
2021-10-05 17:50:32 +00:00
ArmorItem.SpareAmmoCount = FMin(ArmorItem.SpareAmmoCount + PercentArmorBought, ArmorItem.MaxSpareAmmo);
2020-12-13 15:01:13 +00:00
BoughtAmmo(PercentArmorBought, ChunkCost, EIT_Armor);
}
2021-09-02 21:46:08 +00:00
2020-12-13 15:01:13 +00:00
return (PercentArmorBought > 0);
}
//grenade
function int GetFillGrenadeCost( )
{
local int AmmoCount, MaxAmmoCount;
local float MissingAmmo, PricePerMag;
AmmoCount = GrenadeItem.SpareAmmoCount;
MaxAmmoCount = GrenadeItem.MaxSpareAmmo;
PricePerMag = GrenadeItem.AmmoPricePerMagazine;
MissingAmmo = MaxAmmoCount - AmmoCount;
// Use FCeil so you can never buy ammo for 0 Do$h on an int conversion
return FCeil(MissingAmmo * PricePerMag);
}
function int BuyGrenade( )
{
local int MagAmmoCost;
MagAmmoCost = 0;
if( (GrenadeItem.MaxSpareAmmo - GrenadeItem.SpareAmmoCount) > 0 )
{
MagAmmoCost = GrenadeItem.AmmoPricePerMagazine;
GrenadeItem.SpareAmmoCount += 1;
BoughtAmmo(1, MagAmmoCost, EIT_Grenade);
}
return MagAmmoCost;
}
// Ammo
//@todo give item information rather than index
function int BuySecondaryAmmoMag( out SItemInformation ItemInfo )
{
local int MagAmmoCost;
local int MagSpaceAvailable;
local int AddedAmmo;
local float AmmoCostScale;
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
AmmoCostScale = KFGRI.GameAmmoCostScale;
}
else
{
AmmoCostScale = 1.0;
}
MagAmmoCost = 0;
MagSpaceAvailable = ItemInfo.MaxSecondaryAmmo - ItemInfo.SecondaryAmmoCount;
if( MagSpaceAvailable > 0 )
{
MagAmmoCost = AmmoCostScale * ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagPrice;
// Don't charge them full price if they don't buy a full mag's worth of ammo
// or we can only afford part of a magazine
if( (MagSpaceAvailable < ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagSize) || (TotalDosh < MagAmmoCost) )
{
return FillAmmo( ItemInfo );
}
AddedAmmo = ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagSize;
ItemInfo.SecondaryAmmoCount += AddedAmmo;
ItemInfo.SecondaryAmmoCount = Min( ItemInfo.MaxSecondaryAmmo, ItemInfo.SecondaryAmmoCount );
BoughtAmmo(AddedAmmo, MagAmmoCost, EIT_Weapon, ItemInfo.DefaultItem.ClassName, ItemInfo.bIsSecondaryAmmo);
}
return MagAmmoCost;
}
function int BuyMagazine( int ItemSlotIndex )
{
local SItemInformation ItemInfo;
local int MagCost;
ItemInfo = OwnedItemList[ ItemSlotIndex ];
if( ItemInfo.bIsSecondaryAmmo )
{
MagCost = BuySecondaryAmmoMag( ItemInfo );
}
else
{
MagCost = BuyItemMagazine( ItemInfo );
}
OwnedItemList[ ItemSlotIndex ] = ItemInfo;
return MagCost;
}
function int BuyItemMagazine( out SItemInformation ItemInfo )
{
local int MagAmmoCost;
local int MagSpaceAvailable;
MagAmmoCost = 0;
MagSpaceAvailable = ItemInfo.MaxSpareAmmo - ItemInfo.SpareAmmoCount;
if( MagSpaceAvailable > 0 )
{
MagAmmoCost = ItemInfo.AmmoPricePerMagazine;
// Don't charge them full price if they don't buy a full mag's worth of ammo
// or we can only afford part of a magazine
if( (MagSpaceAvailable < ItemInfo.DefaultItem.MagazineCapacity) || (TotalDosh < MagAmmoCost) )
{
return FillAmmo( ItemInfo );
}
ItemInfo.SpareAmmoCount += ItemInfo.DefaultItem.MagazineCapacity;
ItemInfo.SpareAmmoCount = Min( ItemInfo.MaxSpareAmmo, ItemInfo.SpareAmmoCount );
BoughtAmmo(ItemInfo.DefaultItem.MagazineCapacity, MagAmmoCost, EIT_Weapon, ItemInfo.DefaultItem.ClassName, ItemInfo.bIsSecondaryAmmo);
}
return MagAmmoCost;
}
function float FillAmmo( out SItemInformation ItemInfo, optional bool bIsGrenade )
{
local float MissingAmmo, MagSize;
local float FillAmmoCost, PricePerMag;
local float PricePerRound;
local float AmmoCostScale;
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
AmmoCostScale = KFGRI.GameAmmoCostScale;
}
else
{
AmmoCostScale = 1.0;
}
if( ItemInfo.bIsSecondaryAmmo )
{
MagSize = ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagSize;
PricePerMag = AmmoCostScale * ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagPrice;
MissingAmmo = ItemInfo.MaxSecondaryAmmo - ItemInfo.SecondaryAmmoCount;
FillAmmoCost = GetFillAmmoCost(ItemInfo);
}
else
{
MagSize = ItemInfo.DefaultItem.MagazineCapacity;
PricePerMag = ItemInfo.AmmoPricePerMagazine;
MissingAmmo = ItemInfo.MaxSpareAmmo - ItemInfo.SpareAmmoCount;
FillAmmoCost = ( bIsGrenade ) ? GetFillGrenadeCost() : GetFillAmmoCost(ItemInfo);
}
// If we cannot fill all our ammo, fill as much as possible
if ( FillAmmoCost > TotalDosh )
{
PricePerRound = ( bIsGrenade ) ? PricePerMag : PricePerMag / MagSize;
MissingAmmo = FFloor(TotalDosh / PricePerRound);
FillAmmoCost = FCeil(MissingAmmo * PricePerRound);
}
if( ItemInfo.bIsSecondaryAmmo )
{
ItemInfo.SecondaryAmmoCount += MissingAmmo;
}
else
{
ItemInfo.SpareAmmoCount += MissingAmmo;
}
if( bIsGrenade )
{
BoughtAmmo(MissingAmmo, FillAmmoCost, EIT_Grenade);
}
else
{
BoughtAmmo(MissingAmmo, FillAmmoCost, EIT_Weapon, ItemInfo.DefaultItem.ClassName, ItemInfo.bIsSecondaryAmmo);
}
return FillAmmoCost;
}
//Refresh player inventory
/** Returns the cost to refill this items ammo */
function int GetFillAmmoCost( out SItemInformation ItemInfo )
{
local int AmmoCount, MaxAmmoCount;
local float MissingAmmo, PricePerMag, MagSize, PricePerRound;
local float AmmoCostScale;
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
AmmoCostScale = KFGRI.GameAmmoCostScale;
}
else
{
AmmoCostScale = 1.0;
}
if( ItemInfo.bIsSecondaryAmmo )
{
AmmoCount = ItemInfo.SecondaryAmmoCount;
MaxAmmoCount = ItemInfo.MaxSecondaryAmmo;
PricePerMag = AmmoCostScale * ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagPrice;
MagSize = ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagSize;
}
else
{
AmmoCount = ItemInfo.SpareAmmoCount;
MaxAmmoCount = ItemInfo.MaxSpareAmmo;
PricePerMag = ItemInfo.AmmoPricePerMagazine;
MagSize = ItemInfo.DefaultItem.MagazineCapacity;
}
if( MagSize <= 0 )
{
return 0;
}
MissingAmmo = MaxAmmoCount - AmmoCount;
PricePerRound = PricePerMag / MagSize;
// Use FCeil so you can never buy ammo for 0 Do$h on an int conversion
return FCeil(MissingAmmo * PricePerRound);
}
// auto fill
// Change the look of the button dependant on if we can afford it, or are at max capacity
function bool AttemptAutoFillOnItem( out SItemInformation ItemInfo, out int InAutoFillDosh, int Price )
{
local int DoshSpent;
DoshSpent = Min(InAutoFillDosh, CostPerAutofillCycle);
InAutoFillDosh -= DoshSpent;
ItemInfo.AutoFillDosh += DoshSpent;
return ( ItemInfo.AutoFillDosh >= Price );
}
/** Take all dosh out of current weapons and pool it back into AutoFillDosh for the final cycle */
function RePoolAutoFillDosh( out int AutoFillDosh )
{
local byte i;
// If we could not buy anything else, clear all cached dosh and buy whatevers possible
for (i = 0; i < OwnedItemList.Length; i++)
{
AutoFillDosh += OwnedItemList[ i ].AutoFillDosh;
OwnedItemList[ i ].AutoFillDosh = 0;
}
AutoFillDosh += ArmorItem.AutoFillDosh;
ArmorItem.AutoFillDosh = 0;
AutoFillDosh += GrenadeItem.AutoFillDosh;
GrenadeItem.AutoFillDosh = 0;
}
/** Empty out any cached dosh in weapons once we've finished autofilling */
function ClearAutoFillDosh()
{
local byte i;
// If we could not buy anything else, clear all cached dosh and buy whatevers possible
for (i = 0; i < OwnedItemList.Length; i++)
{
OwnedItemList[ i ].AutoFillDosh = 0;
}
ArmorItem.AutoFillDosh = 0;
GrenadeItem.AutoFillDosh = 0;
}
function bool AutoFillOwnedItems( out int AutoFillDosh, bool bLastCycle )
{
local int i, PricePerMag, AmmoCount, MaxAmmoCount;
local SItemInformation ItemInfo;
local float AmmoCostScale;
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
AmmoCostScale = KFGRI.GameAmmoCostScale;
}
else
{
AmmoCostScale = 1.0;
}
for (i = 0; i < OwnedItemList.Length; i++)
{
ItemInfo = OwnedItemList[ i ];
if( ItemInfo.bIsSecondaryAmmo )
{
PricePerMag = AmmoCostScale * ItemInfo.DefaultItem.WeaponDef.default.SecondaryAmmoMagPrice;
AmmoCount = ItemInfo.SecondaryAmmoCount;
MaxAmmoCount = ItemInfo.MaxSecondaryAmmo;
}
else
{
PricePerMag = ItemInfo.AmmoPricePerMagazine;
AmmoCount = ItemInfo.SpareAmmoCount;
MaxAmmoCount = ItemInfo.MaxSpareAmmo;
}
// Only buy ammo if we are missing any
if ( AmmoCount < MaxAmmoCount )
{
if( bLastCycle )
{
AutoFillDosh -= FillAmmo( ItemInfo );
}
else if( AttemptAutoFillOnItem(ItemInfo, AutoFillDosh, PricePerMag) )
{
ItemInfo.AutoFillDosh -= BuyMagazine(i);
OwnedItemList[ i ].AutoFillDosh = ItemInfo.AutoFillDosh;
return true;
}
OwnedItemList[ i ] = ItemInfo;
}
}
return false;
}
function bool StartAutoFill()
{
local int AutoFillDosh;
local bool bBoughtSomething;
local bool bLastCycle;
local bool bAutoFillPurchasedItem;
bLastCycle = false;
AutoFillDosh = TotalDosh;
// try and buy items until we cannot afford anything else or we've bought everything
while( true )
{
// Tries to buy ammo for the highest priority weapon with missing ammo, unless we're on the last cycle in which case buy for all weapons
bBoughtSomething = AutoFillOwnedItems(AutoFillDosh, bLastCycle);
// Fill armor
if( ArmorItem.SpareAmmoCount < ArmorItem.MaxSpareAmmo )
{
if( bLastCycle )
{
AutoFillDosh -= FillArmor();
}
else if( AttemptBuyArmorChunk( AutoFillDosh ) )
{
bBoughtSomething = true;
}
}
// Fill grenades
if( GrenadeItem.SpareAmmoCount < GrenadeItem.MaxSpareAmmo )
{
if( bLastCycle )
{
AutoFillDosh -= FillAmmo(GrenadeItem, true);
}
else if( AttemptAutoFillOnItem(GrenadeItem, AutoFillDosh, GrenadeItem.AmmoPricePerMagazine) )
{
GrenadeItem.AutoFillDosh -= BuyGrenade();
bBoughtSomething = true;
}
}
if( bLastCycle )
{
break;
}
else if( !bBoughtSomething )
{
// buy whatever we can with our last cycle
if( !bLastCycle )
{
// Return all accumulated dosh from weapons to AutoFillDosh
RePoolAutoFillDosh(AutoFillDosh);
bLastCycle = true;
}
}
if( !bAutoFillPurchasedItem )
{
bAutoFillPurchasedItem = bBoughtSomething;
}
bBoughtSomething = false;
}
ClearAutoFillDosh();
return bAutoFillPurchasedItem;
}
//This is for external use of the UI. DO NOT use this in the menu. -ZG
function Int GetAutoFillCost()
{
local byte SlotIndex;
local int FillAmmoCost, AutoFillCost;
local SItemInformation ItemInfo;
AutoFillCost += GetFillArmorCost();
AutoFillCost += GetFillGrenadeCost();
// Iterate through all the items to get the auto fill cost, and update the items
// for the page we are currently on
for ( SlotIndex = 0; SlotIndex < OwnedItemList.Length; SlotIndex++ )
{
ItemInfo = OwnedItemList[SlotIndex];
FillAmmoCost = GetFillAmmoCost(ItemInfo);
AutoFillCost += FillAmmoCost;
}
return AutoFillCost;
}
/******************
@Name - General
*******************/
function InitializeOwnedItemList()
{
local Inventory Inv;
local KFWeapon KFW;
local KFPawn_Human KFP;
local bool AllowGrenades;
OwnedItemList.length = 0;
TraderItems = KFGameReplicationInfo( WorldInfo.GRI ).TraderItems;
AllowGrenades = KFGameReplicationInfo( WorldInfo.GRI ).bAllowGrenadePurchase;
KFP = KFPawn_Human( Pawn );
if( KFP != none )
{
// init armor purchase values
ArmorItem.SpareAmmoCount = KFP.Armor;
ArmorItem.MaxSpareAmmo = KFP.GetMaxArmor();
ArmorItem.AmmoPricePerMagazine = TraderItems.ArmorPrice * CurrentPerk.GetArmorDiscountMod();
ArmorItem.DefaultItem.WeaponDef = TraderItems.ArmorDef;
// init grenade purchase values
GrenadeItem.SpareAmmoCount = MyKFIM.GrenadeCount;
GrenadeItem.MaxSpareAmmo = AllowGrenades ? KFP.GetPerk().MaxGrenadeCount : 0;
GrenadeItem.AmmoPricePerMagazine = TraderItems.GrenadePrice;
GrenadeItem.DefaultItem.WeaponDef = CurrentPerk.GetGrenadeWeaponDef();
// @temp: fill in stuff that is normally serialized in the archetype
GrenadeItem.DefaultItem.AssociatedPerkClasses[0] = CurrentPerk.Class;
for ( Inv = MyKFIM.InventoryChain; Inv != none; Inv = Inv.Inventory )
{
KFW = KFWeapon( Inv );
if( KFW != none )
{
// Set the weapon information and add it to the OwnedItemList
SetWeaponInformation( KFW );
}
}
if(MyGfxManager != none && MyGfxManager.TraderMenu != none)
{
MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList;
}
}
}
/** returns true if item can be bought/sold at trader */
function bool IsSellable(const out STraderItem TraderItem)
{
return (TraderItem.WeaponDef != None && TraderItem.WeaponDef.default.BuyPrice > 0);
}
/** Called from KFGFxTraderContainer_Store */
simulated function int GetAdjustedBuyPriceFor( const out STraderItem ShopItem )
{
return MyKFIM.GetAdjustedBuyPriceFor( ShopItem, OwnedItemList );
}
simulated function int GetAdjustedSellPriceFor(const out STraderItem ShopItem)
{
return MyKFIM.GetAdjustedSellPriceFor(ShopItem, OwnedItemList);
}
simulated function int GetAdjustedUpgradePriceFor(const out STraderItem ItemInfo, int UpgradeLevel)
{
return MyKFIM.GetAdjustedUpgradePriceFor(ItemInfo, UpgradeLevel);
}
simulated function int GetItemUpgradeLevelByClassName(name ClassName)
{
local int i;
local name OwnedItemClassName;
for (i = 0; i < OwnedItemList.Length; i++)
{
OwnedItemClassName = OwnedItemList[i].DefaultItem.ClassName;
if (OwnedItemClassName == '')
{
`warn("Owned item with Class NAME_None");
continue;
}
else if (OwnedItemClassName == ClassName)
{
return OwnedItemList[i].ItemUpgradeLevel;
}
}
return 0;
}
function bool IsInOwnedItemList( name ItemName )
{
local int i;
local name OwnedItemClassName;
for (i = 0; i < OwnedItemList.Length; i++)
{
OwnedItemClassName = OwnedItemList[i].DefaultItem.ClassName;
if ( OwnedItemClassName == '' )
{
`warn("Owned item with Class NAME_None");
continue;
}
else if ( OwnedItemClassName == ItemName )
{
return true;
}
}
return false;
}
function AddDosh( int AddedDosh )
{
TotalDosh = Max( TotalDosh + AddedDosh, 0 );
if(Role < ROLE_Authority)
{
bPendingDoshUpdate = true;
// If we have not heard anything back form the server, update the clients dosh value
SetTimer(2.0f, false, nameof(UpdateCurrentDosh), self);
}
}
simulated function NotifyDoshChanged()
{
// If we've spent dosh just prior to receiving an update, keep our client value and wait for the next server update
if( bPendingDoshUpdate )
{
bPendingDoshUpdate = false;
if(MyKFPRI.Score != TotalDosh)
{
return;
}
}
UpdateCurrentDosh();
}
simulated function UpdateCurrentDosh()
{
// If we receive dosh outside of the menu update our TotalDosh and refresh the menus
TotalDosh = Max( MyKFPRI.Score, 0 );
if(MyGfxManager != none && MyGfxManager.TraderMenu != none)
{
MyGfxManager.TraderMenu.RefreshItemComponents();
}
bPendingDoshUpdate = false;
ClearTimer(nameof(UpdateCurrentDosh), self);
}
function BoughtAmmo(float AmountPurchased, int Price, EItemType ItemType, optional name ClassName, optional bool bIsSecondaryAmmo)
{
local byte ItemIndex;
AddDosh( -Price );
if( ItemType == EIT_Weapon )
{
// Get the proper weapon prices from the servers trader archetype
TraderItems.GetItemIndicesFromArche(ItemIndex, ClassName);
}
MyKFIM.BuyAmmo( AmountPurchased, ItemType, ItemIndex, bIsSecondaryAmmo );
}
function SetWeaponInformation( KFWeapon KFW )
{
local int i;
for (i = 0; i < TraderItems.SaleItems.Length; i++)
{
if( KFW.Class.name == TraderItems.SaleItems[i].ClassName )
{
SetWeaponInfo(KFW, TraderItems.SaleItems[i]);
return;
}
}
}
/** Add a currently owned item to the "OwnedItemList" on initialization */
function SetWeaponInfo(const KFWeapon KFW, STraderItem DefaultItem)
{
local SItemInformation WeaponInfo;
local float AmmoCostScale;
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
AmmoCostScale = KFGRI.GameAmmoCostScale;
}
else
{
AmmoCostScale = 1.0;
}
// Include current magazine ammo in spare ammo count
WeaponInfo.SpareAmmoCount = KFW.GetTotalAmmoAmount(0);
// Max spare ammo already includes perk modifications and magazine capacity
WeaponInfo.MaxSpareAmmo = KFW.GetMaxAmmoAmount(0);
WeaponInfo.MagazineCapacity = KFW.MagazineCapacity[0];
WeaponInfo.SecondaryAmmoCount = KFW.GetTotalAmmoAmount(1);
WeaponInfo.MaxSecondaryAmmo = KFW.GetMaxAmmoAmount(1);
WeaponInfo.DefaultItem = DefaultItem;
WeaponInfo.ItemUpgradeLevel = KFW.CurrentWeaponUpgradeIndex;
WeaponInfo.AmmoPricePerMagazine = AmmoCostScale * DefaultItem.WeaponDef.default.AmmoPricePerMag;
WeaponInfo.SellPrice = GetAdjustedSellPriceFor(DefaultItem);
AddItemByPriority( WeaponInfo );
// if adding a dual, remove the related single
if( DefaultItem.SingleClassName != '' )
{
RemoveWeaponFromOwnedItemList( , DefaultItem.SingleClassName, true );
}
}
// We've bought a new item, add its information to our owned item list
function int AddWeaponToOwnedItemList( STraderItem DefaultItem, optional bool bDoNotBuy, optional int OverrideItemUpgradeLevel = INDEX_NONE )
{
local SItemInformation WeaponInfo;
local byte ItemIndex;
local int AddedWeaponIndex, OwnedSingleIdx, SingleDualAmmoDiff;
local bool bAddingDual;
local float AmmoCostScale;
local KFGameReplicationInfo KFGRI;
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
if (KFGRI != none)
{
AmmoCostScale = KFGRI.GameAmmoCostScale;
}
else
{
AmmoCostScale = 1.0;
}
// Magazine capacity affects both spare ammo and max spare ammo. modify this first
WeaponInfo.MagazineCapacity = DefaultItem.MagazineCapacity;
CurrentPerk.ModifyMagSizeAndNumber( none, WeaponInfo.MagazineCapacity, DefaultItem.AssociatedPerkClasses,, DefaultItem.ClassName );
// Newly bought weapons need to have their default values modified by the current perk
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;
// if adding a dual, adjust the displayed ammo count to reflect ammo of single
bAddingDual = DefaultItem.SingleClassName != '';
if( bAddingDual )
{
for( OwnedSingleIdx = 0; OwnedSingleIdx < OwnedItemList.Length; ++OwnedSingleIdx )
{
if( OwnedItemList[OwnedSingleIdx].DefaultItem.ClassName == DefaultItem.SingleClassName )
{
SingleDualAmmoDiff = OwnedItemList[OwnedSingleIdx].SpareAmmoCount - WeaponInfo.SpareAmmoCount;
SingleDualAmmoDiff = Max(0, SingleDualAmmoDiff); //If buying a dual, always have it be minimum starting ammo capacity
//If the new weapon has more when adding a dual, we're boosting it to the new full amount. Set UI info properly
if (WeaponInfo.SpareAmmoCount > OwnedItemList[OwnedSingleIdx].SpareAmmoCount)
{
OwnedItemList[OwnedSingleIdx].SpareAmmoCount = WeaponInfo.SpareAmmoCount;
}
//Otherwise we're going to maintain ammo and want the weapon info to match intended
else
{
//If rounding is causing problems, make sure our current ammo is never over the new max in the UI
WeaponInfo.SpareAmmoCount = Min(OwnedItemList[OwnedSingleIdx].SpareAmmoCount, WeaponInfo.MaxSpareAmmo);
}
WeaponInfo.ItemUpgradeLevel = OwnedItemList[OwnedSingleIdx].ItemUpgradeLevel;
break;
}
}
}
// allow perk to set spare ammo to max (uses different params than ModifySpareAmmoAmount)
// mostly just used for firebug
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 );
TraderItems.GetItemIndicesFromArche(ItemIndex, DefaultItem.ClassName);
if (!bDoNotBuy)
{
// Tell the server to buy the weapon using its trader archetype info
MyKFIM.ServerBuyWeapon(ItemIndex, WeaponInfo.ItemUpgradeLevel);
}
else
{
// Tell the server to add the weapon (without buying) using its trader archetype info
MyKFIM.ServerAddTransactionItem(ItemIndex, WeaponInfo.ItemUpgradeLevel);
AddBlocks(MyKFIM.GetWeaponBlocks(DefaultItem, WeaponInfo.ItemUpgradeLevel));
}
// if adding a dual, set its transaction ammo (given at trader close) to reflect the single it's replacing
if (bAddingDual)
{
AddTransactionAmmo(ItemIndex, SingleDualAmmoDiff /*+ WeaponInfo.MagazineCapacity/2*/, false);
RemoveWeaponFromOwnedItemList(, DefaultItem.SingleClassName, true);
}
return AddedWeaponIndex;
}
/** Removes item from owned list and sells it, if applicable */
function RemoveWeaponFromOwnedItemList( optional int OwnedListIdx = INDEX_NONE, optional name ClassName, optional bool bDoNotSell )
{
local SItemInformation ItemInfo;
local byte 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( !bDoNotSell )
{
// Sell the weapon from our inventory immediately
TraderItems.GetItemIndicesFromArche( ItemIndex, ItemInfo.DefaultItem.ClassName );
MyKFIM.ServerSellWeapon(ItemIndex);
}
else
{
// Remove the weapon from our inventory immediately (without selling)
AddBlocks(-MyKFIM.GetDisplayedBlocksRequiredFor(ItemInfo.DefaultItem));
TraderItems.GetItemIndicesFromArche( ItemIndex, ItemInfo.DefaultItem.ClassName );
MyKFIM.ServerRemoveTransactionItem( ItemIndex );
}
// If we try to sell a weapons secondary ammo slot
if( OwnedItemList[OwnedListIdx].bIsSecondaryAmmo )
{
OwnedItemList.Remove( OwnedListIdx, 1 );
if( OwnedListIdx - 1 >= 0 )
{
OwnedItemList.Remove( OwnedListIdx - 1, 1 );
}
}
// If the weapon we're selling uses secondary ammo, remove the secondary ammo listing also
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 );
}
//now selling duals as we buy them; together.
// add a single to owned items when removing a dual
//if( ItemInfo.DefaultItem.SingleClassName != '' )
if( ItemInfo.DefaultItem.SingleClassName == 'KFWeap_Pistol_9mm' )
{
// When removing a dual, always add a single to the owned list so that it shows up in the player inventory UI.
// If we don't own the single, then also buy it (add it to the transaction list).
if( TraderItems.GetItemIndicesFromArche( ItemIndex, ItemInfo.DefaultItem.SingleClassName) )
{
SingleOwnedIndex = AddWeaponToOwnedItemList( TraderItems.SaleItems[ItemIndex], true, ItemInfo.ItemUpgradeLevel);
// modify default single ammo based on how much ammo dual had when sold
// The now new single gun will spawn with default ammo. We need to correct that down
// to the correct amount. Account for differences in max spare ammo caused by perks.
AddTransactionAmmo( ItemIndex, ItemInfo.SpareAmmoCount - (ItemInfo.MaxSpareAmmo / 2.0) + ((ItemInfo.MaxSpareAmmo / 2.0) - OwnedItemList[SingleOwnedIndex].SpareAmmoCount), false );
// update the values in the trader UI
OwnedItemList[SingleOwnedIndex].SpareAmmoCount = ItemInfo.SpareAmmoCount;
}
}
if(MyGfxManager != none && MyGfxManager.TraderMenu != none)
{
MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList;
}
}
function MergeSingleIntoDual(SItemInformation ExistingDual, SItemInformation NewSingle)
{
ExistingDual.SpareAmmoCount = Min(ExistingDual.SpareAmmoCount + NewSingle.SpareAmmoCount, ExistingDual.MaxSpareAmmo);
ExistingDual.SecondaryAmmoCount = Min(ExistingDual.SecondaryAmmoCount + NewSingle.SecondaryAmmoCount, ExistingDual.MaxSecondaryAmmo);
}
function int AddItemByPriority( out SItemInformation WeaponInfo )
{
local byte i;
local byte WeaponGroup, WeaponPriority;
local byte BestIndex;
BestIndex = 0;
WeaponGroup = WeaponInfo.DefaultItem.InventoryGroup;
WeaponPriority = WeaponInfo.DefaultItem.GroupPriority;
for( i = 0; i < OwnedItemList.length; i++ )
{
//Receiving a single for a dual we already own (Ex: Weapon thrown at the player)
if (WeaponInfo.DefaultItem.DualClassName == OwnedItemList[i].DefaultItem.ClassName)
{
MergeSingleIntoDual(OwnedItemList[i], WeaponInfo);
return i;
}
// If the weapon belongs in the group prior to the current weapon, we've found the spot
if( WeaponGroup < OwnedItemList[i].DefaultItem.InventoryGroup )
{
BestIndex = i;
break;
}
else if( WeaponGroup == OwnedItemList[i].DefaultItem.InventoryGroup )
{
if( WeaponPriority > OwnedItemList[i].DefaultItem.GroupPriority )
{
// if the weapon is in the same group but has a higher priority, we've found the spot
BestIndex = i;
break;
}
else if( WeaponPriority == OwnedItemList[i].DefaultItem.GroupPriority &&
WeaponInfo.DefaultItem.AssociatedPerkClasses.Find(CurrentPerk.Class) != INDEX_NONE )
{
// if the weapons have the same priority give the slot to the on perk weapon
BestIndex = i;
break;
}
}
else
{
// Covers the case if this weapon is the only item in the last group
BestIndex = i + 1;
}
}
OwnedItemList.InsertItem( BestIndex, WeaponInfo );
// Add secondary ammo immediately after the main weapon
if( WeaponInfo.DefaultItem.WeaponDef.static.UsesSecondaryAmmo() )
{
WeaponInfo.bIsSecondaryAmmo = true;
WeaponInfo.SellPrice = 0;
OwnedItemList.InsertItem( BestIndex + 1, WeaponInfo );
}
if( MyGfxManager != none && MyGfxManager.TraderMenu != none )
{
MyGfxManager.TraderMenu.OwnedItemList = OwnedItemList;
}
return BestIndex;
}
function AddBlocks( int AddedBlocks )
{
TotalBlocks = Max( TotalBlocks + AddedBlocks, 0 );
}
function GetTraderItems()
{
TraderItems = KFGameReplicationInfo( WorldInfo.GRI ).TraderItems;
Initialize();
}
native private final function AddTransactionAmmo( byte ItemIndex, int Amount, bool bSecondaryAmmo );
DefaultProperties
{
//defaults
CostPerAutofillCycle=10
DoshBuffer=150
2021-09-02 21:46:08 +00:00
ArmorMagSize=25.0f;
2020-12-13 15:01:13 +00:00
}