Updated to the latest KF version

This commit is contained in:
ForrestMarkX 2020-01-09 05:05:13 -06:00
parent fd568e3d66
commit 245eb9e552
12 changed files with 1408 additions and 1044 deletions

View File

@ -230,7 +230,7 @@ function int AddItemByPriority( out SItemInformation WeaponInfo )
return BestIndex;
}
function bool CanCarry( const out STraderItem Item )
function bool CanCarry(const out STraderItem Item, optional int OverrideLevelValue = INDEX_NONE)
{
local int Result;

View File

@ -36,6 +36,51 @@ static final function Object SafeLoadObject( string S, Class ObjClass )
return O!=None ? O : DynamicLoadObject(S,ObjClass);
}
static function InitCharacterMICs(KFCharacterInfo_Human C, KFPawn P, optional bool bMaskHead)
{
local int i;
if( P.WorldInfo.NetMode == NM_DedicatedServer )
{
return;
}
P.CharacterMICs.Remove(0, P.CharacterMICs.Length);
// body MIC
if ( P.Mesh != None )
{
P.CharacterMICs[0] = P.Mesh.CreateAndSetMaterialInstanceConstant(C.BodyMaterialID);
CloneMIC(P.CharacterMICs[0]);
}
// head MIC
if( P.ThirdPersonHeadMeshComponent != None )
{
P.CharacterMICs[1] = P.ThirdPersonHeadMeshComponent.CreateAndSetMaterialInstanceConstant(C.HeadMaterialID);
if ( bMaskHead )
{
// initial mask for new head MIC (also see ResetHeadMaskParam())
P.CharacterMICs[1].SetScalarParameterValue('Scalar_Mask', 1.f);
}
}
// attachment MIC
for( i=0; i < `MAX_COSMETIC_ATTACHMENTS; i++ )
{
if( P.ThirdPersonAttachments[i] != none )
{
P.CharacterMICs.AddItem(P.ThirdPersonAttachments[i].CreateAndSetMaterialInstanceConstant(0));
}
if (P.FirstPersonAttachments[i] != none)
{
P.CharacterMICs.AddItem(P.FirstPersonAttachments[i].CreateAndSetMaterialInstanceConstant(0));
}
}
}
/** Sets the pawns character mesh from it's CharacterInfo, and updates instance of player in map if there is one. */
static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI )
{
@ -43,25 +88,27 @@ static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn
local int AttachmentIdx, CosmeticMeshIdx;
local bool bMaskHeadMesh, bCustom;
EPRI = ExtPlayerReplicationInfo(KFPRI);
if ( KFPRI == none )
{
`Warn("Does not have a KFPRI" @ C);
return;
}
EPRI = ExtPlayerReplicationInfo(KFPRI);
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// Body mesh & skin. Index of 255 implies use index 0 (default).
SetBodyMeshAndSkin(C,
bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex,
bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex,
KFP);
KFP,
KFPRI);
// Head mesh & skin. Index of 255 implies use index 0 (default).
SetHeadMeshAndSkin(C,
bCustom ? EPRI.CustomCharacter.HeadMeshIndex : KFPRI.RepCustomizationInfo.HeadMeshIndex,
bCustom ? EPRI.CustomCharacter.HeadSkinIndex : KFPRI.RepCustomizationInfo.HeadSkinIndex,
KFP);
KFP,
KFPRI);
// skip dedicated for purely cosmetic stuff
if ( KFP.WorldInfo.NetMode != NM_DedicatedServer )
@ -78,7 +125,7 @@ static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn
for( AttachmentIdx=0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ )
{
CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx];
if ( CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX )
if ( CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX && CosmeticMeshIdx != INDEX_NONE )
{
bMaskHeadMesh = bMaskHeadMesh || C.CosmeticVariants[CosmeticMeshIdx].bMaskHeadMesh;
@ -91,29 +138,49 @@ static final function SetCharacterMeshFromArch( KFCharacterInfo_Human C, KFPawn
}
// initial mask for new MIC (also see ResetHeadMaskParam())
if ( bMaskHeadMesh && KFP.CharacterMICs[1] != None )
KFP.CharacterMICs[1].SetScalarParameterValue('Scalar_Mask', 1.f);
InitCharacterMICs(C, KFP, bMaskHeadMesh);
}
}
static final function SetBodyMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentBodyMeshIndex,
byte CurrentBodySkinIndex,
KFPawn KFP )
KFPawn KFP,
KFPlayerReplicationInfo KFPRI )
{
local string CharBodyMeshName;
local SkeletalMesh CharBodyMesh;
//Always use default body on servers
if (KFP.WorldInfo.NetMode == NM_DedicatedServer)
{
CurrentBodyMeshIndex = 0;
CurrentBodySkinIndex = 0;
}
// Character Mesh
if( C.BodyVariants.length > 0 )
{
// Assign a skin to the body mesh as a material override
CurrentBodyMeshIndex = (CurrentBodyMeshIndex < C.BodyVariants.length) ? CurrentBodyMeshIndex : 0;
if (KFPRI.StartLoadCosmeticContent(C, ECOSMETICTYPE_Body, CurrentBodyMeshIndex))
{
return;
}
// Retrieve the name of the meshes to be used from the archetype
CharBodyMeshName = C.BodyVariants[CurrentBodyMeshIndex].MeshName;
// Load the meshes
CharBodyMesh = SkeletalMesh(SafeLoadObject(C.BodyVariants[CurrentBodyMeshIndex].MeshName, class'SkeletalMesh'));
CharBodyMesh = SkeletalMesh(SafeLoadObject(CharBodyMeshName, class'SkeletalMesh'));
// Assign the body mesh to the pawn
if ( CharBodyMesh != KFP.Mesh.SkeletalMesh )
{
KFP.Mesh.SetSkeletalMesh(CharBodyMesh);
KFP.OnCharacterMeshChanged();
}
if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
{
@ -146,17 +213,10 @@ static final function SetBodySkinMaterial( KFCharacterInfo_Human C, OutfitVarian
KFP.Mesh.SetMaterial(i, none);
}
}
// Initialize MICs
if( KFP.Mesh != None )
{
KFP.CharacterMICs[0] = KFP.Mesh.CreateAndSetMaterialInstanceConstant(C.BodyMaterialID);
CloneMIC(KFP.CharacterMICs[0]);
}
}
}
static final function SetHeadSkinMaterial( KFCharacterInfo_Human C, OutfitVariants CurrentVariant, byte NewSkinIndex, KFPawn KFP)
static final function SetHeadSkinMaterial( KFCharacterInfo_Human C, OutfitVariants CurrentVariant, byte NewSkinIndex, KFPawn KFP )
{
local int i;
@ -176,20 +236,14 @@ static final function SetHeadSkinMaterial( KFCharacterInfo_Human C, OutfitVarian
KFP.ThirdPersonHeadMeshComponent.SetMaterial(i, none);
}
}
// Initialize MICs
if( KFP.ThirdPersonHeadMeshComponent != None )
{
KFP.CharacterMICs[1] = KFP.ThirdPersonHeadMeshComponent.CreateAndSetMaterialInstanceConstant(C.HeadMaterialID);
CloneMIC(KFP.CharacterMICs[1]);
}
}
}
static final function SetHeadMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentHeadMeshIndex,
byte CurrentHeadSkinIndex,
KFPawn KFP )
KFPawn KFP,
KFPlayerReplicationInfo KFPRI )
{
local string CharHeadMeshName;
local SkeletalMesh CharHeadMesh;
@ -198,6 +252,11 @@ static final function SetHeadMeshAndSkin( KFCharacterInfo_Human C,
{
CurrentHeadMeshIndex = (CurrentHeadMeshIndex < C.HeadVariants.length) ? CurrentHeadMeshIndex : 0;
if (KFPRI.StartLoadCosmeticContent(C, ECOSMETICTYPE_Head, CurrentHeadMeshIndex))
{
return;
}
CharHeadMeshName = C.HeadVariants[CurrentHeadMeshIndex].MeshName;
CharHeadMesh = SkeletalMesh(DynamicLoadObject(CharHeadMeshName, class'SkeletalMesh'));
@ -222,7 +281,8 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
int PawnAttachmentIndex,
const out AttachmentVariants CurrentVariant,
byte NewSkinIndex,
KFPawn KFP)
KFPawn KFP,
optional bool bIsFirstPerson)
{
local int i;
if (KFP.WorldInfo.NetMode != NM_DedicatedServer)
@ -231,11 +291,23 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
{
// Assign a skin to the attachment mesh as a material override
if ( NewSkinIndex < CurrentVariant.AttachmentItem.SkinVariations.length )
{
if (bIsFirstPerson)
{
if (KFP.FirstPersonAttachments[PawnAttachmentIndex] != none)
{
KFP.FirstPersonAttachments[PawnAttachmentIndex].SetMaterial(
CurrentVariant.AttachmentItem.SkinMaterialID,
CurrentVariant.AttachmentItem.SkinVariations[NewSkinIndex].Skin1p);
}
}
else
{
KFP.ThirdPersonAttachments[PawnAttachmentIndex].SetMaterial(
CurrentVariant.AttachmentItem.SkinMaterialID,
CurrentVariant.AttachmentItem.SkinVariations[NewSkinIndex].Skin);
}
}
else
{
`log("Out of bounds skin index for"@CurrentVariant.MeshName);
@ -243,6 +315,18 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
}
}
else
{
if (bIsFirstPerson)
{
if (KFP.FirstPersonAttachments[PawnAttachmentIndex] != none)
{
for (i = 0; i < KFP.FirstPersonAttachments[PawnAttachmentIndex].GetNumElements(); i++)
{
KFP.FirstPersonAttachments[PawnAttachmentIndex].SetMaterial(i, none);
}
}
}
else
{
// Use material specified in the mesh asset
for( i=0; i < KFP.ThirdPersonAttachments[PawnAttachmentIndex].GetNumElements(); i++ )
@ -251,27 +335,20 @@ static final function SetAttachmentSkinMaterial( KFCharacterInfo_Human C,
}
}
}
}
}
/** Called on owning client to change a cosmetic attachment or on other clients via replication */
static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
byte CurrentAttachmentMeshIndex,
byte CurrentAttachmentSkinIndex,
int CurrentAttachmentMeshIndex,
int CurrentAttachmentSkinIndex,
KFPawn KFP,
optional KFPlayerReplicationInfo KFPRI )
KFPlayerReplicationInfo KFPRI,
optional bool bIsFirstPerson )
{
local string CharAttachmentMeshName;
local name CharAttachmentSocketName;
local bool bIsSkeletalAttachment;
local StaticMesh CharAttachmentStaticMesh;
local SkeletalMesh CharacterAttachmentSkelMesh;
local float MaxDrawDistance;
local StaticMeshComponent StaticAttachment;
local SkeletalMeshComponent SkeletalAttachment;
local SkeletalMeshSocket AttachmentSocket;
local vector AttachmentLocationRelativeToSocket, AttachmentScaleRelativeToSocket;
local rotator AttachmentRotationRelativeToSocket;
local int AttachmentSlotIndex;
local SkeletalMeshComponent AttachmentMesh;
if (KFP.WorldInfo.NetMode == NM_DedicatedServer)
{
@ -281,21 +358,27 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
// Clear any previously attachments for the same slot
//DetachConflictingAttachments(CurrentAttachmentMeshIndex, KFP, KFPRI);
// Get a slot where this attachment could fit
AttachmentSlotIndex = C.GetAttachmentSlotIndex(CurrentAttachmentMeshIndex, KFP);
AttachmentSlotIndex = GetAttachmentSlotIndex(C, CurrentAttachmentMeshIndex, KFP, KFPRI);
if (AttachmentSlotIndex == INDEX_NONE)
{
return;
}
// Since cosmetic attachments are optional, do not choose index 0 if none is
// specified unlike the the head and body meshes
if ( C.CosmeticVariants.length > 0 &&
CurrentAttachmentMeshIndex < C.CosmeticVariants.length )
if ( C.CosmeticVariants.Length > 0 &&
CurrentAttachmentMeshIndex < C.CosmeticVariants.Length )
{
if (KFPRI.StartLoadCosmeticContent(C, ECOSMETICTYPE_Attachment, CurrentAttachmentMeshIndex))
{
return;
}
// Cache values from character info
CharAttachmentMeshName = C.GetMeshByIndex(CurrentAttachmentMeshIndex);
CharAttachmentSocketName = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.SocketName;
MaxDrawDistance = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.MaxDrawDistance;
AttachmentLocationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeTranslation;
AttachmentRotationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeRotation;
AttachmentScaleRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeScale;
bIsSkeletalAttachment = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.bIsSkeletalAttachment;
CharAttachmentMeshName = bIsFirstPerson ? C.Get1pMeshByIndex(CurrentAttachmentMeshIndex) : C.GetMeshByIndex(CurrentAttachmentMeshIndex);
CharAttachmentSocketName = bIsFirstPerson ? C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.SocketName1p : C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.SocketName;
AttachmentMesh = bIsFirstPerson ? KFP.ArmsMesh : KFP.Mesh;
// If previously attached and we could have changed outfits (e.g. local player UI) then re-validate
// required skeletal mesh socket. Must be after body mesh DLO, but before AttachComponent.
@ -308,49 +391,127 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
}
}
// Set First Person Cosmetic if mesh exists for it.
if(CharAttachmentMeshName != "")
{
// Set Cosmetic Mesh
SetAttachmentMesh(C, CurrentAttachmentMeshIndex, AttachmentSlotIndex, CharAttachmentMeshName, CharAttachmentSocketName, AttachmentMesh, KFP, bIsFirstPerson);
}
else
{
// Make sure to clear out attachment if we're replacing with nothing.
if(bIsFirstPerson)
{
KFP.FirstPersonAttachments[AttachmentSlotIndex] = none;
KFP.FirstPersonAttachmentSocketNames[AttachmentSlotIndex] = '';
}
}
// Set Cosmetic Skin
SetAttachmentSkinMaterial(
C,
AttachmentSlotIndex,
C.CosmeticVariants[CurrentAttachmentMeshIndex],
CurrentAttachmentSkinIndex,
KFP,
bIsFirstPerson);
}
// Treat `CLEARED_ATTACHMENT_INDEX as special value (for client detachment)
if( CurrentAttachmentMeshIndex == `CLEARED_ATTACHMENT_INDEX )
{
C.RemoveAttachmentMeshAndSkin(AttachmentSlotIndex, KFP, KFPRI);
}
}
static final function SetAttachmentMesh(KFCharacterInfo_Human C, int CurrentAttachmentMeshIndex, int AttachmentSlotIndex, string CharAttachmentMeshName, name CharAttachmentSocketName, SkeletalMeshComponent PawnMesh, KFPawn KFP, bool bIsFirstPerson = false)
{
local StaticMeshComponent StaticAttachment;
local SkeletalMeshComponent SkeletalAttachment;
local bool bIsSkeletalAttachment;
local StaticMesh CharAttachmentStaticMesh;
local SkeletalMesh CharacterAttachmentSkelMesh;
local float MaxDrawDistance;
local SkeletalMeshSocket AttachmentSocket;
local vector AttachmentLocationRelativeToSocket, AttachmentScaleRelativeToSocket;
local rotator AttachmentRotationRelativeToSocket;
MaxDrawDistance = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.MaxDrawDistance;
AttachmentLocationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeTranslation;
AttachmentRotationRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeRotation;
AttachmentScaleRelativeToSocket = C.CosmeticVariants[CurrentAttachmentMeshIndex].RelativeScale;
bIsSkeletalAttachment = C.CosmeticVariants[CurrentAttachmentMeshIndex].AttachmentItem.bIsSkeletalAttachment;
//`log("AttachmentLocationRelativeToSocket: x="$AttachmentLocationRelativeToSocket.x@"y="$AttachmentLocationRelativeToSocket.y@"z="$AttachmentLocationRelativeToSocket.z);
// If it is a skeletal attachment, parent anim it to the body mesh
if( bIsSkeletalAttachment )
if (bIsSkeletalAttachment)
{
if( SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none )
if (bIsFirstPerson && (SkeletalMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]) != none))
{
SkeletalAttachment = SkeletalMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]);
}
else if (!bIsFirstPerson && (SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none))
{
SkeletalAttachment = SkeletalMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]);
}
else
{
SkeletalAttachment = new(KFP) class'SkeletalMeshComponent';
SkeletalAttachment = new(KFP) class'KFSkeletalMeshComponent';
if (bIsFirstPerson)
{
C.SetFirstPersonCosmeticAttachment(SkeletalAttachment);
}
SkeletalAttachment.SetActorCollision(false, false);
if(bIsFirstPerson)
{
KFP.FirstPersonAttachments[AttachmentSlotIndex] = SkeletalAttachment;
}
else
{
KFP.ThirdPersonAttachments[AttachmentSlotIndex] = SkeletalAttachment;
}
}
// Load and assign skeletal mesh
CharacterAttachmentSkelMesh = SkeletalMesh(DynamicLoadObject(CharAttachmentMeshName, class'SkeletalMesh'));
SkeletalAttachment.SetSkeletalMesh(CharacterAttachmentSkelMesh);
// Parent animation and LOD transitions to body mesh
SkeletalAttachment.SetParentAnimComponent(KFP.Mesh);
SkeletalAttachment.SetLODParent(KFP.Mesh);
SkeletalAttachment.SetParentAnimComponent(PawnMesh);
SkeletalAttachment.SetLODParent(PawnMesh);
SkeletalAttachment.SetScale(C.DefaultMeshScale);
SkeletalAttachment.SetCullDistance(MaxDrawDistance);
SkeletalAttachment.SetShadowParent(KFP.Mesh);
SkeletalAttachment.SetShadowParent(PawnMesh);
SkeletalAttachment.SetLightingChannels(KFP.PawnLightingChannel);
// Attach
KFP.AttachComponent(SkeletalAttachment);
}
// Otherwise (if static), attach to a socket on the body mesh
else
{
if( StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none )
if (!bIsFirstPerson && (StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]) != none))
{
StaticAttachment = StaticMeshComponent(KFP.ThirdPersonAttachments[AttachmentSlotIndex]);
}
else if (bIsFirstPerson && (StaticMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]) != none))
{
StaticAttachment = StaticMeshComponent(KFP.FirstPersonAttachments[AttachmentSlotIndex]);
}
else
{
StaticAttachment = new(KFP) class'StaticMeshComponent';
StaticAttachment.SetActorCollision(false, false);
if(bIsFirstPerson)
{
KFP.FirstPersonAttachments[AttachmentSlotIndex] = StaticAttachment;
}
else
{
KFP.ThirdPersonAttachments[AttachmentSlotIndex] = StaticAttachment;
}
}
// Load and assign static mesh
CharAttachmentStaticMesh = StaticMesh(DynamicLoadObject(CharAttachmentMeshName, class'StaticMesh'));
@ -363,8 +524,8 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
StaticAttachment.SetLightingChannels(KFP.PawnLightingChannel);
// For static meshes, attach to given socket
AttachmentSocket = KFP.mesh.GetSocketByName(CharAttachmentSocketName);
KFP.mesh.AttachComponent(
AttachmentSocket = PawnMesh.GetSocketByName(CharAttachmentSocketName);
PawnMesh.AttachComponent(
StaticAttachment,
AttachmentSocket.BoneName,
AttachmentSocket.RelativeLocation + AttachmentLocationRelativeToSocket,
@ -372,22 +533,13 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
AttachmentSocket.RelativeScale * AttachmentScaleRelativeToSocket);
}
// Update the pawn's attachment metadata
KFP.ThirdPersonAttachmentBitMask = KFP.ThirdPersonAttachmentBitMask | (1 << AttachmentSlotIndex);
KFP.ThirdPersonAttachmentSocketNames[AttachmentSlotIndex] = CharAttachmentSocketName;
SetAttachmentSkinMaterial(
C,
AttachmentSlotIndex,
C.CosmeticVariants[CurrentAttachmentMeshIndex],
CurrentAttachmentSkinIndex,
KFP);
}
// Treat `CLEARED_ATTACHMENT_INDEX as special value (for client detachment)
if( CurrentAttachmentMeshIndex == `CLEARED_ATTACHMENT_INDEX )
if(bIsFirstPerson)
{
C.RemoveAttachmentMeshAndSkin(AttachmentSlotIndex, KFP, KFPRI);
KFP.FirstPersonAttachmentSocketNames[AttachmentSlotIndex] = CharAttachmentSocketName;
}
else
{
KFP.ThirdPersonAttachmentSocketNames[AttachmentSlotIndex] = CharAttachmentSocketName;
}
}
@ -395,7 +547,7 @@ static final function SetAttachmentMeshAndSkin( KFCharacterInfo_Human C,
* Removes any attachments that exist in the same socket or have overriding cases
* Network: Local Player
*/
static final function DetachConflictingAttachments( KFCharacterInfo_Human C, byte NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI)
static final function DetachConflictingAttachments( KFCharacterInfo_Human C, int NewAttachmentMeshIndex, KFPawn KFP, optional KFPlayerReplicationInfo KFPRI)
{
local name NewAttachmentSocketName;
local int i, CurrentAttachmentIdx;
@ -409,7 +561,7 @@ static final function DetachConflictingAttachments( KFCharacterInfo_Human C, byt
NewAttachmentMeshIndex < C.CosmeticVariants.length )
{
// The socket that this attachment requires
NewAttachmentSocketName = C.CosmeticVariants[NewAttachmentMeshIndex].SocketName;
NewAttachmentSocketName = C.CosmeticVariants[NewAttachmentMeshIndex].AttachmentItem.SocketName;
for( i=0; i < `MAX_COSMETIC_ATTACHMENTS; i++ )
{
@ -448,13 +600,14 @@ static final function SetFirstPersonArmsFromArch( KFCharacterInfo_Human C, KFPaw
local MaterialInstanceConstant M;
local ExtPlayerReplicationInfo EPRI;
local bool bCustom;
local int AttachmentIdx, CosmeticMeshIdx;
EPRI = ExtPlayerReplicationInfo(KFPRI);
if ( KFPRI == none )
{
`Warn("Does not have a KFPRI" @ C);
return;
}
EPRI = ExtPlayerReplicationInfo(KFPRI);
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// First person arms mesh and skin are based on body mesh & skin.
@ -462,7 +615,22 @@ static final function SetFirstPersonArmsFromArch( KFCharacterInfo_Human C, KFPaw
C.SetArmsMeshAndSkin(
bCustom ? EPRI.CustomCharacter.BodyMeshIndex : KFPRI.RepCustomizationInfo.BodyMeshIndex,
bCustom ? EPRI.CustomCharacter.BodySkinIndex : KFPRI.RepCustomizationInfo.BodySkinIndex,
KFP);
KFP,
KFPRI);
for (AttachmentIdx = 0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++)
{
CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx];
if (CosmeticMeshIdx != `CLEARED_ATTACHMENT_INDEX && CosmeticMeshIdx != INDEX_NONE)
{
// Attach all saved attachments to the character
SetAttachmentMeshAndSkin(
C,
CosmeticMeshIdx,
bCustom ? EPRI.CustomCharacter.AttachmentSkinIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentSkinIndices[AttachmentIdx],
KFP, KFPRI, true);
}
}
// Hack fix for a material bug on KF2
if( bCustom && KFP.ArmsMesh.SkeletalMesh!=None && KFP.ArmsMesh.GetMaterial(0)!=None )
@ -471,3 +639,44 @@ static final function SetFirstPersonArmsFromArch( KFCharacterInfo_Human C, KFPaw
CloneMIC(M);
}
}
static function int GetAttachmentSlotIndex(
KFCharacterInfo_Human C,
int CurrentAttachmentMeshIndex,
KFPawn KFP,
KFPlayerReplicationInfo KFPRI)
{
local int AttachmentIdx,CosmeticMeshIdx;
local ExtPlayerReplicationInfo EPRI;
local bool bCustom;
if( KFPRI == None )
{
`warn("GetAttachmentSlotIndex - NO KFPRI");
return INDEX_NONE;
}
EPRI = ExtPlayerReplicationInfo(KFPRI);
bCustom = (EPRI!=None ? EPRI.UsesCustomChar() : false);
// Return the next available attachment index or the index that matches this mesh
for( AttachmentIdx = 0; AttachmentIdx < `MAX_COSMETIC_ATTACHMENTS; AttachmentIdx++ )
{
CosmeticMeshIdx = bCustom ? EPRI.CustomCharacter.AttachmentMeshIndices[AttachmentIdx] : KFPRI.RepCustomizationInfo.AttachmentMeshIndices[AttachmentIdx];
if( CosmeticMeshIdx == INDEX_NONE || CosmeticMeshIdx == CurrentAttachmentMeshIndex )
{
return AttachmentIdx;
}
}
return INDEX_NONE;
}
static function bool IsAttachmentAvailable(KFCharacterInfo_Human C, const out AttachmentVariants Attachment, Pawn PreviewPawn)
{
if ( Attachment.AttachmentItem.SocketName != '' && PreviewPawn.Mesh.GetSocketByName(Attachment.AttachmentItem.SocketName) == None )
{
return false;
}
return true;
}

