2017-10-20 02:00:49 +00:00
|
|
|
Class ExtPlayerReplicationInfo extends KFPlayerReplicationInfo;
|
|
|
|
|
|
|
|
struct FCustomCharEntry
|
|
|
|
{
|
|
|
|
var bool bLock;
|
|
|
|
var KFCharacterInfo_Human Char;
|
|
|
|
var ObjectReferencer Ref;
|
|
|
|
};
|
|
|
|
struct FMyCustomChar // Now without constant.
|
|
|
|
{
|
2020-11-28 19:53:57 +00:00
|
|
|
var int CharacterIndex,HeadMeshIndex,HeadSkinIndex,BodyMeshIndex,BodySkinIndex,AttachmentMeshIndices[`MAX_COSMETIC_ATTACHMENTS],AttachmentSkinIndices[`MAX_COSMETIC_ATTACHMENTS];
|
|
|
|
|
|
|
|
structdefaultproperties
|
|
|
|
{
|
|
|
|
AttachmentMeshIndices[0]=`CLEARED_ATTACHMENT_INDEX
|
|
|
|
AttachmentMeshIndices[1]=`CLEARED_ATTACHMENT_INDEX
|
|
|
|
AttachmentMeshIndices[2]=`CLEARED_ATTACHMENT_INDEX
|
|
|
|
}
|
2017-10-20 02:00:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// For custom trader inventory.
|
|
|
|
struct FCustomTraderItem
|
|
|
|
{
|
|
|
|
var class<KFWeaponDefinition> WeaponDef;
|
|
|
|
var class<KFWeapon> WeaponClass;
|
|
|
|
};
|
|
|
|
|
|
|
|
var bool bIsMuted,bInitialPT,bIsDev,bHiddenUser,bClientUseCustom,bClientFirstChar,bClientCharListDone,bClientInitChars;
|
|
|
|
|
|
|
|
var int RespawnCounter;
|
|
|
|
var byte AdminType;
|
|
|
|
var class<Ext_PerkBase> ECurrentPerk;
|
2017-10-20 07:02:53 +00:00
|
|
|
var Ext_PerkBase FCurrentPerk;
|
2017-10-20 02:00:49 +00:00
|
|
|
var int ECurrentPerkLevel,ECurrentPerkPrestige;
|
|
|
|
var ExtPerkManager PerkManager;
|
|
|
|
/* AdminTypes:
|
|
|
|
0 - Super Admin (server owner)
|
|
|
|
1 - Admin
|
|
|
|
2 - Moderator
|
|
|
|
3 - Trusted member
|
|
|
|
4 - VIP
|
|
|
|
*/
|
|
|
|
|
|
|
|
var string TaggedPlayerName;
|
|
|
|
var repnotify string NameTag;
|
|
|
|
var repnotify byte RepLevelProgress;
|
|
|
|
var transient color HUDPerkColor;
|
|
|
|
var byte FixedData;
|
|
|
|
var int RepPlayTime,RepKills,RepEXP;
|
|
|
|
|
|
|
|
// Custom character stuff.
|
|
|
|
var array<FCustomCharEntry> CustomCharList;
|
|
|
|
var repnotify FMyCustomChar CustomCharacter;
|
|
|
|
var transient array<ExtCharDataInfo> SaveDataObjects;
|
|
|
|
var transient ExtPlayerReplicationInfo LocalOwnerPRI; // Local playercontroller owner PRI
|
|
|
|
|
|
|
|
// Custom trader inventory
|
|
|
|
var KFGFxObject_TraderItems CustomList;
|
|
|
|
var array<FCustomTraderItem> CustomItems;
|
|
|
|
|
|
|
|
// Supplier data:
|
|
|
|
var transient struct FSupplierData
|
|
|
|
{
|
|
|
|
var transient Pawn SuppliedPawn;
|
|
|
|
var transient float NextSupplyTimer;
|
|
|
|
} SupplierLimit;
|
|
|
|
var repnotify class<Ext_TraitSupply> HasSupplier;
|
|
|
|
|
|
|
|
replication
|
|
|
|
{
|
|
|
|
// Things the server should send to the client.
|
2020-11-28 20:04:55 +00:00
|
|
|
if (true)
|
2017-10-20 02:00:49 +00:00
|
|
|
RespawnCounter,AdminType,ECurrentPerk,ECurrentPerkLevel,ECurrentPerkPrestige,RepKills,RepEXP,RepLevelProgress,bIsDev,NameTag,FixedData,bHiddenUser,CustomCharacter,HasSupplier;
|
|
|
|
if (bNetInitial || bInitialPT)
|
|
|
|
RepPlayTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function PostBeginPlay()
|
|
|
|
{
|
|
|
|
local PlayerController PC;
|
|
|
|
|
|
|
|
Super.PostBeginPlay();
|
|
|
|
SetTimer(1,true,'TickPT');
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode!=NM_DedicatedServer)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
HUDPerkColor = PickPerkColor();
|
|
|
|
PC = GetALocalPlayerController();
|
2020-11-28 20:12:58 +00:00
|
|
|
if (PC!=None)
|
2017-10-20 02:00:49 +00:00
|
|
|
LocalOwnerPRI = ExtPlayerReplicationInfo(PC.PlayerReplicationInfo);
|
|
|
|
}
|
|
|
|
else LocalOwnerPRI = Self; // Dedicated server can use self PRI.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resupply traits:
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated final function bool CanUseSupply(Pawn P)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
return (SupplierLimit.SuppliedPawn!=P || SupplierLimit.NextSupplyTimer<WorldInfo.TimeSeconds);
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated final function UsedSupply(Pawn P, float NextTime)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
SupplierLimit.SuppliedPawn = P;
|
|
|
|
SupplierLimit.NextSupplyTimer = WorldInfo.TimeSeconds+NextTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function ClientInitialize(Controller C)
|
|
|
|
{
|
|
|
|
local ExtPlayerReplicationInfo PRI;
|
|
|
|
|
|
|
|
Super.ClientInitialize(C);
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode!=NM_DedicatedServer)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
LocalOwnerPRI = Self;
|
|
|
|
|
|
|
|
// Make all other PRI's load character list from local owner PRI.
|
|
|
|
foreach DynamicActors(class'ExtPlayerReplicationInfo',PRI)
|
|
|
|
PRI.LocalOwnerPRI = Self;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function TickPT()
|
|
|
|
{
|
|
|
|
++RepPlayTime;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event ReplicatedEvent(name VarName)
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
switch (VarName)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
case 'RepLevelProgress':
|
|
|
|
HUDPerkColor = PickPerkColor();
|
|
|
|
break;
|
|
|
|
case 'CustomCharacter':
|
|
|
|
CharacterCustomizationChanged();
|
|
|
|
break;
|
|
|
|
case 'HasSupplier':
|
|
|
|
SupplierLimit.SuppliedPawn = None; // Reset if stat was changed.
|
|
|
|
break;
|
|
|
|
case 'PlayerName':
|
|
|
|
case 'NameTag':
|
|
|
|
UpdateNameTag();
|
|
|
|
default:
|
|
|
|
Super.ReplicatedEvent(VarName);
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
function SetPlayerName(string S)
|
|
|
|
{
|
|
|
|
Super.SetPlayerName(S);
|
|
|
|
UpdateNameTag();
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
function SetPlayerNameTag(string S)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
NameTag = S;
|
|
|
|
UpdateNameTag();
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
function OverrideWith(PlayerReplicationInfo PRI)
|
|
|
|
{
|
|
|
|
Super.OverrideWith(PRI);
|
|
|
|
NameTag = ExtPlayerReplicationInfo(PRI).NameTag;
|
|
|
|
bAdmin = PRI.bAdmin;
|
|
|
|
AdminType = ExtPlayerReplicationInfo(PRI).AdminType;
|
|
|
|
UpdateNameTag();
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function UpdateNameTag()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (NameTag!="")
|
2017-10-20 02:00:49 +00:00
|
|
|
TaggedPlayerName = "["$NameTag$"] "$PlayerName;
|
|
|
|
else TaggedPlayerName = PlayerName;
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
final function SetLevelProgress(int CurLevel, int CurPrest, int MinLevel, int MaxLevel)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
local float V;
|
|
|
|
|
|
|
|
ECurrentPerkLevel = CurLevel;
|
|
|
|
ECurrentPerkPrestige = CurPrest;
|
|
|
|
V = FClamp((float(CurLevel-MinLevel) / float(MaxLevel-MinLevel))*255.f,0,255);
|
|
|
|
RepLevelProgress = V;
|
|
|
|
bForceNetUpdate = true;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode!=NM_DedicatedServer)
|
2017-10-20 02:00:49 +00:00
|
|
|
HUDPerkColor = PickPerkColor();
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function string GetPerkLevelStr()
|
|
|
|
{
|
|
|
|
return (ECurrentPerkPrestige>0 ? (string(ECurrentPerkPrestige)$"-"$string(ECurrentPerkLevel)) : string(ECurrentPerkLevel));
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function color PickPerkColor()
|
|
|
|
{
|
|
|
|
local float P;
|
|
|
|
local byte i;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (RepLevelProgress==0)
|
2017-10-20 02:00:49 +00:00
|
|
|
return MakeColor(255,255,255,255);
|
|
|
|
P = float(RepLevelProgress) / 255.f;
|
2020-11-28 20:12:58 +00:00
|
|
|
if (P<0.25f) // White - Blue
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
i = 255 - (P*1020.f);
|
|
|
|
return MakeColor(i,i,255,255);
|
|
|
|
}
|
2020-11-28 20:12:58 +00:00
|
|
|
if (P<0.5f) // Blue - Green
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
i = ((P-0.25f)*1020.f);
|
|
|
|
return MakeColor(0,i,255-i,255);
|
|
|
|
}
|
2020-11-28 20:12:58 +00:00
|
|
|
if (P<0.75f) // Green - Red
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
i = ((P-0.5f)*1020.f);
|
|
|
|
return MakeColor(i,255-i,0,255);
|
|
|
|
}
|
|
|
|
// Red - Yellow
|
|
|
|
i = ((P-0.75f)*1020.f);
|
|
|
|
return MakeColor(255,i,0,255);
|
|
|
|
}
|
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
function SetInitPlayTime(int T)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
bInitialPT = true;
|
|
|
|
bForceNetUpdate = true;
|
|
|
|
RepPlayTime = T;
|
|
|
|
SetTimer(5,false,'UnsetPT');
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
function UnsetPT()
|
|
|
|
{
|
|
|
|
bInitialPT = false;
|
|
|
|
}
|
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
Delegate bool OnRepNextItem(ExtPlayerReplicationInfo PRI, int RepIndex)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated reliable client function ClientAddTraderItem(int Index, FCustomTraderItem Item)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
// Make sure to not execute on server.
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode!=NM_Client && (PlayerController(Owner)==None || LocalPlayer(PlayerController(Owner).Player)==None))
|
2017-10-20 02:00:49 +00:00
|
|
|
return;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CustomList==None)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-06-23 20:38:04 +00:00
|
|
|
CustomList = CreateNewList();
|
2017-10-20 02:00:49 +00:00
|
|
|
RecheckGRI();
|
|
|
|
}
|
|
|
|
CustomItems.AddItem(Item);
|
|
|
|
SetWeaponInfo(false,Index,Item,CustomList);
|
|
|
|
}
|
2020-06-23 20:38:04 +00:00
|
|
|
|
|
|
|
simulated static final function KFGFxObject_TraderItems CreateNewList()
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-06-23 12:48:24 +00:00
|
|
|
local KFGFxObject_TraderItems L;
|
2017-10-20 02:00:49 +00:00
|
|
|
|
2020-06-23 20:38:04 +00:00
|
|
|
L = new class'KFGFxObject_TraderItems';
|
|
|
|
L.SaleItems = L.Default.SaleItems;
|
|
|
|
L.ArmorPrice = L.Default.ArmorPrice;
|
|
|
|
L.GrenadePrice = L.Default.GrenadePrice;
|
2017-10-20 02:00:49 +00:00
|
|
|
|
|
|
|
return L;
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated static final function SetWeaponInfo(bool bDedicated, int Index, FCustomTraderItem Item, KFGFxObject_TraderItems List)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
local array<STraderItemWeaponStats> S;
|
2020-07-06 21:12:25 +00:00
|
|
|
local int i;
|
2017-10-20 02:00:49 +00:00
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (List.SaleItems.Length<=Index)
|
2017-10-20 02:00:49 +00:00
|
|
|
List.SaleItems.Length = Index+1;
|
|
|
|
|
|
|
|
List.SaleItems[Index].WeaponDef = Item.WeaponDef;
|
|
|
|
List.SaleItems[Index].ClassName = Item.WeaponClass.Name;
|
2020-11-28 20:12:58 +00:00
|
|
|
if (class<KFWeap_DualBase>(Item.WeaponClass)!=None && class<KFWeap_DualBase>(Item.WeaponClass).Default.SingleClass!=None)
|
2017-10-20 02:00:49 +00:00
|
|
|
List.SaleItems[Index].SingleClassName = class<KFWeap_DualBase>(Item.WeaponClass).Default.SingleClass.Name;
|
|
|
|
else List.SaleItems[Index].SingleClassName = '';
|
|
|
|
List.SaleItems[Index].DualClassName = Item.WeaponClass.Default.DualClass!=None ? Item.WeaponClass.Default.DualClass.Name : '';
|
|
|
|
List.SaleItems[Index].AssociatedPerkClasses = Item.WeaponClass.Static.GetAssociatedPerkClasses();
|
2020-07-06 21:12:25 +00:00
|
|
|
List.SaleItems[Index].MaxSpareAmmo = Item.WeaponClass.Default.SpareAmmoCapacity[0];
|
2017-10-20 02:00:49 +00:00
|
|
|
List.SaleItems[Index].MagazineCapacity = Item.WeaponClass.Default.MagazineCapacity[0];
|
|
|
|
List.SaleItems[Index].InitialSpareMags = Item.WeaponClass.Default.InitialSpareMags[0];
|
|
|
|
List.SaleItems[Index].MaxSecondaryAmmo = Item.WeaponClass.Default.MagazineCapacity[1] * Item.WeaponClass.Default.SpareAmmoCapacity[1];
|
|
|
|
List.SaleItems[Index].BlocksRequired = Item.WeaponClass.Default.InventorySize;
|
|
|
|
List.SaleItems[Index].ItemID = Index;
|
2020-07-06 21:12:25 +00:00
|
|
|
|
|
|
|
List.SaleItems[Index].InitialSecondaryAmmo = Item.WeaponClass.Default.InitialSpareMags[1];
|
|
|
|
List.SaleItems[Index].WeaponUpgradeDmgMultiplier[0] = 1.0;
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i = 0;i<Min(Item.WeaponClass.Default.WeaponUpgrades.Length, 5);i++)
|
2020-07-06 21:12:25 +00:00
|
|
|
{
|
|
|
|
List.SaleItems[Index].WeaponUpgradeWeight[i+1] = Item.WeaponClass.Static.GetUpgradeStatAdd(EWUS_Weight, i+1);
|
|
|
|
List.SaleItems[Index].WeaponUpgradeDmgMultiplier[i+1] = Item.WeaponClass.Static.GetUpgradeStatScale(EWUS_Damage0, i+1);
|
|
|
|
}
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (!bDedicated)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-07-06 21:12:25 +00:00
|
|
|
List.SaleItems[Index].SecondaryAmmoImagePath = Item.WeaponClass.Default.SecondaryAmmoTexture!=None ? PathName(Item.WeaponClass.Default.SecondaryAmmoTexture) : "UI_SecondaryAmmo_TEX.GasTank";
|
2017-10-20 02:00:49 +00:00
|
|
|
List.SaleItems[Index].TraderFilter = Item.WeaponClass.Static.GetTraderFilter();
|
|
|
|
List.SaleItems[Index].InventoryGroup = Item.WeaponClass.Default.InventoryGroup;
|
|
|
|
List.SaleItems[Index].GroupPriority = Item.WeaponClass.Default.GroupPriority;
|
|
|
|
Item.WeaponClass.Static.SetTraderWeaponStats(S);
|
|
|
|
List.SaleItems[Index].WeaponStats = S;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function RecheckGRI()
|
|
|
|
{
|
|
|
|
local ExtPlayerController PC;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (KFGameReplicationInfo(WorldInfo.GRI)==None)
|
2017-10-20 02:00:49 +00:00
|
|
|
SetTimer(0.1,false,'RecheckGRI');
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KFGameReplicationInfo(WorldInfo.GRI).TraderItems = CustomList;
|
|
|
|
foreach LocalPlayerControllers(class'ExtPlayerController',PC)
|
2020-07-06 21:12:25 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (PC.PurchaseHelper!=None)
|
2020-07-06 21:12:25 +00:00
|
|
|
{
|
2017-10-20 02:00:49 +00:00
|
|
|
PC.PurchaseHelper.TraderItems = CustomList;
|
2020-07-06 21:12:25 +00:00
|
|
|
}
|
|
|
|
}
|
2017-10-20 02:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated final function bool ShowAdminName()
|
|
|
|
{
|
|
|
|
return (bAdmin || AdminType<255);
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated function string GetAdminName()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
switch (AdminType)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return "Super Admin";
|
|
|
|
case 1:
|
|
|
|
case 255:
|
|
|
|
return "Admin";
|
|
|
|
case 2:
|
|
|
|
return "Mod";
|
|
|
|
case 3:
|
|
|
|
return "Trusted Member";
|
|
|
|
case 4:
|
|
|
|
return "VIP";
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated function string GetAdminNameAbr()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
switch (AdminType)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return "S";
|
|
|
|
case 1:
|
|
|
|
case 255:
|
|
|
|
return "A";
|
|
|
|
case 2:
|
|
|
|
return "M";
|
|
|
|
case 3:
|
|
|
|
return "T";
|
|
|
|
case 4:
|
|
|
|
return "V";
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated function string GetAdminColor()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
switch (AdminType)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return "FF6600";
|
|
|
|
case 1:
|
|
|
|
case 255:
|
|
|
|
return "40FFFF";
|
|
|
|
case 2:
|
|
|
|
return "FF33FF";
|
|
|
|
case 3:
|
|
|
|
return "FF0000";
|
|
|
|
case 4:
|
|
|
|
return "FFD700";
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated function color GetAdminColorC()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
switch (AdminType)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return MakeColor(255,102,0,255);
|
|
|
|
case 1:
|
|
|
|
case 255:
|
|
|
|
return MakeColor(64,255,255,255);
|
|
|
|
case 2:
|
|
|
|
return MakeColor(255,51,255,255);
|
|
|
|
case 3:
|
|
|
|
return MakeColor(255,0,0,255);
|
|
|
|
case 4:
|
|
|
|
return MakeColor(255,215,0,255);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated function string GetHumanReadableName()
|
|
|
|
{
|
|
|
|
return TaggedPlayerName;
|
|
|
|
}
|
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
function SetFixedData(byte M)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
OnModeSet(Self,M);
|
|
|
|
FixedData = FixedData | M;
|
|
|
|
SetTimer(5,false,'ClearFixed');
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
function ClearFixed()
|
|
|
|
{
|
|
|
|
FixedData = 0;
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function string GetDesc()
|
|
|
|
{
|
|
|
|
local string S;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if ((FixedData & 1)!=0)
|
2017-10-20 02:00:49 +00:00
|
|
|
S = "A.";
|
2020-11-28 20:12:58 +00:00
|
|
|
if ((FixedData & 2)!=0)
|
2017-10-20 02:00:49 +00:00
|
|
|
S $= "WF.";
|
2020-11-28 20:12:58 +00:00
|
|
|
if ((FixedData & 4)!=0)
|
2017-10-20 02:00:49 +00:00
|
|
|
S $= "G.";
|
2020-11-28 20:12:58 +00:00
|
|
|
if ((FixedData & 8)!=0)
|
2017-10-20 02:00:49 +00:00
|
|
|
S $= "NW.";
|
2020-11-28 20:12:58 +00:00
|
|
|
if ((FixedData & 16)!=0)
|
2017-10-20 02:00:49 +00:00
|
|
|
S $= "WA.";
|
|
|
|
return S;
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
delegate OnModeSet(ExtPlayerReplicationInfo PRI, byte Num);
|
2017-10-20 02:00:49 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated final function bool LoadPlayerCharacter(byte CharIndex, out FMyCustomChar CharInfo)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
local KFCharacterInfo_Human C;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CharIndex>=(CharacterArchetypes.Length+CustomCharList.Length))
|
2017-10-20 02:00:49 +00:00
|
|
|
return false;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (SaveDataObjects.Length<=CharIndex)
|
2017-10-20 02:00:49 +00:00
|
|
|
SaveDataObjects.Length = CharIndex+1;
|
2020-11-28 20:12:58 +00:00
|
|
|
if (SaveDataObjects[CharIndex]==None)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
C = (CharIndex<CharacterArchetypes.Length) ? CharacterArchetypes[CharIndex] : CustomCharList[CharIndex-CharacterArchetypes.Length].Char;
|
|
|
|
SaveDataObjects[CharIndex] = new(None,PathName(C)) class'ExtCharDataInfo';
|
|
|
|
}
|
|
|
|
CharInfo = SaveDataObjects[CharIndex].LoadData();
|
|
|
|
return true;
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function bool SavePlayerCharacter()
|
|
|
|
{
|
|
|
|
local KFCharacterInfo_Human C;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CustomCharacter.CharacterIndex>=(CharacterArchetypes.Length+CustomCharList.Length))
|
2017-10-20 02:00:49 +00:00
|
|
|
return false;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (SaveDataObjects.Length<=CustomCharacter.CharacterIndex)
|
2017-10-20 02:00:49 +00:00
|
|
|
SaveDataObjects.Length = CustomCharacter.CharacterIndex+1;
|
2020-11-28 20:12:58 +00:00
|
|
|
if (SaveDataObjects[CustomCharacter.CharacterIndex]==None)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
C = (CustomCharacter.CharacterIndex<CharacterArchetypes.Length) ? CharacterArchetypes[CustomCharacter.CharacterIndex] : CustomCharList[CustomCharacter.CharacterIndex-CharacterArchetypes.Length].Char;
|
|
|
|
SaveDataObjects[CustomCharacter.CharacterIndex] = new(None,PathName(C)) class'ExtCharDataInfo';
|
|
|
|
}
|
|
|
|
SaveDataObjects[CustomCharacter.CharacterIndex].SaveData(CustomCharacter);
|
|
|
|
return true;
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated function ChangeCharacter(byte CharIndex, optional bool bFirstSet)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
local FMyCustomChar NewChar;
|
|
|
|
local byte i;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CharIndex>=(CharacterArchetypes.Length+CustomCharList.Length) || IsClientCharLocked(CharIndex))
|
2017-10-20 02:00:49 +00:00
|
|
|
CharIndex = 0;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (bFirstSet && RepCustomizationInfo.CharacterIndex==CharIndex)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
// Copy properties from default character info.
|
|
|
|
NewChar.HeadMeshIndex = RepCustomizationInfo.HeadMeshIndex;
|
|
|
|
NewChar.HeadSkinIndex = RepCustomizationInfo.HeadSkinIndex;
|
|
|
|
NewChar.BodyMeshIndex = RepCustomizationInfo.BodyMeshIndex;
|
|
|
|
NewChar.BodySkinIndex = RepCustomizationInfo.BodySkinIndex;
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
NewChar.AttachmentMeshIndices[i] = RepCustomizationInfo.AttachmentMeshIndices[i];
|
|
|
|
NewChar.AttachmentSkinIndices[i] = RepCustomizationInfo.AttachmentSkinIndices[i];
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 20:12:58 +00:00
|
|
|
if (LoadPlayerCharacter(CharIndex,NewChar))
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
NewChar.CharacterIndex = CharIndex;
|
|
|
|
CustomCharacter = NewChar;
|
|
|
|
ServerSetCharacterX(NewChar);
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode==NM_Client)
|
2017-10-20 02:00:49 +00:00
|
|
|
CharacterCustomizationChanged();
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-12-13 20:47:31 +00:00
|
|
|
simulated function UpdateCustomization(int Type, int MeshIndex, int SkinIndex, optional int SlotIndex)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
switch (Type)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
case CO_Head:
|
|
|
|
CustomCharacter.HeadMeshIndex = MeshIndex;
|
|
|
|
CustomCharacter.HeadSkinIndex = SkinIndex;
|
|
|
|
break;
|
|
|
|
case CO_Body:
|
|
|
|
CustomCharacter.BodyMeshIndex = MeshIndex;
|
|
|
|
CustomCharacter.BodySkinIndex = SkinIndex;
|
|
|
|
break;
|
|
|
|
case CO_Attachment:
|
|
|
|
CustomCharacter.AttachmentMeshIndices[SlotIndex] = MeshIndex;
|
|
|
|
CustomCharacter.AttachmentSkinIndices[SlotIndex] = SkinIndex;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SavePlayerCharacter();
|
|
|
|
ServerSetCharacterX(CustomCharacter);
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode==NM_Client)
|
2017-10-20 02:00:49 +00:00
|
|
|
CharacterCustomizationChanged();
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function RemoveAttachments()
|
|
|
|
{
|
|
|
|
local byte i;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
CustomCharacter.AttachmentMeshIndices[i] = `CLEARED_ATTACHMENT_INDEX;
|
|
|
|
CustomCharacter.AttachmentSkinIndices[i] = 0;
|
|
|
|
}
|
|
|
|
SavePlayerCharacter();
|
|
|
|
ServerSetCharacterX(CustomCharacter);
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode==NM_Client)
|
2017-10-20 02:00:49 +00:00
|
|
|
CharacterCustomizationChanged();
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated function ClearCharacterAttachment(int AttachmentIndex)
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (UsesCustomChar())
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
CustomCharacter.AttachmentMeshIndices[AttachmentIndex] = `CLEARED_ATTACHMENT_INDEX;
|
|
|
|
CustomCharacter.AttachmentSkinIndices[AttachmentIndex] = 0;
|
|
|
|
}
|
|
|
|
else Super.ClearCharacterAttachment(AttachmentIndex);
|
|
|
|
}
|
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
reliable server final function ServerSetCharacterX(FMyCustomChar NewMeshInfo)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (NewMeshInfo.CharacterIndex>=(CharacterArchetypes.Length+CustomCharList.Length) || IsClientCharLocked(NewMeshInfo.CharacterIndex))
|
2017-10-20 02:00:49 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
CustomCharacter = NewMeshInfo;
|
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
if (Role == Role_Authority)
|
2020-11-28 19:53:57 +00:00
|
|
|
{
|
2017-10-20 02:00:49 +00:00
|
|
|
CharacterCustomizationChanged();
|
2020-11-28 19:53:57 +00:00
|
|
|
}
|
2017-10-20 02:00:49 +00:00
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated final function bool IsClientCharLocked(byte Index)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (Index<CharacterArchetypes.Length)
|
2017-10-20 02:00:49 +00:00
|
|
|
return false;
|
|
|
|
Index-=CharacterArchetypes.Length;
|
|
|
|
return (Index<CustomCharList.Length && CustomCharList[Index].bLock && !ShowAdminName());
|
|
|
|
}
|
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
simulated reliable client function ReceivedCharacter(byte Index, FCustomCharEntry C)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode==NM_DedicatedServer)
|
2017-10-20 02:00:49 +00:00
|
|
|
return;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CustomCharList.Length<=Index)
|
2017-10-20 02:00:49 +00:00
|
|
|
CustomCharList.Length = Index+1;
|
|
|
|
CustomCharList[Index] = C;
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated reliable client function AllCharReceived()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (WorldInfo.NetMode==NM_DedicatedServer)
|
2017-10-20 02:00:49 +00:00
|
|
|
return;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (!bClientInitChars)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
OnCharListDone();
|
|
|
|
NotifyCharListDone();
|
|
|
|
bClientInitChars = true;
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function NotifyCharListDone()
|
|
|
|
{
|
|
|
|
local KFPawn_Human KFP;
|
|
|
|
local KFCharacterInfo_Human NewCharArch;
|
|
|
|
local ExtPlayerReplicationInfo EPRI;
|
|
|
|
|
|
|
|
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFP)
|
|
|
|
{
|
|
|
|
EPRI = ExtPlayerReplicationInfo(KFP.PlayerReplicationInfo);
|
2020-11-28 20:12:58 +00:00
|
|
|
if (EPRI!=None)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
NewCharArch = EPRI.GetSelectedArch();
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (NewCharArch != KFP.CharacterArch)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
// selected a new character
|
2020-11-28 20:04:55 +00:00
|
|
|
KFP.SetCharacterArch(NewCharArch);
|
2017-10-20 02:00:49 +00:00
|
|
|
}
|
2020-11-28 20:12:58 +00:00
|
|
|
else if (WorldInfo.NetMode != NM_DedicatedServer)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
// refresh cosmetics only
|
2020-11-28 20:04:55 +00:00
|
|
|
class'ExtCharacterInfo'.Static.SetCharacterMeshFromArch(NewCharArch, KFP, EPRI);
|
2017-10-20 02:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated delegate OnCharListDone();
|
|
|
|
|
|
|
|
// Player has a server specific setting for a character selected.
|
|
|
|
simulated final function bool UsesCustomChar()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (LocalOwnerPRI==None)
|
2017-10-20 02:00:49 +00:00
|
|
|
return false; // Not yet init on client.
|
|
|
|
return CustomCharacter.CharacterIndex<(LocalOwnerPRI.CustomCharList.Length+CharacterArchetypes.Length);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Client uses a server specific custom character.
|
|
|
|
simulated final function bool ReallyUsingCustomChar()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (!UsesCustomChar())
|
2017-10-20 02:00:49 +00:00
|
|
|
return false;
|
|
|
|
return (CustomCharacter.CharacterIndex>=CharacterArchetypes.Length);
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
simulated final function KFCharacterInfo_Human GetSelectedArch()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (UsesCustomChar())
|
2017-10-20 02:00:49 +00:00
|
|
|
return (CustomCharacter.CharacterIndex<CharacterArchetypes.Length) ? CharacterArchetypes[CustomCharacter.CharacterIndex] : LocalOwnerPRI.CustomCharList[CustomCharacter.CharacterIndex-CharacterArchetypes.Length].Char;
|
|
|
|
return CharacterArchetypes[RepCustomizationInfo.CharacterIndex];
|
|
|
|
}
|
|
|
|
|
|
|
|
simulated event CharacterCustomizationChanged()
|
|
|
|
{
|
|
|
|
local KFPawn_Human KFP;
|
|
|
|
local KFCharacterInfo_Human NewCharArch;
|
|
|
|
|
|
|
|
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFP)
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (KFP.PlayerReplicationInfo == self || (KFP.DrivenVehicle != None && KFP.DrivenVehicle.PlayerReplicationInfo == self))
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
NewCharArch = GetSelectedArch();
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (NewCharArch != KFP.CharacterArch)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
// selected a new character
|
2020-11-28 20:04:55 +00:00
|
|
|
KFP.SetCharacterArch(NewCharArch);
|
2017-10-20 02:00:49 +00:00
|
|
|
}
|
2020-11-28 20:12:58 +00:00
|
|
|
else if (WorldInfo.NetMode != NM_DedicatedServer)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
// refresh cosmetics only
|
2020-11-28 20:04:55 +00:00
|
|
|
class'ExtCharacterInfo'.Static.SetCharacterMeshFromArch(NewCharArch, KFP, self);
|
2017-10-20 02:00:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save/Load custom character information.
|
2020-11-28 20:04:55 +00:00
|
|
|
final function SaveCustomCharacter(ExtSaveDataBase Data)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
local byte i,c;
|
|
|
|
local string S;
|
|
|
|
|
|
|
|
// Write the name of custom character.
|
2020-11-28 20:12:58 +00:00
|
|
|
if (UsesCustomChar())
|
2017-10-20 02:00:49 +00:00
|
|
|
S = string(GetSelectedArch().Name);
|
|
|
|
Data.SaveStr(S);
|
2020-11-28 20:12:58 +00:00
|
|
|
if (S=="")
|
2017-10-20 02:00:49 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Write selected accessories.
|
|
|
|
Data.SaveInt(CustomCharacter.HeadMeshIndex);
|
|
|
|
Data.SaveInt(CustomCharacter.HeadSkinIndex);
|
|
|
|
Data.SaveInt(CustomCharacter.BodyMeshIndex);
|
|
|
|
Data.SaveInt(CustomCharacter.BodySkinIndex);
|
|
|
|
|
|
|
|
c = 0;
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CustomCharacter.AttachmentMeshIndices[i]!=`CLEARED_ATTACHMENT_INDEX)
|
2017-10-20 02:00:49 +00:00
|
|
|
++c;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write attachments count.
|
|
|
|
Data.SaveInt(c);
|
|
|
|
|
|
|
|
// Write attachments.
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CustomCharacter.AttachmentMeshIndices[i]!=`CLEARED_ATTACHMENT_INDEX)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
Data.SaveInt(i);
|
|
|
|
Data.SaveInt(CustomCharacter.AttachmentMeshIndices[i]);
|
|
|
|
Data.SaveInt(CustomCharacter.AttachmentSkinIndices[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
final function LoadCustomCharacter(ExtSaveDataBase Data)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
local string S;
|
|
|
|
local byte i,n,j;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (Data.GetArVer()>=2)
|
2017-10-20 02:00:49 +00:00
|
|
|
S = Data.ReadStr();
|
2020-11-28 20:12:58 +00:00
|
|
|
if (S=="") // Stock skin.
|
2017-10-20 02:00:49 +00:00
|
|
|
return;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<CharacterArchetypes.Length; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (string(CharacterArchetypes[i].Name)~=S)
|
2017-10-20 02:00:49 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (i==CharacterArchetypes.Length)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<CustomCharList.Length; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (string(CustomCharList[i].Char.Name)~=S)
|
2017-10-20 02:00:49 +00:00
|
|
|
break;
|
|
|
|
}
|
2020-11-28 20:12:58 +00:00
|
|
|
if (i==CharacterArchetypes.Length)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
// Character not found = Skip data.
|
|
|
|
Data.SkipBytes(4);
|
|
|
|
n = Data.ReadInt();
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<n; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
Data.SkipBytes(3);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
i+=CharacterArchetypes.Length;
|
|
|
|
}
|
|
|
|
|
|
|
|
CustomCharacter.CharacterIndex = i;
|
|
|
|
CustomCharacter.HeadMeshIndex = Data.ReadInt();
|
|
|
|
CustomCharacter.HeadSkinIndex = Data.ReadInt();
|
|
|
|
CustomCharacter.BodyMeshIndex = Data.ReadInt();
|
|
|
|
CustomCharacter.BodySkinIndex = Data.ReadInt();
|
|
|
|
|
|
|
|
n = Data.ReadInt();
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<n; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
j = Min(Data.ReadInt(),`MAX_COSMETIC_ATTACHMENTS-1);
|
|
|
|
CustomCharacter.AttachmentMeshIndices[j] = Data.ReadInt();
|
|
|
|
CustomCharacter.AttachmentSkinIndices[j] = Data.ReadInt();
|
|
|
|
}
|
|
|
|
bNetDirty = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only used to skip offset (in case of an error).
|
2020-11-28 20:04:55 +00:00
|
|
|
static final function DummyLoadChar(ExtSaveDataBase Data)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
local string S;
|
|
|
|
local byte i,n;
|
|
|
|
|
2020-11-28 20:12:58 +00:00
|
|
|
if (Data.GetArVer()>=2)
|
2017-10-20 02:00:49 +00:00
|
|
|
S = Data.ReadStr();
|
2020-11-28 20:12:58 +00:00
|
|
|
if (S=="") // Stock skin.
|
2017-10-20 02:00:49 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
Data.SkipBytes(4);
|
|
|
|
n = Data.ReadInt();
|
2020-11-28 20:12:58 +00:00
|
|
|
for (i=0; i<n; ++i)
|
2017-10-20 02:00:49 +00:00
|
|
|
Data.SkipBytes(3);
|
|
|
|
}
|
2020-11-28 21:54:57 +00:00
|
|
|
|
2020-11-28 20:04:55 +00:00
|
|
|
static final function DummySaveChar(ExtSaveDataBase Data)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
Data.SaveStr("");
|
|
|
|
}
|
|
|
|
|
2020-01-09 11:05:13 +00:00
|
|
|
simulated function Texture2D GetCurrentIconToDisplay()
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
if (CurrentVoiceCommsRequest == VCT_NONE && ECurrentPerk != none)
|
2020-01-09 11:05:13 +00:00
|
|
|
{
|
|
|
|
return ECurrentPerk.default.PerkIcon;
|
|
|
|
}
|
|
|
|
|
|
|
|
return class'KFLocalMessage_VoiceComms'.default.VoiceCommsIcons[CurrentVoiceCommsRequest];
|
|
|
|
}
|
|
|
|
|
2017-10-20 02:00:49 +00:00
|
|
|
// Set admin levels without having to hard-reference to this mod.
|
|
|
|
event BeginState(Name N)
|
|
|
|
{
|
2020-11-28 20:12:58 +00:00
|
|
|
switch (N)
|
2017-10-20 02:00:49 +00:00
|
|
|
{
|
|
|
|
case 'Global':
|
|
|
|
AdminType = 0;
|
|
|
|
break;
|
|
|
|
case 'Admin':
|
|
|
|
AdminType = 1;
|
|
|
|
break;
|
|
|
|
case 'Mod':
|
|
|
|
AdminType = 2;
|
|
|
|
break;
|
|
|
|
case 'TMem':
|
|
|
|
AdminType = 3;
|
|
|
|
break;
|
|
|
|
case 'VIP':
|
|
|
|
AdminType = 4;
|
|
|
|
break;
|
|
|
|
case 'User':
|
|
|
|
AdminType = 255;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultproperties
|
|
|
|
{
|
|
|
|
RespawnCounter=-1
|
|
|
|
AdminType=255
|
|
|
|
TaggedPlayerName="Player"
|
|
|
|
}
|