first version
This commit is contained in:
parent
590270cf89
commit
7edd65b3e0
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "tools"]
|
||||||
|
path = tools
|
||||||
|
url = https://github.com/GenZmeY/KF2-BuildTools
|
66
CTI/Classes/AddItems.uc
Normal file
66
CTI/Classes/AddItems.uc
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
class AddItems extends Object
|
||||||
|
dependson(CTI)
|
||||||
|
config(CTI);
|
||||||
|
|
||||||
|
var private config Array<String> Item;
|
||||||
|
|
||||||
|
public static function InitConfig(int Version, int LatestVersion)
|
||||||
|
{
|
||||||
|
switch (Version)
|
||||||
|
{
|
||||||
|
case `NO_CONFIG:
|
||||||
|
ApplyDefault();
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LatestVersion != Version)
|
||||||
|
{
|
||||||
|
StaticSaveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function ApplyDefault()
|
||||||
|
{
|
||||||
|
default.Item.Length = 0;
|
||||||
|
default.Item.AddItem("SomePackage.SomeWeapon");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function Array<class<KFWeaponDefinition> > Load(E_LogLevel LogLevel)
|
||||||
|
{
|
||||||
|
local Array<class<KFWeaponDefinition> > ItemList;
|
||||||
|
local class<KFWeaponDefinition> ItemClass;
|
||||||
|
local String ItemRaw;
|
||||||
|
local int Line;
|
||||||
|
|
||||||
|
`Log_Info("Load Items to add:");
|
||||||
|
foreach default.Item(ItemRaw, Line)
|
||||||
|
{
|
||||||
|
ItemClass = class<KFWeaponDefinition>(DynamicLoadObject(ItemRaw, class'Class'));
|
||||||
|
if (ItemClass == None)
|
||||||
|
{
|
||||||
|
`Log_Warn("[" $ Line + 1 $ "]" @ "Can't load Item class:" @ ItemRaw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ItemList.AddItem(ItemClass);
|
||||||
|
`Log_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully:" @ ItemRaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemList.Length == default.Item.Length)
|
||||||
|
{
|
||||||
|
`Log_Info("Items to add list loaded successfully (" $ default.Item.Length @ "entries)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
`Log_Info("Items to add list: loaded" @ ItemList.Length @ "of" @ default.Item.Length @ "entries");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ItemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
247
CTI/Classes/CTI.uc
Normal file
247
CTI/Classes/CTI.uc
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
class CTI extends Info
|
||||||
|
config(CTI);
|
||||||
|
|
||||||
|
const LatestVersion = 1;
|
||||||
|
|
||||||
|
const CfgRemoveItems = class'RemoveItems';
|
||||||
|
const CfgAddItems = class'AddItems';
|
||||||
|
const Helper = class'Helper';
|
||||||
|
|
||||||
|
var private config int Version;
|
||||||
|
var private config E_LogLevel LogLevel;
|
||||||
|
var private config bool bPreloadContent;
|
||||||
|
var private config bool bForcePreloadContent;
|
||||||
|
var private config bool UnlockDLC;
|
||||||
|
|
||||||
|
var private KFGameInfo KFGI;
|
||||||
|
var private KFGameReplicationInfo KFGRI;
|
||||||
|
|
||||||
|
var private Array<class<KFWeaponDefinition> > RemoveItems;
|
||||||
|
var private Array<class<KFWeaponDefinition> > AddItems;
|
||||||
|
|
||||||
|
var private Array<CTI_RepInfo> RepInfos;
|
||||||
|
|
||||||
|
var private bool ReadyToSync;
|
||||||
|
|
||||||
|
public simulated function bool SafeDestroy()
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
return (bPendingDelete || bDeleteMe || Destroy());
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PreBeginPlay()
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
`Log_Debug("PreBeginPlay readyToSync" @ ReadyToSync);
|
||||||
|
|
||||||
|
if (WorldInfo.NetMode == NM_Client)
|
||||||
|
{
|
||||||
|
`Log_Fatal("NetMode == NM_Client, Destroy...");
|
||||||
|
SafeDestroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Super.PreBeginPlay();
|
||||||
|
|
||||||
|
PreInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PostBeginPlay()
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
if (bPendingDelete || bDeleteMe) return;
|
||||||
|
|
||||||
|
Super.PostBeginPlay();
|
||||||
|
|
||||||
|
PostInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function PreInit()
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
if (Version == `NO_CONFIG)
|
||||||
|
{
|
||||||
|
LogLevel = LL_Info;
|
||||||
|
bPreloadContent = true;
|
||||||
|
bForcePreloadContent = true;
|
||||||
|
UnlockDLC = false;
|
||||||
|
SaveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
CfgRemoveItems.static.InitConfig(Version, LatestVersion);
|
||||||
|
CfgAddItems.static.InitConfig(Version, LatestVersion);
|
||||||
|
|
||||||
|
switch (Version)
|
||||||
|
{
|
||||||
|
case `NO_CONFIG:
|
||||||
|
`Log_Info("Config created");
|
||||||
|
|
||||||
|
case MaxInt:
|
||||||
|
`Log_Info("Config updated to version"@LatestVersion);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LatestVersion:
|
||||||
|
`Log_Info("Config is up-to-date");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
`Log_Warn("The config version is higher than the current version (are you using an old mutator?)");
|
||||||
|
`Log_Warn("Config version is" @ Version @ "but current version is" @ LatestVersion);
|
||||||
|
`Log_Warn("The config version will be changed to" @ LatestVersion);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LatestVersion != Version)
|
||||||
|
{
|
||||||
|
Version = LatestVersion;
|
||||||
|
SaveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LogLevel == LL_WrongLevel)
|
||||||
|
{
|
||||||
|
LogLevel = LL_Info;
|
||||||
|
`Log_Warn("Wrong 'LogLevel', return to default value");
|
||||||
|
SaveConfig();
|
||||||
|
}
|
||||||
|
`Log_Base("LogLevel:" @ LogLevel);
|
||||||
|
|
||||||
|
RemoveItems = CfgRemoveItems.static.Load(LogLevel);
|
||||||
|
AddItems = CfgAddItems.static.Load(LogLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function PostInit()
|
||||||
|
{
|
||||||
|
local CTI_RepInfo RepLink;
|
||||||
|
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
if (WorldInfo == None || WorldInfo.Game == None)
|
||||||
|
{
|
||||||
|
SetTimer(1.0f, false, nameof(PostInit));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KFGI = KFGameInfo(WorldInfo.Game);
|
||||||
|
if (KFGI == None)
|
||||||
|
{
|
||||||
|
`Log_Fatal("Incompatible gamemode:" @ WorldInfo.Game);
|
||||||
|
SafeDestroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UnlockDLC && KFGI.KFGFxManagerClass != class'CTI_GFxMoviePlayer_Manager')
|
||||||
|
{
|
||||||
|
KFGI.KFGFxManagerClass = class'CTI_GFxMoviePlayer_Manager';
|
||||||
|
`Log_Info("DLC unlocked");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KFGI.GameReplicationInfo == None)
|
||||||
|
{
|
||||||
|
SetTimer(1.0f, false, nameof(PostInit));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KFGRI = KFGameReplicationInfo(KFGI.GameReplicationInfo);
|
||||||
|
if (KFGRI == None)
|
||||||
|
{
|
||||||
|
`Log_Fatal("Incompatible Replication info:" @ KFGI.GameReplicationInfo);
|
||||||
|
SafeDestroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper.static.ModifyTrader(KFGRI, RemoveItems, AddItems, CfgRemoveItems.default.bAll);
|
||||||
|
|
||||||
|
if (bPreloadContent)
|
||||||
|
{
|
||||||
|
Helper.static.PreloadContent(AddItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadyToSync = true;
|
||||||
|
|
||||||
|
foreach RepInfos(RepLink)
|
||||||
|
{
|
||||||
|
if (RepLink.PendingSync)
|
||||||
|
{
|
||||||
|
RepLink.ServerSync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function NotifyLogin(Controller C)
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
CreateRepLink(C);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function NotifyLogout(Controller C)
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
DestroyRepLink(C);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bool CreateRepLink(Controller C)
|
||||||
|
{
|
||||||
|
local CTI_RepInfo RepLink;
|
||||||
|
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
if (C == None) return false;
|
||||||
|
|
||||||
|
RepLink = Spawn(class'CTI_RepInfo', C);
|
||||||
|
|
||||||
|
if (RepLink == None) return false;
|
||||||
|
|
||||||
|
RepLink.PrepareSync(
|
||||||
|
Self,
|
||||||
|
LogLevel,
|
||||||
|
RemoveItems,
|
||||||
|
AddItems,
|
||||||
|
CfgRemoveItems.default.bAll,
|
||||||
|
bPreloadContent,
|
||||||
|
bForcePreloadContent);
|
||||||
|
|
||||||
|
RepInfos.AddItem(RepLink);
|
||||||
|
|
||||||
|
if (ReadyToSync)
|
||||||
|
{
|
||||||
|
RepLink.ServerSync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RepLink.PendingSync = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bool DestroyRepLink(Controller C)
|
||||||
|
{
|
||||||
|
local CTI_RepInfo RepLink;
|
||||||
|
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
if (C == None) return false;
|
||||||
|
|
||||||
|
foreach RepInfos(RepLink)
|
||||||
|
{
|
||||||
|
if (RepLink.Owner == C)
|
||||||
|
{
|
||||||
|
RepLink.SafeDestroy();
|
||||||
|
RepInfos.RemoveItem(RepLink);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
ReadyToSync = false
|
||||||
|
}
|
4
CTI/Classes/CTI.upkg
Normal file
4
CTI/Classes/CTI.upkg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[Flags]
|
||||||
|
AllowDownload=True
|
||||||
|
ClientOptional=False
|
||||||
|
ServerSideOnly=False
|
62
CTI/Classes/CTIMut.uc
Normal file
62
CTI/Classes/CTIMut.uc
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
class CTIMut extends KFMutator;
|
||||||
|
|
||||||
|
var private CTI CTI;
|
||||||
|
|
||||||
|
public simulated function bool SafeDestroy()
|
||||||
|
{
|
||||||
|
return (bPendingDelete || bDeleteMe || Destroy());
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PreBeginPlay()
|
||||||
|
{
|
||||||
|
Super.PreBeginPlay();
|
||||||
|
|
||||||
|
if (WorldInfo.NetMode == NM_Client) return;
|
||||||
|
|
||||||
|
foreach WorldInfo.DynamicActors(class'CTI', CTI)
|
||||||
|
{
|
||||||
|
`Log_Base("Found 'CTI'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CTI == None)
|
||||||
|
{
|
||||||
|
`Log_Base("Spawn 'CTI'");
|
||||||
|
CTI = WorldInfo.Spawn(class'CTI');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CTI == None)
|
||||||
|
{
|
||||||
|
`Log_Base("Can't Spawn 'CTI', Destroy...");
|
||||||
|
SafeDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function AddMutator(Mutator Mut)
|
||||||
|
{
|
||||||
|
if (Mut == Self) return;
|
||||||
|
|
||||||
|
if (Mut.Class == Class)
|
||||||
|
Mut.Destroy();
|
||||||
|
else
|
||||||
|
Super.AddMutator(Mut);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function NotifyLogin(Controller C)
|
||||||
|
{
|
||||||
|
Super.NotifyLogin(C);
|
||||||
|
|
||||||
|
CTI.NotifyLogin(C);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function NotifyLogout(Controller C)
|
||||||
|
{
|
||||||
|
Super.NotifyLogout(C);
|
||||||
|
|
||||||
|
CTI.NotifyLogout(C);
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultProperties
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
8
CTI/Classes/CTI_GFxMenu_Trader.uc
Normal file
8
CTI/Classes/CTI_GFxMenu_Trader.uc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
class CTI_GFxMenu_Trader extends KFGFxMenu_Trader
|
||||||
|
dependsOn(CTI_GFxTraderContainer_Store);
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
SubWidgetBindings.Remove((WidgetName="shopContainer",WidgetClass=class'KFGFxTraderContainer_Store'))
|
||||||
|
SubWidgetBindings.Add((WidgetName="shopContainer",WidgetClass=class'CTI_GFxTraderContainer_Store'))
|
||||||
|
}
|
8
CTI/Classes/CTI_GFxMoviePlayer_Manager.uc
Normal file
8
CTI/Classes/CTI_GFxMoviePlayer_Manager.uc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
class CTI_GFxMoviePlayer_Manager 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'))
|
||||||
|
}
|
20
CTI/Classes/CTI_GFxTraderContainer_Store.uc
Normal file
20
CTI/Classes/CTI_GFxTraderContainer_Store.uc
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
class CTI_GFxTraderContainer_Store extends KFGFxTraderContainer_Store;
|
||||||
|
|
||||||
|
function bool IsItemFiltered(STraderItem Item, optional bool bDebug)
|
||||||
|
{
|
||||||
|
if (KFPC.GetPurchaseHelper().IsInOwnedItemList(Item.ClassName))
|
||||||
|
return true;
|
||||||
|
if (KFPC.GetPurchaseHelper().IsInOwnedItemList(Item.DualClassName))
|
||||||
|
return true;
|
||||||
|
if (!KFPC.GetPurchaseHelper().IsSellable(Item))
|
||||||
|
return true;
|
||||||
|
if (Item.WeaponDef.default.PlatformRestriction != PR_All && class'KFUnlockManager'.static.IsPlatformRestricted(Item.WeaponDef.default.PlatformRestriction))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
309
CTI/Classes/CTI_RepInfo.uc
Normal file
309
CTI/Classes/CTI_RepInfo.uc
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
class CTI_RepInfo extends ReplicationInfo;
|
||||||
|
|
||||||
|
const Helper = class'Helper';
|
||||||
|
|
||||||
|
var public bool PendingSync;
|
||||||
|
|
||||||
|
var private CTI CTI;
|
||||||
|
var private E_LogLevel LogLevel;
|
||||||
|
var private Array<class<KFWeaponDefinition> > RemoveItems;
|
||||||
|
var private Array<class<KFWeaponDefinition> > AddItems;
|
||||||
|
var private bool ReplaceMode;
|
||||||
|
var private bool PreloadContent;
|
||||||
|
var private bool ForcePreloadContent;
|
||||||
|
|
||||||
|
var private int Recieved;
|
||||||
|
var private int SyncSize;
|
||||||
|
|
||||||
|
var private KFGFxWidget_PartyInGame PartyInGameWidget;
|
||||||
|
var private GFxObject Notification;
|
||||||
|
|
||||||
|
replication
|
||||||
|
{
|
||||||
|
if (bNetInitial && Role == ROLE_Authority)
|
||||||
|
LogLevel, ReplaceMode, PreloadContent, ForcePreloadContent, SyncSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public simulated function bool SafeDestroy()
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
return (bPendingDelete || bDeleteMe || Destroy());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function PrepareSync(
|
||||||
|
CTI _CTI,
|
||||||
|
E_LogLevel _LogLevel,
|
||||||
|
Array<class<KFWeaponDefinition> > _RemoveItems,
|
||||||
|
Array<class<KFWeaponDefinition> > _AddItems,
|
||||||
|
bool _ReplaceMode,
|
||||||
|
bool _PreloadContent,
|
||||||
|
bool _ForcePreloadContent)
|
||||||
|
{
|
||||||
|
CTI = _CTI;
|
||||||
|
LogLevel = _LogLevel;
|
||||||
|
RemoveItems = _RemoveItems;
|
||||||
|
AddItems = _AddItems;
|
||||||
|
ReplaceMode = _ReplaceMode;
|
||||||
|
PreloadContent = _PreloadContent;
|
||||||
|
ForcePreloadContent = _ForcePreloadContent;
|
||||||
|
SyncSize = RemoveItems.Length + AddItems.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private simulated function PlayerController GetPlayerController()
|
||||||
|
{
|
||||||
|
local PlayerController PC;
|
||||||
|
|
||||||
|
PC = PlayerController(Owner);
|
||||||
|
|
||||||
|
if (PC == None && ROLE < ROLE_Authority)
|
||||||
|
{
|
||||||
|
PC = GetALocalPlayerController();
|
||||||
|
}
|
||||||
|
|
||||||
|
return PC;
|
||||||
|
}
|
||||||
|
|
||||||
|
private simulated function SetPartyInGameWidget()
|
||||||
|
{
|
||||||
|
local KFPlayerController KFPC;
|
||||||
|
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
KFPC = KFPlayerController(GetPlayerController());
|
||||||
|
if (KFPC == None) return;
|
||||||
|
if (KFPC.MyGFxManager == None) return;
|
||||||
|
if (KFPC.MyGFxManager.PartyWidget == None) return;
|
||||||
|
|
||||||
|
PartyInGameWidget = KFGFxWidget_PartyInGame(KFPC.MyGFxManager.PartyWidget);
|
||||||
|
Notification = PartyInGameWidget.Notification;
|
||||||
|
}
|
||||||
|
|
||||||
|
private simulated function bool CheckPartyInGameWidget()
|
||||||
|
{
|
||||||
|
if (PartyInGameWidget == None)
|
||||||
|
{
|
||||||
|
SetPartyInGameWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (PartyInGameWidget != None);
|
||||||
|
}
|
||||||
|
|
||||||
|
private simulated function UpdateNotification(String Title, String Downloading, String Remainig, int Percent)
|
||||||
|
{
|
||||||
|
if (Notification != None)
|
||||||
|
{
|
||||||
|
Notification.SetString("itemName", Title);
|
||||||
|
Notification.SetFloat("percent", Percent);
|
||||||
|
Notification.SetInt("queue", 0);
|
||||||
|
Notification.SetString("downLoading", Downloading);
|
||||||
|
Notification.SetString("remaining", Remainig);
|
||||||
|
Notification.SetObject("notificationInfo", Notification);
|
||||||
|
Notification.SetVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private reliable client function ClientSync(class<KFWeaponDefinition> WeapDef, optional bool Remove = false)
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
if (WeapDef == None)
|
||||||
|
{
|
||||||
|
`Log_Fatal("WeapDef is:" @ WeapDef);
|
||||||
|
SafeDestroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckPartyInGameWidget())
|
||||||
|
{
|
||||||
|
PartyInGameWidget.SetReadyButtonVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Remove)
|
||||||
|
{
|
||||||
|
RemoveItems.AddItem(WeapDef);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddItems.AddItem(WeapDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
Recieved = RemoveItems.Length + AddItems.Length;
|
||||||
|
if (CheckPartyInGameWidget())
|
||||||
|
{
|
||||||
|
UpdateNotification(
|
||||||
|
"Sync items, please wait...",
|
||||||
|
Remove ? "-" : "+" @ Repl(String(WeapDef), "KFWeapDef_", ""),
|
||||||
|
Recieved @ "/" @ SyncSize,
|
||||||
|
(float(Recieved) / float(SyncSize)) * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Recieved == SyncSize && (PreloadContent || ForcePreloadContent))
|
||||||
|
{
|
||||||
|
if (CheckPartyInGameWidget())
|
||||||
|
{
|
||||||
|
UpdateNotification(
|
||||||
|
"Preload Content, please wait...",
|
||||||
|
"Game isn't frozen",
|
||||||
|
"Don't panic",
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ServerSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private simulated reliable client function SyncFinished()
|
||||||
|
{
|
||||||
|
local KFGameReplicationInfo KFGRI;
|
||||||
|
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
if (WorldInfo == None || WorldInfo.GRI == None)
|
||||||
|
{
|
||||||
|
SetTimer(1.0f, false, nameof(SyncFinished));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KFGRI = KFGameReplicationInfo(WorldInfo.GRI);
|
||||||
|
if (KFGRI == None)
|
||||||
|
{
|
||||||
|
`Log_Fatal("Incompatible Replication info:" @ WorldInfo.GRI);
|
||||||
|
SafeDestroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper.static.ModifyTrader(KFGRI, RemoveItems, AddItems, ReplaceMode);
|
||||||
|
|
||||||
|
if (PreloadContent)
|
||||||
|
{
|
||||||
|
Helper.static.PreloadContent(AddItems);
|
||||||
|
}
|
||||||
|
if (ForcePreloadContent)
|
||||||
|
{
|
||||||
|
PreloadContentWorkaround();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CheckPartyInGameWidget())
|
||||||
|
{
|
||||||
|
Notification.SetVisible(false);
|
||||||
|
PartyInGameWidget.SetReadyButtonVisibility(true);
|
||||||
|
PartyInGameWidget.UpdateReadyButtonText();
|
||||||
|
PartyInGameWidget.UpdateReadyButtonVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public reliable server function ServerSync()
|
||||||
|
{
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
PendingSync = false;
|
||||||
|
|
||||||
|
if (bPendingDelete || bDeleteMe) return;
|
||||||
|
|
||||||
|
if (SyncSize <= Recieved || WorldInfo.NetMode == NM_StandAlone)
|
||||||
|
{
|
||||||
|
SyncFinished();
|
||||||
|
if (!CTI.DestroyRepLink(Controller(Owner)))
|
||||||
|
{
|
||||||
|
SafeDestroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Recieved < RemoveItems.Length)
|
||||||
|
{
|
||||||
|
ClientSync(RemoveItems[Recieved++], true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClientSync(AddItems[Recieved++ - RemoveItems.Length], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private simulated function PreloadContentWorkaround()
|
||||||
|
{
|
||||||
|
local PlayerController PC;
|
||||||
|
local Pawn P;
|
||||||
|
local KFInventoryManager KFIM;
|
||||||
|
local class<Weapon> CW;
|
||||||
|
local Weapon W;
|
||||||
|
local int Index;
|
||||||
|
local DroppedPickup DP;
|
||||||
|
local float Time;
|
||||||
|
|
||||||
|
`Log_Trace(`Location);
|
||||||
|
|
||||||
|
PC = GetPlayerController();
|
||||||
|
|
||||||
|
if (PC == None)
|
||||||
|
{
|
||||||
|
SetTimer(0.1f, false, nameof(PreloadContentWorkaround));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
P = PC.Pawn;
|
||||||
|
if (P == None)
|
||||||
|
{
|
||||||
|
SetTimer(0.1f, false, nameof(PreloadContentWorkaround));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KFIM = KFInventoryManager(P.InvManager);
|
||||||
|
if (KFIM == None)
|
||||||
|
{
|
||||||
|
SetTimer(0.1f, false, nameof(PreloadContentWorkaround));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KFIM.bInfiniteWeight = true;
|
||||||
|
Time = WorldInfo.TimeSeconds - 1.0f;
|
||||||
|
|
||||||
|
for (Index = 0; Index < AddItems.Length; Index++)
|
||||||
|
{
|
||||||
|
CW = class<Weapon> (DynamicLoadObject(AddItems[Index].default.WeaponClassPath, class'Class'));
|
||||||
|
if (CW != None && Weapon(P.FindInventoryType(CW)) == None)
|
||||||
|
{
|
||||||
|
P.CreateInventory(CW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach KFIM.InventoryActors(class'Weapon', W)
|
||||||
|
{
|
||||||
|
if (W != None)
|
||||||
|
{
|
||||||
|
KFIM.PendingWeapon = W;
|
||||||
|
KFIM.ChangedWeapon();
|
||||||
|
if (W.CanThrow())
|
||||||
|
{
|
||||||
|
P.TossInventory(W);
|
||||||
|
W.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach WorldInfo.DynamicActors(class'DroppedPickup', DP)
|
||||||
|
{
|
||||||
|
if (DP.Instigator == P && DP.CreationTime > Time)
|
||||||
|
{
|
||||||
|
DP.Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KFIM.bInfiniteWeight = false;
|
||||||
|
|
||||||
|
`Log_Info("Force Preload Finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
bAlwaysRelevant = false
|
||||||
|
bOnlyRelevantToOwner = true
|
||||||
|
bSkipActorPropertyReplication = false
|
||||||
|
|
||||||
|
PendingSync = false
|
||||||
|
Recieved = 0
|
||||||
|
}
|
73
CTI/Classes/Helper.uc
Normal file
73
CTI/Classes/Helper.uc
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
class Helper extends Object;
|
||||||
|
|
||||||
|
private delegate int ByPrice(class<KFWeaponDefinition> A, class<KFWeaponDefinition> B)
|
||||||
|
{
|
||||||
|
return A.default.BuyPrice > B.default.BuyPrice ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static simulated function ModifyTrader(
|
||||||
|
KFGameReplicationInfo KFGRI,
|
||||||
|
Array<class<KFWeaponDefinition> > RemoveItems,
|
||||||
|
Array<class<KFWeaponDefinition> > AddItems,
|
||||||
|
bool ReplaceMode)
|
||||||
|
{
|
||||||
|
local KFGFxObject_TraderItems TraderItems;
|
||||||
|
local STraderItem Item;
|
||||||
|
local class<KFWeaponDefinition> WeapDef;
|
||||||
|
local Array<class<KFWeaponDefinition> > WeapDefs;
|
||||||
|
local int Index;
|
||||||
|
local int MaxItemID;
|
||||||
|
|
||||||
|
if (KFGRI == None) return;
|
||||||
|
|
||||||
|
TraderItems = KFGFxObject_TraderItems(DynamicLoadObject(KFGRI.TraderItemsPath, class'KFGFxObject_TraderItems'));
|
||||||
|
|
||||||
|
if (!ReplaceMode)
|
||||||
|
{
|
||||||
|
foreach TraderItems.SaleItems(Item)
|
||||||
|
{
|
||||||
|
if (Item.WeaponDef != None && RemoveItems.Find(Item.WeaponDef) == INDEX_NONE)
|
||||||
|
{
|
||||||
|
WeapDefs.AddItem(Item.WeaponDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Index = 0; Index < AddItems.Length; Index++)
|
||||||
|
WeapDefs.AddItem(AddItems[Index]);
|
||||||
|
|
||||||
|
WeapDefs.Sort(ByPrice);
|
||||||
|
|
||||||
|
TraderItems.SaleItems.Length = 0;
|
||||||
|
MaxItemID = 0;
|
||||||
|
foreach WeapDefs(WeapDef)
|
||||||
|
{
|
||||||
|
Item.WeaponDef = WeapDef;
|
||||||
|
Item.ItemID = ++MaxItemID;
|
||||||
|
TraderItems.SaleItems.AddItem(Item);
|
||||||
|
}
|
||||||
|
|
||||||
|
TraderItems.SetItemsInfo(TraderItems.SaleItems);
|
||||||
|
|
||||||
|
KFGRI.TraderItems = TraderItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function PreloadContent(Array<class<KFWeaponDefinition> > WeapDefs)
|
||||||
|
{
|
||||||
|
local class<KFWeapon> KFW;
|
||||||
|
local int Index;
|
||||||
|
|
||||||
|
for (Index = 0; Index < WeapDefs.Length; Index++)
|
||||||
|
{
|
||||||
|
KFW = class<KFWeapon> (DynamicLoadObject(WeapDefs[Index].default.WeaponClassPath, class'Class'));
|
||||||
|
if (KFW != None)
|
||||||
|
{
|
||||||
|
class'KFWeapon'.static.TriggerAsyncContentLoad(KFW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
75
CTI/Classes/RemoveItems.uc
Normal file
75
CTI/Classes/RemoveItems.uc
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
class RemoveItems extends Object
|
||||||
|
dependson(CTI)
|
||||||
|
config(CTI);
|
||||||
|
|
||||||
|
var public config bool bAll;
|
||||||
|
var private config Array<String> Item;
|
||||||
|
|
||||||
|
public static function InitConfig(int Version, int LatestVersion)
|
||||||
|
{
|
||||||
|
switch (Version)
|
||||||
|
{
|
||||||
|
case `NO_CONFIG:
|
||||||
|
ApplyDefault();
|
||||||
|
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LatestVersion != Version)
|
||||||
|
{
|
||||||
|
StaticSaveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function ApplyDefault()
|
||||||
|
{
|
||||||
|
default.bAll = false;
|
||||||
|
default.Item.Length = 0;
|
||||||
|
default.Item.AddItem("KFGame.KFWeapDef_9mmDual");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function Array<class<KFWeaponDefinition> > Load(E_LogLevel LogLevel)
|
||||||
|
{
|
||||||
|
local Array<class<KFWeaponDefinition> > ItemList;
|
||||||
|
local class<KFWeaponDefinition> ItemClass;
|
||||||
|
local String ItemRaw;
|
||||||
|
local int Line;
|
||||||
|
|
||||||
|
`Log_Info("Load items to remove:");
|
||||||
|
if (default.bAll)
|
||||||
|
{
|
||||||
|
`Log_Info("Remove all default items");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach default.Item(ItemRaw, Line)
|
||||||
|
{
|
||||||
|
ItemClass = class<KFWeaponDefinition>(DynamicLoadObject(ItemRaw, class'Class'));
|
||||||
|
if (ItemClass == None)
|
||||||
|
{
|
||||||
|
`Log_Warn("[" $ Line + 1 $ "]" @ "Can't load item class:" @ ItemRaw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ItemList.AddItem(ItemClass);
|
||||||
|
`Log_Debug("[" $ Line + 1 $ "]" @ "Loaded successfully:" @ ItemRaw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemList.Length == default.Item.Length)
|
||||||
|
{
|
||||||
|
`Log_Info("Items to remove list loaded successfully (" $ default.Item.Length @ "entries)");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
`Log_Info("Items to remove list: loaded" @ ItemList.Length @ "of" @ default.Item.Length @ "entries");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ItemList;
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
19
CTI/Classes/_Logger.uc
Normal file
19
CTI/Classes/_Logger.uc
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
class _Logger extends Object
|
||||||
|
abstract;
|
||||||
|
|
||||||
|
enum E_LogLevel
|
||||||
|
{
|
||||||
|
LL_WrongLevel,
|
||||||
|
LL_Fatal,
|
||||||
|
LL_Error,
|
||||||
|
LL_Warning,
|
||||||
|
LL_Info,
|
||||||
|
LL_Debug,
|
||||||
|
LL_Trace,
|
||||||
|
LL_All
|
||||||
|
};
|
||||||
|
|
||||||
|
defaultproperties
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
2
CTI/Constants.uci
Normal file
2
CTI/Constants.uci
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Constants
|
||||||
|
`define NO_CONFIG 0
|
3
CTI/Globals.uci
Normal file
3
CTI/Globals.uci
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Imports
|
||||||
|
`include(Logger.uci)
|
||||||
|
`include(Constants.uci)
|
11
CTI/Logger.uci
Normal file
11
CTI/Logger.uci
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// Logger
|
||||||
|
`define Log_Tag 'CTI'
|
||||||
|
|
||||||
|
`define Log_Base(msg, cond) `log(`msg `if(`cond), `cond`{endif}, `Log_Tag)
|
||||||
|
|
||||||
|
`define Log_Fatal(msg) `log("FATAL:" @ `msg, (LogLevel >= LL_Fatal), `Log_Tag)
|
||||||
|
`define Log_Error(msg) `log("ERROR:" @ `msg, (LogLevel >= LL_Error), `Log_Tag)
|
||||||
|
`define Log_Warn(msg) `log("WARN:" @ `msg, (LogLevel >= LL_Warning), `Log_Tag)
|
||||||
|
`define Log_Info(msg) `log("INFO:" @ `msg, (LogLevel >= LL_Info), `Log_Tag)
|
||||||
|
`define Log_Debug(msg) `log("DEBUG:" @ `msg, (LogLevel >= LL_Debug), `Log_Tag)
|
||||||
|
`define Log_Trace(msg) `log("TRACE:" @ `msg, (LogLevel >= LL_Trace), `Log_Tag)
|
9
PublicationContent/description.txt
Normal file
9
PublicationContent/description.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
[h1]Custom Trader Inventory[/h1]
|
||||||
|
|
||||||
|
[h1]Description[/h1]
|
||||||
|
description will come later...
|
||||||
|
|
||||||
|
[b]Mutator:[/b] CTI.CTIMut
|
||||||
|
|
||||||
|
[h1]Sources[/h1]
|
||||||
|
[url=https://github.com/GenZmeY/KF2-CustomTraderInventory]https://github.com/GenZmeY/KF2-CustomTraderInventory[/url]
|
BIN
PublicationContent/preview.png
Normal file
BIN
PublicationContent/preview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
1
PublicationContent/tags.txt
Normal file
1
PublicationContent/tags.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Mutators
|
1
PublicationContent/title.txt
Normal file
1
PublicationContent/title.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Custom Trader Inventory
|
52
builder.cfg
Normal file
52
builder.cfg
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
### Build parameters ###
|
||||||
|
|
||||||
|
# If True - compresses the mutator when compiling
|
||||||
|
# Scripts will be stored in binary form
|
||||||
|
# (reduces the size of the output file)
|
||||||
|
StripSource="True"
|
||||||
|
|
||||||
|
# Mutators to be compiled
|
||||||
|
# Specify them with a space as a separator,
|
||||||
|
# Mutators will be compiled in the specified order
|
||||||
|
PackageBuildOrder="CTI"
|
||||||
|
|
||||||
|
|
||||||
|
### Steam Workshop upload parameters ###
|
||||||
|
|
||||||
|
# Mutators that will be uploaded to the workshop
|
||||||
|
# Specify them with a space as a separator,
|
||||||
|
# The order doesn't matter
|
||||||
|
PackageUpload="CTI"
|
||||||
|
|
||||||
|
|
||||||
|
### Test parameters ###
|
||||||
|
|
||||||
|
# Map:
|
||||||
|
Map="KF-Nuked"
|
||||||
|
|
||||||
|
# Game:
|
||||||
|
# Survival: KFGameContent.KFGameInfo_Survival
|
||||||
|
# WeeklyOutbreak: KFGameContent.KFGameInfo_WeeklySurvival
|
||||||
|
# Endless: KFGameContent.KFGameInfo_Endless
|
||||||
|
# Objective: KFGameContent.KFGameInfo_Objective
|
||||||
|
# Versus: KFGameContent.KFGameInfo_VersusSurvival
|
||||||
|
Game="KFGameContent.KFGameInfo_Endless"
|
||||||
|
|
||||||
|
# Difficulty:
|
||||||
|
# Normal: 0
|
||||||
|
# Hard: 1
|
||||||
|
# Suicide: 2
|
||||||
|
# Hell: 3
|
||||||
|
Difficulty="0"
|
||||||
|
|
||||||
|
# GameLength:
|
||||||
|
# 4 waves: 0
|
||||||
|
# 7 waves: 1
|
||||||
|
# 10 waves: 2
|
||||||
|
GameLength="0"
|
||||||
|
|
||||||
|
# Mutators
|
||||||
|
Mutators="CTI.CTIMut"
|
||||||
|
|
||||||
|
# Additional parameters
|
||||||
|
Args=""
|
1
tools
Submodule
1
tools
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 2f173aad7a6f4578574764801136a0d86e830653
|
Loading…
x
Reference in New Issue
Block a user