View File

@ -14,6 +14,7 @@ function UpdatePerk()
{
local int CurrentPerkLevel,CurrentPerkEXP;
local Ext_PerkBase CurrentPerk;
local GFxObject PerkIconObject;
if( ExPC == none || ExPC.ActivePerkManager==None || ExPC.ActivePerkManager.CurrentPerk==None )
return;
@ -26,7 +27,11 @@ function UpdatePerk()
if( ( ExLastPerkClass != CurrentPerk.Class ) || ( LastPerkLevel != CurrentPerkLevel ) )
{
CurPerkPath = CurrentPerk.GetPerkIconPath(CurrentPerkLevel);
SetString("playerPerkIcon" , CurPerkPath);
PerkIconObject = CreateObject("Object");
PerkIconObject.SetString("perkIcon", CurPerkPath);
SetObject("playerPerkIcon", PerkIconObject);
SetInt("playerPerkXPPercent", CurrentPerk.GetProgressPercent() * 100.f );
if( LastPerkLevel != CurrentPerkLevel && ExLastPerkClass==CurrentPerk.Class )
{

View File

@ -15,6 +15,7 @@ var bool bWaitingCharList,bIsCustomChar;
function InitializeMenu( KFGFxMoviePlayer_Manager InManager )
{
super(KFGFxObject_Menu).InitializeMenu(InManager);
CheckForCustomizationPawn( GetPC() );
LocalizeText();
EmoteList = class'ExtEmoteList'.static.GetEmoteArray();
InitCharacterMenu();
@ -66,9 +67,8 @@ function OnOpen()
if( PC == none )
return;
// @hack: moved from KFGfxMoviePlayer_Manager because this causes a crash while
// bink (e.g. KFII-25456) are playing. Don't use HandleInputAxis with Bink! (for now) :)
GetGameViewportClient().HandleInputAxis = OnAxisModified;
CheckForCustomizationPawn( PC );
//GetGameViewportClient().HandleInputAxis = OnAxisModified;
if ( PC.PlayerReplicationInfo.bReadyToPlay && PC.WorldInfo.GRI.bMatchHasBegun )
{
@ -77,6 +77,21 @@ function OnOpen()
}
}
/** The customization pawn won't exist if this menu was opened mid-match */
function CheckForCustomizationPawn( PlayerController PC )
{
local KFPlayerController KFPC;
if( PC.Pawn == None || (!PC.Pawn.IsAliveAndWell() && KFPawn_Customization(PC.Pawn) == None) )
{
KFPC = KFPlayerController( PC );
if( KFPC != None )
{
KFPC.SpawnMidGameCustomizationPawn();
}
}
}
function LocalizeText()
{
local GFxObject LocalizedObject;
@ -104,7 +119,7 @@ simulated function CharListRecieved()
function UpdateEmoteList()
{
local byte ItemIndex, i;
local int ItemIndex, i;
local GFxObject DataProvider, SlotObject;
local string TexturePath;
@ -135,7 +150,7 @@ function UpdateEmoteList()
function UpdateCharacterList()
{
local byte i, ItemIndex;
local int i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local string TexturePath;
@ -208,7 +223,7 @@ final function string GetMenuNameStr( string ObjName )
function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants> Outfits, string DataArrayString)
{
local byte i, ItemIndex;
local int i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local string TexturePath, OutfitName;
local OutfitVariants Outfit;
@ -216,7 +231,7 @@ function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants>
ItemIndex = 0;
DataProvider = CreateArray();
for (i = 0; i < Outfits.length; i++)
for (i = 0; i < Outfits.Length; i++)
{
Outfit = Outfits[i];
@ -247,7 +262,7 @@ function UpdateMeshList(string OutfitKey, string SkinKey, array<OutfitVariants>
function SkinVariant UpdateOutfitVariants(string OutfitKey, string KeyName, out array<SkinVariant> SkinVariations, int OutfitIndex, out GFxObject MeshObject)
{
local byte i, ItemIndex;
local int i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local SkinVariant Skin;
local SkinVariant FirstSkin;
@ -284,41 +299,36 @@ function SkinVariant UpdateOutfitVariants(string OutfitKey, string KeyName, out
function UpdateAttachmentsList(array<AttachmentVariants> Attachments)
{
local byte i, ItemIndex;
local int i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local string TexturePath;
local AttachmentVariants Variant;
local Pawn MyPawn;
local SkinVariant FirstSkin;
local string AttachmentName;
ItemIndex = 0;
DataProvider = CreateArray();
MyPawn = GetPC().Pawn;
// Insert blank object
SlotObject = CreateObject( "Object" );
SlotObject.SetString("label", class'KFGFxMenu_Gear'.Default.NoneString);
SlotObject.SetString("source", "img://"$class'KFGFxMenu_Gear'.Default.ClearImagePath);
SlotObject.SetString("label", class'KFGFxMenu_Gear'.default.NoneString);
SlotObject.SetString("source", "img://"$class'KFGFxMenu_Gear'.default.ClearImagePath);
SlotObject.SetInt("ItemIndex", INDEX_NONE);
SlotObject.SetBool("enabled", true);
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
for (i = 0; i < Attachments.length; i++)
for (i = 0; i < Attachments.Length; i++)
{
Variant = Attachments[i];
AttachmentName = Localize(string(Variant.AttachmentItem.Name), class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString);
if( bIsCustomChar )
AttachmentName = GetMenuNameStr(Variant.MeshName);
if ( InStr(AttachmentName, "?INT?") != -1 )
continue;
if ( class'ExtCharacterInfo'.static.IsAttachmentAvailable(CurrentCharInfo, Variant, MyPawn) )
{
SlotObject = CreateObject( "Object" );
SlotObject.SetInt("ItemIndex", i);
FirstSkin = UpdateCosmeticVariants( class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentSkinKey, Variant.AttachmentItem, i, SlotObject );
if( string(FirstSkin.UITexture) == "Bad" )
continue;
FirstSkin = UpdateCosmeticVariants( class'KFGFxMenu_Gear'.default.AttachmentKey, class'KFGFxMenu_Gear'.default.AttachmentSkinKey, Variant.AttachmentItem, i, SlotObject );
AttachmentName = bIsCustomChar ? GetMenuNameStr(Variant.MeshName) : Localize(string(Variant.AttachmentItem.Name), class'KFGFxMenu_Gear'.default.AttachmentKey, class'KFGFxMenu_Gear'.default.KFCharacterInfoString);
SlotObject.SetString("label", AttachmentName);
SlotObject.SetBool("enabled", true);
TexturePath = "img://"$PathName(FirstSkin.UITexture);
@ -327,13 +337,14 @@ function UpdateAttachmentsList(array<AttachmentVariants> Attachments)
DataProvider.SetElementObject(ItemIndex, SlotObject);
ItemIndex++;
}
}
SetObject("attachmentsArray", DataProvider);
}
function SkinVariant UpdateCosmeticVariants(string OutfitKey, string KeyName, KFCharacterAttachment Attachment, int OutfitIndex, out GFxObject MeshObject)
{
local byte i, ItemIndex;
local int i, ItemIndex;
local GFxObject DataProvider, SlotObject;
local SkinVariant Skin;
local SkinVariant FirstSkin;
@ -372,20 +383,35 @@ function SetCurrentCharacterButtons()
{
local bool bCustom;
local GFxObject DataObject;
local byte CharacterIndex, HeadMeshIndex, HeadSkinIndex, BodyMeshIndex, BodySkinIndex;
bCustom = ExtPRI.UsesCustomChar();
DataObject = CreateObject("Object");
CharacterIndex = ExtPRI.RepCustomizationInfo.CharacterIndex;
HeadMeshIndex = ExtPRI.RepCustomizationInfo.HeadMeshIndex;
HeadSkinIndex = ExtPRI.RepCustomizationInfo.HeadSkinIndex;
BodyMeshIndex = ExtPRI.RepCustomizationInfo.BodyMeshIndex;
BodySkinIndex = ExtPRI.RepCustomizationInfo.BodySkinIndex;
if( bCustom )
{
CharacterIndex = ExtPRI.CustomCharacter.CharacterIndex;
HeadMeshIndex = ExtPRI.CustomCharacter.HeadMeshIndex;
HeadSkinIndex = ExtPRI.CustomCharacter.HeadSkinIndex;
BodyMeshIndex = ExtPRI.CustomCharacter.BodyMeshIndex;
BodySkinIndex = ExtPRI.CustomCharacter.BodySkinIndex;
}
DataObject.SetString( "selectedCharacter", (bIsCustomChar ? Repl(string(CurrentCharInfo.Name),"_"," ") : Localize(CharInfoPath, "CharacterName", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString)) );
DataObject.SetString( "characterBio", (bIsCustomChar ? Repl(CurrentCharInfo.ArmMeshPackageName,"|","\n") : Localize(CharInfoPath, "Description", class'KFGFxMenu_Gear'.Default.KFCharacterInfoString)) );
DataObject.SetInt( "selectedCharacterIndex", bCustom ? ExtPRI.CustomCharacter.CharacterIndex : ExtPRI.RepCustomizationInfo.CharacterIndex );
DataObject.SetInt( "selectedCharacterIndex", CharacterIndex );
SetObject( "selectedCharacter", DataObject);
//set head
SetGearButtons(bCustom ? ExtPRI.CustomCharacter.HeadMeshIndex : ExtPRI.RepCustomizationInfo.HeadMeshIndex, bCustom ? ExtPRI.CustomCharacter.HeadSkinIndex : ExtPRI.RepCustomizationInfo.HeadSkinIndex, class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, class'KFGFxMenu_Gear'.Default.HeadFunctionKey);
SetGearButtons(HeadMeshIndex, HeadSkinIndex, class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, class'KFGFxMenu_Gear'.Default.HeadFunctionKey);
//set body
SetGearButtons(bCustom ? ExtPRI.CustomCharacter.BodyMeshIndex : ExtPRI.RepCustomizationInfo.BodyMeshIndex, bCustom ? ExtPRI.CustomCharacter.BodySkinIndex : ExtPRI.RepCustomizationInfo.BodySkinIndex, class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, class'KFGFxMenu_Gear'.Default.BodyFunctionKey);
SetGearButtons(BodyMeshIndex, BodySkinIndex, class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, class'KFGFxMenu_Gear'.Default.BodyFunctionKey);
//set attachments
SetAttachmentButtons(class'KFGFxMenu_Gear'.Default.AttachmentKey, class'KFGFxMenu_Gear'.Default.AttachmentFunctionKey);
@ -416,7 +442,7 @@ function SetEmoteButton()
}
/** Update the labels for our gear buttons */
function SetGearButtons(byte MeshIndex, byte SkinIndex, string MeshKey, string SkinKey, string sectionFunctionName)
function SetGearButtons(int MeshIndex, int SkinIndex, string MeshKey, string SkinKey, string sectionFunctionName)
{
local string SectionPath;
local string CurrentMesh;
@ -444,6 +470,7 @@ function SetGearButtons(byte MeshIndex, byte SkinIndex, string MeshKey, string S
SkinName = GetMenuName(CurrentCharInfo.BodyVariants[MeshIndex].SkinVariations[SkinIndex].Skin);
MeshName = GetMenuNameStr(CurrentCharInfo.BodyVariants[MeshIndex].MeshName);
}
DataObject.SetString( sectionFunctionName, MeshName @"\n" @SkinName );
}
else
@ -465,9 +492,8 @@ function SetGearButtons(byte MeshIndex, byte SkinIndex, string MeshKey, string S
/** Update the labels for our currently equipped attachments */
function SetAttachmentButtons(string AttachmentMeshKey, string sectionFunctionName)
{
local string FinishedString;
local GFxObject DataObject;
local byte i, AttachmentIndex;
local int i, AttachmentIndex;
local bool bCustom;
if( bWaitingCharList )
@ -481,16 +507,14 @@ function SetAttachmentButtons(string AttachmentMeshKey, string sectionFunctionNa
AttachmentIndex = bCustom ? ExtPRI.CustomCharacter.AttachmentMeshIndices[i] : ExtPRI.RepCustomizationInfo.AttachmentMeshIndices[i];
if( AttachmentIndex == `CLEARED_ATTACHMENT_INDEX )
{
FinishedString $= "----"$"\n";
DataObject.SetString("selectedAttachment_"$i, "----");
}
else
{
FinishedString $= (bIsCustomChar ? GetMenuNameStr(CurrentCharInfo.CosmeticVariants[AttachmentIndex].MeshName) : Localize(string(CurrentCharInfo.CosmeticVariants[AttachmentIndex].AttachmentItem.Name), AttachmentMeshKey, class'KFGFxMenu_Gear'.Default.KFCharacterInfoString)$"\n");
DataObject.SetString("selectedAttachment_"$i, bIsCustomChar ? GetMenuNameStr(CurrentCharInfo.CosmeticVariants[AttachmentIndex].MeshName) : Localize(string(CurrentCharInfo.CosmeticVariants[AttachmentIndex].AttachmentItem.Name), AttachmentMeshKey, class'KFGFxMenu_Gear'.default.KFCharacterInfoString));
}
}
DataObject.SetString( sectionFunctionName, FinishedString );
SetObject( sectionFunctionName, DataObject);
}
@ -500,7 +524,7 @@ event OnClose()
super.OnClose();
GetGameViewportClient().HandleInputAxis = none;
//GetGameViewportClient().HandleInputAxis = none;
if ( class'WorldInfo'.static.IsMenuLevel() )
{
@ -531,7 +555,7 @@ event bool OnAxisModified( int ControllerId, name Key, float Delta, float DeltaT
// ActionScript Callbacks
//==============================================================
function Callback_Emote(byte Index)
function Callback_Emote(int Index)
{
local KFPlayerController KFPC;
@ -588,13 +612,13 @@ function Callback_HeadCamera()
KFPlayerCamera( GetPC().PlayerCamera ).CustomizationCam.SetBodyView( 1 );
}
function Callback_Character(byte Index)
function Callback_Character(int Index)
{
ExtPRI.ChangeCharacter(Index,!ExtPRI.UsesCustomChar());
UpdateGear();
}
function Callback_Head( byte MeshIndex, byte SkinIndex )
function Callback_Head( int MeshIndex, int SkinIndex )
{
if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server.
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
@ -602,7 +626,7 @@ function Callback_Head( byte MeshIndex, byte SkinIndex )
SetGearButtons(MeshIndex, SkinIndex, class'KFGFxMenu_Gear'.Default.HeadMeshKey, class'KFGFxMenu_Gear'.Default.HeadSkinKey, class'KFGFxMenu_Gear'.Default.HeadFunctionKey);
}
function Callback_Body( byte MeshIndex, byte SkinIndex )
function Callback_Body( int MeshIndex, int SkinIndex )
{
if( !ExtPRI.UsesCustomChar() ) // Force client to setup custom character now for this server.
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
@ -617,7 +641,7 @@ function Callback_Body( byte MeshIndex, byte SkinIndex )
SetGearButtons(MeshIndex, SkinIndex, class'KFGFxMenu_Gear'.Default.BodyMeshKey, class'KFGFxMenu_Gear'.Default.BodySkinKey, class'KFGFxMenu_Gear'.Default.BodyFunctionKey);
}
function Callback_Attachment( byte MeshIndex, byte SkinIndex )
function Callback_Attachment( int MeshIndex, int SkinIndex )
{
local int SlotIndex;
local KFPawn KFP;
@ -626,14 +650,19 @@ function Callback_Attachment( byte MeshIndex, byte SkinIndex )
ExtPRI.ChangeCharacter(ExtPRI.RepCustomizationInfo.CharacterIndex,true);
KFP = KFPawn(GetPC().Pawn);
if( KFP!=None )
if( KFP!=None && ExtPRI!=None )
{
if( MeshIndex==`CLEARED_ATTACHMENT_INDEX )
ExtPRI.RemoveAttachments();
else
{
class'ExtCharacterInfo'.Static.DetachConflictingAttachments(CurrentCharInfo, MeshIndex, KFP, ExtPRI);
SlotIndex = CurrentCharInfo.GetAttachmentSlotIndex(MeshIndex, KFP);
SlotIndex = class'ExtCharacterInfo'.Static.GetAttachmentSlotIndex(CurrentCharInfo, MeshIndex, KFP, ExtPRI);
if(SlotIndex == INDEX_NONE)
{
return;
}
ExtPRI.UpdateCustomization(CO_Attachment, MeshIndex, SkinIndex, SlotIndex);
}

View File

@ -103,8 +103,8 @@ defaultproperties
WidgetBindings.Add((WidgetName="PlayerBackpackWidget",WidgetClass=class'ExtHUD_PlayerBackpack'))
WidgetBindings.Remove((WidgetName="WaveInfoContainer",WidgetClass=class'KFGFxHUD_WaveInfo'))
WidgetBindings.Add((WidgetName="WaveInfoContainer",WidgetClass=class'ExtHUD_WaveInfo'))
WidgetBindings.Remove((WidgetName="bossHealthBar", WidgetClass=class'KFGFxWidget_BossHealthBar'))
WidgetBindings.Add((WidgetName="bossHealthBar", WidgetClass=class'ExtWidget_BossHealthBar'))
//WidgetBindings.Remove((WidgetName="bossHealthBar", WidgetClass=class'KFGFxWidget_BossHealthBar'))
//WidgetBindings.Add((WidgetName="bossHealthBar", WidgetClass=class'ExtWidget_BossHealthBar'))
WidgetBindings.Remove((WidgetName="WeaponSelectContainer",WidgetClass=class'KFGFxHUD_WeaponSelectWidget'))
WidgetBindings.Add((WidgetName="WeaponSelectContainer",WidgetClass=class'ExtHUD_WeaponSelectWidget'))
}

View File

@ -144,7 +144,7 @@ reliable client event ReceiveLocalizedMessage( class<LocalMessage> Message, opti
Super.ReceiveLocalizedMessage(Message,Switch,RelatedPRI_1,RelatedPRI_2,OptionalObject);
}
function AddZedKill( class<KFPawn_Monster> MonsterClass, byte Difficulty, class<DamageType> DT )
function AddZedKill( class<KFPawn_Monster> MonsterClass, byte Difficulty, class<DamageType> DT, bool bKiller )
{
// Stats.
if( ActivePerkManager!=None )
@ -603,7 +603,7 @@ simulated function CancelConnection()
else class'Engine'.Static.GetEngine().GameViewport.ConsoleCommand("Disconnect");
}
function NotifyLevelUp(class<KFPerk> PerkClass, byte PerkLevel);
function NotifyLevelUp(class<KFPerk> PerkClass, byte PerkLevel, byte NewPrestigeLevel);
function ShowBossNameplate( KFInterface_MonsterBoss KFBoss, optional string PlayerName)
{
@ -1167,6 +1167,16 @@ state Dead
}
}
exec function RequestSwitchTeam()
{
ConsoleCommand("disconnect");
}
exec function SwitchTeam()
{
ConsoleCommand("disconnect");
}
defaultproperties
{
InputClass=Class'ExtPlayerInput'

View File

@ -12,10 +12,9 @@ struct FMyCustomChar // Now without constant.
structdefaultproperties
{
CharacterIndex=255
AttachmentMeshIndices[0]=255
AttachmentMeshIndices[1]=255
AttachmentMeshIndices[2]=255
AttachmentMeshIndices[0]=`CLEARED_ATTACHMENT_INDEX
AttachmentMeshIndices[1]=`CLEARED_ATTACHMENT_INDEX
AttachmentMeshIndices[2]=`CLEARED_ATTACHMENT_INDEX
}
};
@ -658,7 +657,7 @@ final function SaveCustomCharacter( ExtSaveDataBase Data )
c = 0;
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{
if( CustomCharacter.AttachmentMeshIndices[i]!=255 )
if( CustomCharacter.AttachmentMeshIndices[i]!=`CLEARED_ATTACHMENT_INDEX )
++c;
}
@ -668,7 +667,7 @@ final function SaveCustomCharacter( ExtSaveDataBase Data )
// Write attachments.
for( i=0; i<`MAX_COSMETIC_ATTACHMENTS; ++i )
{
if( CustomCharacter.AttachmentMeshIndices[i]!=255 )
if( CustomCharacter.AttachmentMeshIndices[i]!=`CLEARED_ATTACHMENT_INDEX )
{
Data.SaveInt(i);
Data.SaveInt(CustomCharacter.AttachmentMeshIndices[i]);
@ -748,6 +747,16 @@ static final function DummySaveChar( ExtSaveDataBase Data )
Data.SaveStr("");
}
simulated function Texture2D GetCurrentIconToDisplay()
{
if(CurrentVoiceCommsRequest == VCT_NONE && ECurrentPerk != none)
{
return ECurrentPerk.default.PerkIcon;
}
return class'KFLocalMessage_VoiceComms'.default.VoiceCommsIcons[CurrentVoiceCommsRequest];
}
// Set admin levels without having to hard-reference to this mod.
event BeginState(Name N)
{

View File

@ -21,7 +21,7 @@ function GFxObject RefreshSlot( int SlotIndex, KFPlayerReplicationInfo KFPRI )
local bool bIsLeader;
local bool bIsMyPlayer;
local ExtPlayerController EPC;
local GFxObject PlayerInfoObject;
local GFxObject PlayerInfoObject, PerkIconObject;
local ExtPlayerReplicationInfo EPRI;
PlayerInfoObject = CreateObject("Object");
@ -42,8 +42,11 @@ function GFxObject RefreshSlot( int SlotIndex, KFPlayerReplicationInfo KFPRI )
PlayerInfoObject.SetBool("myPlayer", bIsMyPlayer);
if( ExtMemberSlots[SlotIndex].PerkClass != none )
{
PerkIconObject = CreateObject("Object");
PerkIconObject.SetString("perkIcon", ExtMemberSlots[SlotIndex].PerkClass.static.GetPerkIconPath(EPRI.ECurrentPerkLevel));
PlayerInfoObject.SetObject("perkImageSource", PerkIconObject);
PlayerInfoObject.SetString("perkLevel", string(EPRI.ECurrentPerkLevel));
PlayerInfoObject.SetString("perkIconPath", ExtMemberSlots[SlotIndex].PerkClass.static.GetPerkIconPath(EPRI.ECurrentPerkLevel));
}
if( !bIsMyPlayer )
{
@ -76,5 +79,4 @@ function GFxObject RefreshSlot( int SlotIndex, KFPlayerReplicationInfo KFPRI )
DefaultProperties
{
PlayerSlots=12
}

View File

@ -105,7 +105,7 @@ simulated final function bool IsWeaponOnPerk( KFWeapon W )
simulated static function string GetPerkIconPath( int Level )
{
return "img://"$PathName(Default.PerkIcon);
return "img://"$PathName(default.PerkIcon);
}
simulated function PostBeginPlay()

View File

@ -446,26 +446,47 @@ final function RenderProgress()
function DrawHUD()
{
local KFPawn KFPH;
local KFPawn_Human H;
local KFPawn_Human KFPH;
local KFPawn_Scripted KFPS;
local vector ViewLocation, ViewVector, PlayerPartyInfoLocation, PawnLocation;
local rotator ViewRotation;
local array<PlayerReplicationInfo> VisibleHumanPlayers;
local array<sHiddenHumanPawnInfo> HiddenHumanPlayers;
local float ThisDot,DotScale;
local vector TargetLocation;
local Actor LocActor;
local KFPawn_Monster M;
local vector V;
local bool bSpec;
local array<PlayerReplicationInfo> VisibleHumanPlayers;
local array<sHiddenHumanPawnInfo> HiddenHumanPlayers;
local vector ViewLocation,PawnLocation;
local rotator ViewRotation;
Super(HUD).DrawHUD();
// Draw weapon HUD underneath everything else
if( KFPlayerOwner != none && KFPlayerOwner.Pawn != none && KFPlayerOwner.Pawn.Weapon != none )
{
KFPlayerOwner.Pawn.Weapon.DrawHUD( self, Canvas );
}
super.DrawHUD();
// Cache GRI
if( KFGRI == none )
{
KFGRI = KFGameReplicationInfo( WorldInfo.GRI );
}
// Don't draw canvas HUD in cinematic mode
if( KFPlayerOwner != none && KFPlayerOwner.bCinematicMode )
{
return;
}
LocActor = KFPlayerOwner.ViewTarget != none ? KFPlayerOwner.ViewTarget : KFPlayerOwner;
// Draw the crosshair for casual mode
if( bDrawCrosshair || bForceDrawCrosshair || (KFPlayerOwner != none && KFPlayerOwner.GetTeamNum() == 255) )
if( KFPlayerOwner != none && (bDrawCrosshair || bForceDrawCrosshair || KFPlayerOwner.GetTeamNum() == 255) )
{
if( KFPlayerOwner != none && !KFPlayerOwner.bCinematicMode )
DrawCrosshair();
}
// Friendly player status
bSpec = (PlayerOwner.PlayerReplicationInfo!=None && PlayerOwner.PlayerReplicationInfo.bOnlySpectator);
if( bSpec || PlayerOwner.GetTeamNum()==0 )
{
@ -476,67 +497,80 @@ function DrawHUD()
{
KFPlayerOwner.GetPlayerViewPoint( ViewLocation, ViewRotation );
}
ViewVector = vector(ViewRotation);
Canvas.EnableStencilTest(true);
foreach WorldInfo.AllPawns(class'KFPawn', KFPH)
foreach WorldInfo.AllPawns( class'KFPawn_Human', KFPH )
{
if( KFPH == None )
continue;
H = KFPawn_Human(KFPH);
if( KFPH.PlayerReplicationInfo!=None && KFPH.PlayerReplicationInfo.Team!=None && KFPH.PlayerReplicationInfo.Team.TeamIndex==0 )
if( KFPH.IsAliveAndWell() && KFPH != KFPlayerOwner.Pawn && KFPH.Mesh.SkeletalMesh != none && KFPH.Mesh.bAnimTreeInitialised )
{
V = KFPH.Location + KFPH.MTO_PhysSmoothOffset + KFPH.CylinderComponent.CollisionHeight * vect(0,0,1);
ThisDot = Normal(V - PLCameraLoc) dot Normal(PLCameraDir);
if( KFPH.IsAliveAndWell() && KFPH != PlayerOwner.Pawn)
PlayerPartyInfoLocation = KFPH.Mesh.GetPosition() + ( KFPH.CylinderComponent.CollisionHeight * vect(0,0,1) );
if(`TimeSince(KFPH.Mesh.LastRenderTime) < 0.2f && Normal(PlayerPartyInfoLocation - ViewLocation) dot ViewVector > 0.f )
{
if((WorldInfo.TimeSeconds - KFPH.Mesh.LastRenderTime) < 0.4f && (ThisDot > 0 && ThisDot < 1.0) )
if( DrawFriendlyHumanPlayerInfo(KFPH) )
{
if( H!=None )
{
DrawFriendlyHUD(H);
VisibleHumanPlayers.AddItem( H.PlayerReplicationInfo );
VisibleHumanPlayers.AddItem( KFPH.PlayerReplicationInfo );
}
else DrawMonsterHUD(KFPH);
}
else if( H != None )
else
{
HiddenHumanPlayers.Insert( 0, 1 );
HiddenHumanPlayers[0].HumanPawn = H;
HiddenHumanPlayers[0].HumanPRI = H.PlayerReplicationInfo;
HiddenHumanPlayers[0].HumanPawn = KFPH;
HiddenHumanPlayers[0].HumanPRI = KFPH.PlayerReplicationInfo;
}
}
else
{
HiddenHumanPlayers.Insert( 0, 1 );
HiddenHumanPlayers[0].HumanPawn = KFPH;
HiddenHumanPlayers[0].HumanPRI = KFPH.PlayerReplicationInfo;
}
}
}
foreach WorldInfo.AllPawns(class'KFPawn_Scripted', KFPS)
{
if (KFPS.ShouldShowOnHUD())
{
PlayerPartyInfoLocation = KFPS.Mesh.GetPosition() + (KFPS.CylinderComponent.CollisionHeight * vect(0,0,1));
DrawScriptedPawnInfo(KFPS, Normal(PlayerPartyInfoLocation - ViewLocation) dot ViewVector, `TimeSince(KFPS.Mesh.LastRenderTime) < 0.2f);
}
}
if( !KFGRI.bHidePawnIcons )
{
// Draw hidden players
CheckAndDrawHiddenPlayerIcons( VisibleHumanPlayers, HiddenHumanPlayers );
// Draw last remaining zeds
CheckAndDrawRemainingZedIcons();
Canvas.EnableStencilTest(false);
//Draw our current objective location
if(KFGRI.CurrentObjective != none && KFGRI.ObjectiveInterface != none)
{
KFGRI.ObjectiveInterface.DrawHUD(self, Canvas);
if( bSpec )
TargetLocation = KFGRI.ObjectiveInterface.GetIconLocation();
ThisDot = Normal((TargetLocation + (class'KFPawn_Human'.default.CylinderComponent.CollisionHeight * vect(0, 0, 1))) - ViewLocation) dot ViewVector;
if (ThisDot > 0 &&
KFGRI.ObjectiveInterface.ShouldShowObjectiveHUD() &&
(!KFGRI.ObjectiveInterFace.HasObjectiveDrawDistance() || VSizeSq(TargetLocation - LocActor.Location) < MaxDrawDistanceObjective))
{
// Draw zed health bars.
foreach WorldInfo.AllPawns(class'KFPawn_Monster', M)
{
ThisDot = (PLCameraDir Dot (M.Location + M.CylinderComponent.CollisionHeight * vect(0,0,1))) - PLCameraDot;
if( ThisDot>0 && ThisDot<8000.f && M.IsAliveAndWell() && M.PlayerReplicationInfo!=None && M!=PlayerOwner.Pawn && (WorldInfo.TimeSeconds - M.Mesh.LastRenderTime) < 0.4f )
DrawFriendlyHUDZ(M);
DrawObjectiveHUD();
}
}
}
Canvas.EnableStencilTest(false);
}
}
else if( KFPawn_Monster(PlayerOwner.Pawn)!=None )
{
// Draw human health auras.
DotScale = Canvas.ClipX*0.2f;
foreach WorldInfo.AllPawns(class'KFPawn_Human', H)
foreach WorldInfo.AllPawns(class'KFPawn_Human', KFPH)
{
PawnLocation = H.Location;
PawnLocation = KFPH.Location;
if( IsZero( PawnLocation ) )
{
@ -544,12 +578,12 @@ function DrawHUD()
}
ThisDot = (PLCameraDir Dot PawnLocation) - PLCameraDot;
if( H.IsAliveAndWell() && ThisDot>0.f && ThisDot<10000.f )
if( KFPH.IsAliveAndWell() && ThisDot>0.f && ThisDot<10000.f )
{
V = Canvas.Project(PawnLocation);
if( V.X<-100 || V.X>(Canvas.SizeX+100) || V.Y<-100 || V.Y>(Canvas.SizeY+100) )
continue;
Canvas.DrawColor = GetHPColorScale(H);
Canvas.DrawColor = GetHPColorScale(KFPH);
if( PlayerOwner.FastTrace(PawnLocation,PLCameraLoc) )
ThisDot*=1.75f;
ThisDot = (DotScale/ThisDot)*350.f;
@ -560,6 +594,7 @@ function DrawHUD()
if( !class'ExtPlayerController'.Default.bHideNameBeacons )
{
Canvas.EnableStencilTest(true);
// Draw zed health bars.
foreach WorldInfo.AllPawns(class'KFPawn_Monster', M)
{
@ -567,52 +602,9 @@ function DrawHUD()
if( ThisDot>0 && ThisDot<8000.f && M.IsAliveAndWell() && M.PlayerReplicationInfo!=None && M!=PlayerOwner.Pawn && (WorldInfo.TimeSeconds - M.Mesh.LastRenderTime) < 0.4f )
DrawFriendlyHUDZ(M);
}
Canvas.EnableStencilTest(false);
}
}
Canvas.Font = GetFontSizeIndex(0);
DrawActorOverlays(PLCameraLoc, PLCameraRot);
}
function DrawHiddenHumanPlayerIcon( PlayerReplicationInfo PRI, vector IconWorldLocation )
{
local vector ScreenPos;
local float IconSizeMult;
local KFPlayerReplicationInfo KFPRI;
local Texture2D PlayerIcon;
local Color PerkColor;
local ExtPlayerReplicationInfo ExtPRI;
local Texture2D HumanIcon;
KFPRI = KFPlayerReplicationInfo(PRI);
if( KFPRI == None )
return;
// Project world pos to canvas
ScreenPos = Canvas.Project( IconWorldLocation + vect(0,0,2.2f) * class'KFPAwn_Human'.default.CylinderComponent.CollisionHeight );
// Fudge by icon size
IconSizeMult = PlayerStatusIconSize * FriendlyHudScale * 0.5f;
ScreenPos.X -= IconSizeMult;
ScreenPos.Y -= IconSizeMult;
if( ScreenPos.X < 0 || ScreenPos.X > Canvas.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.SizeY )
{
return;
}
ExtPRI = ExtPlayerReplicationInfo(KFPRI);
if( ExtPRI == None )
return;
HumanIcon = ExtPRI.ECurrentPerk != None ? ExtPRI.ECurrentPerk.Default.PerkIcon : GenericHumanIconTexture;
PlayerIcon = PlayerOwner.GetTeamNum() == 0 ? HumanIcon : GenericHumanIconTexture;
PerkColor = ExtPRI.HUDPerkColor;
// Draw human icon
Canvas.SetDrawColor( PerkColor.R, PerkColor.G, PerkColor.B, PerkColor.A );
Canvas.SetPos( ScreenPos.X, ScreenPos.Y );
Canvas.DrawTile( PlayerIcon, PlayerStatusIconSize * FriendlyHudScale, PlayerStatusIconSize * FriendlyHudScale, 0, 0, 256, 256 );
}
simulated static final function color GetHPColorScale( Pawn P )
@ -642,8 +634,10 @@ simulated function DrawFriendlyHUDZ( KFPawn_Monster KFPH )
local vector ScreenPos, TargetLocation;
local FontRenderInfo MyFontRenderInfo;
local float FontScale;
local byte FadeAlpha;
MyFontRenderInfo = Canvas.CreateFontRenderInfo( true );
FadeAlpha = DrawToDistance(KFPH);
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale;
BarHeight = FMin(8.f * (float(Canvas.SizeX) / 1024.f), 8.f) * FriendlyHudScale;
@ -656,16 +650,19 @@ simulated function DrawFriendlyHUDZ( KFPawn_Monster KFPH )
//Draw health bar
Percentage = float(KFPH.Health) / float(KFPH.HealthMax);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, FadeAlpha);
//Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
Canvas.SetDrawColorStruct(DrawToDistance(KFPH, PlayerBarTextColor));
Canvas.DrawColor = PlayerBarTextColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 2);
Canvas.DrawText( KFPH.PlayerReplicationInfo.PlayerName,,FontScale,FontScale, MyFontRenderInfo );
}
simulated function DrawFriendlyHUD( KFPawn_Human KFPH )
simulated function bool DrawFriendlyHumanPlayerInfo( KFPawn_Human KFPH )
{
local float Percentage;
local float BarHeight, BarLength;
@ -673,91 +670,122 @@ simulated function DrawFriendlyHUD( KFPawn_Human KFPH )
local ExtPlayerReplicationInfo KFPRI;
local FontRenderInfo MyFontRenderInfo;
local float FontScale;
local float ResModifier;
local float PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, PerkIconSize;
local color CurrentArmorColor, CurrentHealthColor, TextColor;
local string S;
local byte FadeAlpha;
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
KFPRI = ExtPlayerReplicationInfo(KFPH.PlayerReplicationInfo);
if( KFPRI == none )
return;
{
return false;
}
FadeAlpha = DrawToDistance(KFPH);
MyFontRenderInfo = Canvas.CreateFontRenderInfo( true );
BarLength = FMin(PlayerStatusBarLengthMax * (Canvas.ClipX / 1024.f), PlayerStatusBarLengthMax) * ResModifier;
BarHeight = FMin(8.f * (Canvas.ClipX / 1024.f), 8.f) * ResModifier;
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale;
BarHeight = FMin(8.f * (float(Canvas.SizeX) / 1024.f), 8.f) * FriendlyHudScale;
TargetLocation = KFPH.Location + vect(0,0,1) * KFPH.GetCollisionHeight() * 1.2;
ScreenPos = Canvas.Project(TargetLocation);
if( ScreenPos.X < 0 || ScreenPos.X > Canvas.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.SizeY )
return;
//Draw health bar
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax),1.f);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, true);
//Draw armor bar
Percentage = FMin(float(KFPH.Armor) / float(KFPH.MaxArmor),1.f);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight, ArmorColor);
TargetLocation = KFPH.Mesh.GetPosition() + ( KFPH.CylinderComponent.CollisionHeight * vect(0,0,2.5f) );
ScreenPos = Canvas.Project( TargetLocation );
if( ScreenPos.X < 0 || ScreenPos.X > Canvas.ClipX || ScreenPos.Y < 0 || ScreenPos.Y > Canvas.ClipY )
{
return false;
}
//Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
S = KFPRI.GetHumanReadableName();
// drop shadow for player name text
S = KFPRI.PlayerName;
if( KFPRI.bBot )
{
S = S$" (Bot)";
Canvas.DrawColor = KFPRI.HUDPerkColor;
TextColor = KFPRI.HUDPerkColor;
}
else if( KFPRI.ShowAdminName() ) // Admin info.
{
S = S$" ("$KFPRI.GetAdminNameAbr()$")";
Canvas.DrawColor = KFPRI.GetAdminColorC();
TextColor = KFPRI.GetAdminColorC();
}
else Canvas.DrawColor = WhiteColor;
else TextColor = PlayerBarTextColor;
if( bMeAdmin && KFPRI.FixedData>0 )
{
Canvas.SetDrawColor(255,0,0,255);
S $= " -"$KFPRI.GetDesc();
TextColor = MakeColor(255,0,0,255);
S @= "-"$KFPRI.GetDesc();
}
Canvas.DrawColor = DrawToDistance(KFPH, Canvas.DrawColor);
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 3);
Canvas.DrawText( S,,FontScale,FontScale, MyFontRenderInfo );
TextColor.A = FadeAlpha;
if( KFPRI.ECurrentPerk!=none )
Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y + 8);
Canvas.DrawText(S, , FontScale, FontScale, MyFontRenderInfo);
Canvas.DrawColor = TextColor;
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + 7);
Canvas.DrawText(S, , FontScale, FontScale, MyFontRenderInfo);
//Draw armor bar
Percentage = FMin(float(KFPH.Armor) / float(KFPH.MaxArmor), 100);
CurrentArmorColor = ClassicPlayerInfo ? ClassicArmorColor : ArmorColor;
CurrentArmorColor.A = FadeAlpha;
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight + (36 * FontScale * ResModifier), CurrentArmorColor, FadeAlpha);
//Draw health bar
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax), 100);
CurrentHealthColor = ClassicPlayerInfo ? ClassicHealthColor : HealthColor;
CurrentHealthColor.A = FadeAlpha;
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight * 2 + (36 * FontScale * ResModifier), CurrentHealthColor, FadeAlpha, true);
if( KFPRI.ECurrentPerk == None )
{
//draw perk icon
Canvas.DrawColor = DrawToDistance(KFPH, KFPRI.HUDPerkColor);
Canvas.SetPos(ScreenPos.X - (BarLength * 0.75), ScreenPos.Y - BarHeight * 2);
Canvas.DrawRect(PlayerStatusIconSize*FriendlyHudScale,PlayerStatusIconSize*FriendlyHudScale,KFPRI.ECurrentPerk.default.PerkIcon);
return false;
}
// drop shadow for perk name text
Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f) + 1, ScreenPos.Y + BarHeight * 3 + (36 * FontScale * ResModifier) + 1);
Canvas.DrawText(KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName, , FontScale, FontScale, MyFontRenderInfo);
//Draw perk level and name text
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y + BarHeight);
Canvas.DrawText( KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName,,FontScale,FontScale, MyFontRenderInfo );
Canvas.DrawColor = PlayerBarTextColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(ScreenPos.X - (BarLength * 0.5f), ScreenPos.Y + BarHeight * 3 + (36 * FontScale * ResModifier));
Canvas.DrawText(KFPRI.GetPerkLevelStr()@KFPRI.ECurrentPerk.default.PerkName, , FontScale, FontScale, MyFontRenderInfo);
// drop shadow for perk icon
Canvas.DrawColor = PlayerBarShadowColor;
Canvas.DrawColor.A = FadeAlpha;
PerkIconSize = PlayerStatusIconSize * ResModifier;
PerkIconPosX = ScreenPos.X - (BarLength * 0.5f) - PerkIconSize + 1;
PerkIconPosY = ScreenPos.Y + (36 * FontScale * ResModifier) + 1;
SupplyIconPosX = ScreenPos.X + (BarLength * 0.5f) + 1;
SupplyIconPosY = PerkIconPosY + 4 * ResModifier;
DrawPerkIcons(KFPH, PerkIconSize, PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, true);
if( KFPRI.HasSupplier!=None )
{
Canvas.DrawColor = DrawToDistance(KFPH, (KFPlayerOwner.Pawn==None || KFPRI.CanUseSupply(KFPlayerOwner.Pawn)) ? SupplierUsableColor : SupplierActiveColor);
Canvas.SetPos( ScreenPos.X + BarLength * 0.5f, ScreenPos.Y - BarHeight * 2 );
Canvas.DrawRect( PlayerStatusIconSize*FriendlyHudScale, PlayerStatusIconSize*FriendlyHudScale, KFPRI.HasSupplier.Default.SupplyIcon);
}
}
else if( KFPRI.bBot && KFPRI.CurrentPerkClass!=none )
{
//draw perk icon
Canvas.SetPos(ScreenPos.X - (BarLength * 0.75), ScreenPos.Y - BarHeight * 2);
Canvas.DrawRect(PlayerStatusIconSize*FriendlyHudScale,PlayerStatusIconSize*FriendlyHudScale,KFPRI.CurrentPerkClass.default.PerkIcon);
Canvas.DrawColor = PlayerBarIconColor;
Canvas.DrawColor.A = FadeAlpha;
PerkIconPosX = ScreenPos.X - (BarLength * 0.5f) - PerkIconSize;
PerkIconPosY = ScreenPos.Y + (36 * FontScale * ResModifier);
SupplyIconPosX = ScreenPos.X + (BarLength * 0.5f);
SupplyIconPosY = PerkIconPosY + 4 * ResModifier;
DrawPerkIcons(KFPH, PerkIconSize, PerkIconPosX, PerkIconPosY, SupplyIconPosX, SupplyIconPosY, false);
//Draw name text
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y + BarHeight);
Canvas.DrawText( KFPRI.CurrentPerkClass.default.PerkName,,FontScale,FontScale, MyFontRenderInfo );
}
return true;
}
simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float BarLength, float BarHeight, float XPos, float YPos, Color BarColor, optional bool bDrawingHealth )
simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float BarLength, float BarHeight, float XPos, float YPos, Color BarColor, byte FadeAlpha, optional bool bDrawingHealth )
{
//background for status bar
Canvas.SetDrawColorStruct(DrawToDistance(P, PlayerBarBGColor));
Canvas.DrawColor = PlayerBarBGColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength, BarHeight, 0, 0, 32, 32);
@ -767,7 +795,8 @@ simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float
BarHeight-=2;
//Forground for status bar.
Canvas.SetDrawColorStruct(DrawToDistance(P, BarColor));
Canvas.DrawColor = BarColor;
Canvas.DrawColor.A = FadeAlpha;
Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32);
@ -777,11 +806,76 @@ simulated final function DrawPlayerInfoBar( KFPawn P, float BarPercentage, float
XPos+=(BarLength * BarPercentage);
BarPercentage = FMin(float(ExtHumanPawn(P).RepRegenHP) / float(P.HealthMax),1.f-BarPercentage);
Canvas.DrawColor = DrawToDistance(P, MakeColor(255,128,128,255));
Canvas.DrawColor = MakeColor(255,128,128,FadeAlpha);
Canvas.SetPos(XPos, YPos);
Canvas.DrawTileStretched(PlayerStatusBarBGTexture, BarLength * BarPercentage, BarHeight, 0, 0, 32, 32);
}
}
simulated function DrawPerkIcons(KFPawn_Human KFPH, float PerkIconSize, float PerkIconPosX, float PerkIconPosY, float SupplyIconPosX, float SupplyIconPosY, bool bDropShadow)
{
local byte PrestigeLevel;
local ExtPlayerReplicationInfo KFPRI;
local color TempColor;
local float ResModifier;
KFPRI = ExtPlayerReplicationInfo(KFPH.PlayerReplicationInfo);
if (KFPRI == none)
{
return;
}
PrestigeLevel = KFPRI.GetActivePerkPrestigeLevel();
ResModifier = WorldInfo.static.GetResolutionBasedHUDScale() * FriendlyHudScale;
if (KFPRI.CurrentVoiceCommsRequest == VCT_NONE && KFPRI.ECurrentPerk != none && PrestigeLevel > 0)
{
Canvas.SetPos(PerkIconPosX, PerkIconPosY);
Canvas.DrawTile(KFPRI.ECurrentPerk.default.BasePerk.default.PrestigeIcons[PrestigeLevel - 1], PerkIconSize, PerkIconSize, 0, 0, 256, 256);
}
if (PrestigeLevel > 0)
{ //icon slot in image is not centered
Canvas.SetPos(PerkIconPosX + (PerkIconSize * (1 - PrestigeIconScale)) / 2, PerkIconPosY + PerkIconSize * 0.05f);
Canvas.DrawTile(KFPRI.GetCurrentIconToDisplay(), PerkIconSize * PrestigeIconScale, PerkIconSize * PrestigeIconScale, 0, 0, 256, 256);
}
else
{
Canvas.SetPos(PerkIconPosX, PerkIconPosY);
Canvas.DrawTile(KFPRI.GetCurrentIconToDisplay(), PerkIconSize, PerkIconSize, 0, 0, 256, 256);
}
if (KFPRI.PerkSupplyLevel > 0 && KFPRI.ECurrentPerk.default.BasePerk.static.GetInteractIcon() != none)
{
if (!bDropShadow)
{
if (KFPRI.PerkSupplyLevel == 2)
{
if (KFPRI.bPerkPrimarySupplyUsed && KFPRI.bPerkSecondarySupplyUsed)
{
TempColor = SupplierActiveColor;
}
else if (KFPRI.bPerkPrimarySupplyUsed || KFPRI.bPerkSecondarySupplyUsed)
{
TempColor = SupplierHalfUsableColor;
}
else
{
TempColor = SupplierUsableColor;
}
}
else if (KFPRI.PerkSupplyLevel == 1)
{
TempColor = KFPRI.bPerkPrimarySupplyUsed ? SupplierActiveColor : SupplierUsableColor;
}
Canvas.SetDrawColorStruct(TempColor);
}
Canvas.SetPos(SupplyIconPosX, SupplyIconPosY); //offset so that supplier icon shows up on the correct side of the player's health bar
Canvas.DrawTile(KFPRI.ECurrentPerk.default.BasePerk.static.GetInteractIcon(), (PlayerStatusIconSize * 0.75) * ResModifier, (PlayerStatusIconSize * 0.75) * ResModifier, 0, 0, 256, 256);
}
}
simulated function DrawMonsterHUD( KFPawn KFPH )
{
local float Percentage;
@ -790,11 +884,13 @@ simulated function DrawMonsterHUD( KFPawn KFPH )
local Ext_T_MonsterPRI PRI;
local FontRenderInfo MyFontRenderInfo;
local float FontScale;
local byte FadeAlpha;
PRI = Ext_T_MonsterPRI(KFPH.PlayerReplicationInfo);
if( PRI==None )
return;
FadeAlpha = DrawToDistance(KFPH);
MyFontRenderInfo = Canvas.CreateFontRenderInfo( true );
BarLength = FMin(PlayerStatusBarLengthMax * (float(Canvas.SizeX) / 1024.f), PlayerStatusBarLengthMax) * FriendlyHudScale;
@ -808,12 +904,12 @@ simulated function DrawMonsterHUD( KFPawn KFPH )
//Draw health bar
Percentage = FMin(float(KFPH.Health) / float(KFPH.HealthMax),1.f);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor);
DrawPlayerInfoBar(KFPH, Percentage, BarLength, BarHeight, ScreenPos.X - (BarLength *0.5f), ScreenPos.Y, HealthColor, FadeAlpha);
//Draw player name (Top)
FontScale = class'KFGameEngine'.Static.GetKFFontScale() * FriendlyHudScale;
Canvas.Font = class'KFGameEngine'.Static.GetKFCanvasFont();
Canvas.DrawColor = DrawToDistance(KFPH, (PRI.OwnerPRI==PlayerOwner.PlayerReplicationInfo ? MakeColor(32,250,32,255) : MakeColor(250,32,32,255)));
Canvas.DrawColor = PRI.OwnerPRI==PlayerOwner.PlayerReplicationInfo ? MakeColor(32,250,32,FadeAlpha) : MakeColor(250,32,32,FadeAlpha);
Canvas.SetPos(ScreenPos.X - (BarLength *0.5f), ScreenPos.Y - BarHeight * 3);
Canvas.DrawText( PRI.PlayerName,,FontScale,FontScale, MyFontRenderInfo );
@ -866,18 +962,16 @@ simulated function DrawPetInfo()
}
}
function Color DrawToDistance(KFPawn Pawn, Color DrawColor)
function byte DrawToDistance(Actor A, optional float StartAlpha=255.f, optional float MinAlpha=90.f)
{
local float Dist, fZoom;
Dist = VSize(Pawn.Location - PLCameraLoc) * 0.5;
Dist = VSize(A.Location - PLCameraLoc);
if ( Dist <= HealthBarFullVisDist || PlayerOwner.PlayerReplicationInfo.bOnlySpectator )
fZoom = 1.0;
else fZoom = FMax(1.0 - (Dist - HealthBarFullVisDist) / (HealthBarCutoffDist - HealthBarFullVisDist), 0.0);
DrawColor.A = Clamp(255 * fZoom, 90, 255);
return DrawColor;
return Clamp(StartAlpha * fZoom, MinAlpha, StartAlpha);
}
final function AddNumberMsg( int Amount, vector Pos, byte Type )
@ -1059,13 +1153,13 @@ simulated final function DrawItemsList()
Canvas.TextSize(NewItems[i].Item,XS,YS,FontScale,FontScale);
if( NewItems[i].Icon!=None )
/*if( NewItems[i].Icon!=None )
{
Canvas.SetPos(XPos-YSize,YPos);
Canvas.DrawRect(YSize,YSize,NewItems[i].Icon);
XS = XPos-(YSize*1.1)-XS;
}
else XS = XPos-XS;
else */XS = XPos-XS;
Canvas.SetPos(XS,YPos);
Canvas.DrawText("New Item:",,FontScale,FontScale);

