KF2-Server-Extension/ServerExt/Classes/ExtPlayerReplicationInfo.uc

745 lines
17 KiB
Ucode
Raw Normal View History

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];
2023-05-14 02:49:12 +00:00
2020-11-28 19:53:57 +00:00
structdefaultproperties
{
AttachmentMeshIndices[0]=`CLEARED_ATTACHMENT_INDEX
AttachmentMeshIndices[1]=`CLEARED_ATTACHMENT_INDEX
AttachmentMeshIndices[2]=`CLEARED_ATTACHMENT_INDEX
}
2017-10-20 02:00:49 +00:00
};
var bool bIsMuted,bInitialPT,bIsDev,bHiddenUser,bClientUseCustom,bClientFirstChar,bClientCharListDone,bClientInitChars;
2022-08-30 04:42:20 +00:00
enum E_AdminType
{
AT_Global,
AT_Admin,
AT_Mod,
AT_TMem,
AT_VIP,
AT_Booster,
AT_Player
};
var E_AdminType AdminType;
2017-10-20 02:00:49 +00:00
var int RespawnCounter;
var class<Ext_PerkBase> ECurrentPerk;
var Ext_PerkBase FCurrentPerk;
2017-10-20 02:00:49 +00:00
var int ECurrentPerkLevel,ECurrentPerkPrestige;
var ExtPerkManager PerkManager;
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
// 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);
2023-05-14 02:49:12 +00:00
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;
2023-05-14 02:49:12 +00:00
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;
}
simulated final function bool ShowAdminName()
{
2022-08-30 04:42:20 +00:00
return (bAdmin || AdminType < AT_Player);
2017-10-20 02:00:49 +00:00
}
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
{
2022-08-30 04:42:20 +00:00
case AT_Global:
2017-10-20 02:00:49 +00:00
return "Super Admin";
2022-08-30 04:42:20 +00:00
case AT_Admin:
case AT_Player: // TODO: Admin is the same as player? WTF? #1
2017-10-20 02:00:49 +00:00
return "Admin";
2022-08-30 04:42:20 +00:00
case AT_Mod:
2017-10-20 02:00:49 +00:00
return "Mod";
2022-08-30 04:42:20 +00:00
case AT_TMem:
2017-10-20 02:00:49 +00:00
return "Trusted Member";
2022-08-30 04:42:20 +00:00
case AT_VIP:
2017-10-20 02:00:49 +00:00
return "VIP";
2022-08-30 04:42:20 +00:00
case AT_Booster:
return "Booster";
2017-10-20 02:00:49 +00:00
}
}
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
{
2022-08-30 04:42:20 +00:00
case AT_Global:
2017-10-20 02:00:49 +00:00
return "S";
2022-08-30 04:42:20 +00:00
case AT_Admin:
case AT_Player: // TODO: Admin is the same as player? WTF? #2
2017-10-20 02:00:49 +00:00
return "A";
2022-08-30 04:42:20 +00:00
case AT_Mod:
2017-10-20 02:00:49 +00:00
return "M";
2022-08-30 04:42:20 +00:00
case AT_TMem:
2017-10-20 02:00:49 +00:00
return "T";
2022-08-30 04:42:20 +00:00
case AT_VIP:
2017-10-20 02:00:49 +00:00
return "V";
2022-08-30 04:42:20 +00:00
case AT_Booster:
return "B";
2017-10-20 02:00:49 +00:00
}
}
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
{
2022-08-30 04:42:20 +00:00
case AT_Global:
2017-10-20 02:00:49 +00:00
return "FF6600";
2022-08-30 04:42:20 +00:00
case AT_Admin:
case AT_Player: // TODO: Admin is the same as player? WTF? #3
2017-10-20 02:00:49 +00:00
return "40FFFF";
2022-08-30 04:42:20 +00:00
case AT_Mod:
2017-10-20 02:00:49 +00:00
return "FF33FF";
2022-08-30 04:42:20 +00:00
case AT_TMem:
2017-10-20 02:00:49 +00:00
return "FF0000";
2022-08-30 04:42:20 +00:00
case AT_VIP:
2017-10-20 02:00:49 +00:00
return "FFD700";
2022-08-30 04:42:20 +00:00
case AT_Booster:
return "32A852";
2017-10-20 02:00:49 +00:00
}
}
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
{
2022-08-30 04:42:20 +00:00
case AT_Global:
2017-10-20 02:00:49 +00:00
return MakeColor(255,102,0,255);
2022-08-30 04:42:20 +00:00
case AT_Admin:
case AT_Player: // TODO: Admin is the same as player? WTF? #4
2017-10-20 02:00:49 +00:00
return MakeColor(64,255,255,255);
2022-08-30 04:42:20 +00:00
case AT_Mod:
2017-10-20 02:00:49 +00:00
return MakeColor(255,51,255,255);
2022-08-30 04:42:20 +00:00
case AT_TMem:
2017-10-20 02:00:49 +00:00
return MakeColor(255,0,0,255);
2022-08-30 04:42:20 +00:00
case AT_VIP:
2017-10-20 02:00:49 +00:00
return MakeColor(255,215,0,255);
2022-08-30 04:42:20 +00:00
case AT_Booster:
return MakeColor(50,168,82,255);
2017-10-20 02:00:49 +00:00
}
}
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;
2023-05-14 02:49:12 +00:00
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
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;
2023-05-14 02:49:12 +00:00
2017-10-20 02:00:49 +00:00
// Write selected accessories.
Data.SaveInt(CustomCharacter.HeadMeshIndex);
Data.SaveInt(CustomCharacter.HeadSkinIndex);
Data.SaveInt(CustomCharacter.BodyMeshIndex);
Data.SaveInt(CustomCharacter.BodySkinIndex);
2023-05-14 02:49:12 +00:00
2017-10-20 02:00:49 +00:00
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);
2023-05-14 02:49:12 +00:00
2017-10-20 02:00:49 +00:00
// 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;
}
2023-05-14 02:49:12 +00:00
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':
2022-08-30 04:42:20 +00:00
AdminType = AT_Global;
2017-10-20 02:00:49 +00:00
break;
case 'Admin':
2022-08-30 04:42:20 +00:00
AdminType = AT_Admin;
2017-10-20 02:00:49 +00:00
break;
case 'Mod':
2022-08-30 04:42:20 +00:00
AdminType = AT_Mod;
2017-10-20 02:00:49 +00:00
break;
case 'TMem':
2022-08-30 04:42:20 +00:00
AdminType = AT_TMem;
2017-10-20 02:00:49 +00:00
break;
case 'VIP':
2022-08-30 04:42:20 +00:00
AdminType = AT_VIP;
break;
case 'Booster':
AdminType = AT_Booster;
2017-10-20 02:00:49 +00:00
break;
case 'User':
2022-08-30 04:42:20 +00:00
AdminType = AT_Player;
2017-10-20 02:00:49 +00:00
break;
}
}
defaultproperties
{
RespawnCounter=-1
2022-09-16 03:36:06 +00:00
AdminType=AT_Player
2017-10-20 02:00:49 +00:00
TaggedPlayerName="Player"
2023-05-14 02:49:12 +00:00
}