View File

@ -0,0 +1,5 @@
Class SRPerkManager extends ExtPerkManager;
defaultproperties
{
}

View File

@ -49,6 +49,7 @@ var int LastWaveNum,NumWaveSwitches;
var ExtSpawnPointHelper SpawnPointer;
var bool bRespawnCheck,bSpecialSpawn,bGameHasEnded,bIsPostGame;
var config bool bKillMessages,bDamageMessages,bEnableMapVote,bNoAdminCommands,bNoWebAdmin,bNoBoomstickJumping,bDumpXMLStats,bRagdollFromFall,bRagdollFromMomentum,bRagdollFromBackhit,bAddCountryTags;
var config bool bServerPerksMode;
function PostBeginPlay()
{
@ -426,7 +427,7 @@ final function GT_PlayerKilled( Controller Killer, Controller Killed, class<Dama
if( KFG!=None && KFPC != none && MonsterPawn!=none )
{
//Chris: We have to do it earlier here because we need a damage type
KFPC.AddZedKill( MonsterPawn.class, KFG.GameDifficulty, damageType );
KFPC.AddZedKill( MonsterPawn.class, KFG.GameDifficulty, damageType, false );
if( KFPC.ActivePerkManager!=none && KFPC.ActivePerkManager.CanEarnSmallRadiusKillXP(damageType) )
KFG.CheckForBerserkerSmallRadiusKill( MonsterPawn, KFPC );